Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ A PDF of the working specification for Outlook rules files (.rwz) files can be f

```swift
let data = Data(contentsOfFile: "<path-to-file>.rwz")!
let file = try OutlookRulesFile(data: data)
let file = try OutlookRules(data: data)
print(file.rules.count)
print(file.rules[0].name)
print(file.rules[0].enabled)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// OutlookRulesFile.swift
// OutlookRules.swift
//
//
// Created by Hugh Bellamy on 28/07/2020.
Expand All @@ -8,8 +8,9 @@
import DataStream
import Foundation

public struct OutlookRulesFile: CustomDebugStringConvertible {
public var rules: [Rule] = []
public struct OutlookRules: CustomDebugStringConvertible {
public let rules: [Rule]
private var header: RulesHeader
private var footer: RulesFooter?
public var templateDirectory: String {
get {
Expand All @@ -21,6 +22,7 @@ public struct OutlookRulesFile: CustomDebugStringConvertible {

public init(rules: [Rule] = []) {
self.rules = rules
self.header = RulesHeader(numberOfRules: 0)
self.footer = RulesFooter()
}

Expand All @@ -30,7 +32,7 @@ public struct OutlookRulesFile: CustomDebugStringConvertible {
}

public init(dataStream: inout DataStream) throws {
let header = try RulesHeader(dataStream: &dataStream)
self.header = try RulesHeader(dataStream: &dataStream)

var rules: [Rule] = []
rules.reserveCapacity(Int(header.numberOfRules))
Expand All @@ -48,18 +50,20 @@ public struct OutlookRulesFile: CustomDebugStringConvertible {
}
}

public func getData() -> Data {
public func getData(version: OutlookRulesVersion? = nil) -> Data {
let version = version ?? self.header.version

var dataStream = OutputDataStream()

let header = RulesHeader(numberOfRules: UInt16(rules.count))
header.write(to: &dataStream)
header.write(to: &dataStream, version: version)

for (index, rule) in rules.enumerated() {
rule.write(to: &dataStream, index: index)
rule.write(to: &dataStream, index: index, version: version)
}

let footer = RulesFooter()
footer.write(to: &dataStream)
footer.write(to: &dataStream, version: version)

return dataStream.data
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/OutlookRulesReader/OutlookRulesReadError.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// OutlookRulesFileError.swift
// OutlookRulesError.swift
//
//
// Created by Hugh Bellamy on 28/07/2020.
Expand Down
284 changes: 37 additions & 247 deletions Sources/OutlookRulesReader/Rule.swift

Large diffs are not rendered by default.

262 changes: 254 additions & 8 deletions Sources/OutlookRulesReader/RuleElement.swift

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions Sources/OutlookRulesReader/RuleElementData.swift
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
//
// RuleElementData.swift
// RuleParameter.swift
//
//
// Created by Hugh Bellamy on 28/07/2020.
//

import DataStream

public protocol RuleElementData {
public protocol RuleParameter {
var dataSize: UInt32 { get }
init(dataStream: inout DataStream, version: OutlookRulesVersion) throws
func write(to dataStream: inout OutputDataStream)
func write(to dataStream: inout OutputDataStream, version: OutlookRulesVersion)
}
2 changes: 1 addition & 1 deletion Sources/OutlookRulesReader/RuleElementIdentifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

public enum RuleElementIdentifier: UInt32 {
/// "type of messages to which this rule applies"
case applyCondition = 0x00000190
case eventFlags = 0x00000190

/// Unknown
case unknown0x64 = 0x00000064
Expand Down
2 changes: 1 addition & 1 deletion Sources/OutlookRulesReader/RulesFooter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ internal struct RulesFooter {
assert(dataStream.remainingCount == 0)
}

public func write(to dataStream: inout OutputDataStream) {
public func write(to dataStream: inout OutputDataStream, version: OutlookRulesVersion) {
/// Template Directory Length (4 bytes)
dataStream.write(UInt32(templateDirectory.count), endianess: .littleEndian)

Expand Down
2 changes: 1 addition & 1 deletion Sources/OutlookRulesReader/RulesHeader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ internal struct RulesHeader {
self.numberOfRules = try dataStream.read(endianess: .littleEndian)
}

public func write(to dataStream: inout OutputDataStream) {
public func write(to dataStream: inout OutputDataStream, version: OutlookRulesVersion) {
if let signature = signature {
/// Signature (4 bytes)
dataStream.write(signature, endianess: .littleEndian)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,13 @@ public struct DocumentProperty {
self.unknown2 = try dataStream.read(endianess: .littleEndian)
}

public func write(to dataStream: inout OutputDataStream) {
public func write(to dataStream: inout OutputDataStream, version: OutlookRulesVersion) {
/// Field (variable)
UTF16String(value: field).write(to: &dataStream)
if version >= .outlook2002 {
UTF16String(value: field).write(to: &dataStream)
} else {
ASCIIString(value: field).write(to: &dataStream)
}

/// Tag (4 bytes)
tag.write(to: &dataStream)
Expand All @@ -141,7 +145,11 @@ public struct DocumentProperty {
dataStream.write(rawStringMatchType, endianess: .littleEndian)

/// String Value (variable)
UTF16String(value: stringValue).write(to: &dataStream)
if version >= .outlook2002 {
UTF16String(value: stringValue).write(to: &dataStream)
} else {
ASCIIString(value: stringValue).write(to: &dataStream)
}

/// Number Match Type (4 bytes)
dataStream.write(rawNumberMatchType, endianess: .littleEndian)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
//
// ThroughAccountCondition.swift
// AccountParameter.swift
//
//
// Created by Hugh Bellamy on 29/07/2020.
//

import DataStream

public struct ThroughAccountRuleElementData: RuleElementData {
public struct AccountParameter: RuleParameter {
public var dataSize: UInt32 {
var baseSize: UInt32 = 8
var baseSize: UInt32 = 4
baseSize += UTF16String(value: accountName).dataSize
baseSize += ASCIIString(value: accountName).dataSize
return baseSize
}

public var extended: UInt32 = 1
public var reserved: UInt32 = 0
public var accountName: String
public var unknown: String
Expand All @@ -26,12 +25,6 @@ public struct ThroughAccountRuleElementData: RuleElementData {
}

public init(dataStream: inout DataStream, version: OutlookRulesVersion) throws {
/// Extended (4 bytes)
self.extended = try dataStream.read(endianess: .littleEndian)
guard self.extended == 0x00000001 else {
throw OutlookRulesReadError.corrupted
}

/// Reserved (4 bytes)
self.reserved = try dataStream.read(endianess: .littleEndian)

Expand All @@ -42,10 +35,7 @@ public struct ThroughAccountRuleElementData: RuleElementData {
self.unknown = try ASCIIString(dataStream: &dataStream).value
}

public func write(to dataStream: inout OutputDataStream) {
/// Extended (4 bytes)
dataStream.write(extended, endianess: .littleEndian)

public func write(to dataStream: inout OutputDataStream, version: OutlookRulesVersion) {
/// Reserved (4 bytes)
dataStream.write(reserved, endianess: .littleEndian)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// SenderInSpecifiedAddressBookRuleElementData.swift
// AddressBookParameter.swift
//
//
// Created by Hugh Bellamy on 28/07/2020.
Expand All @@ -8,15 +8,14 @@
import DataStream
import MAPI

public struct SenderInSpecifiedAddressBookRuleElementData: RuleElementData {
public struct AddressBookParameter: RuleParameter {
public var dataSize: UInt32 {
var baseSize: UInt32 = 12
var baseSize: UInt32 = 4
baseSize += UInt32(FlatEntry(entryID: entryId).dataSize)
baseSize += UTF16String(value: name).dataSize
return baseSize
}

public var extended: UInt32 = 1
public var reserved: UInt32 = 0
public var entryId: EntryID
public var name: String
Expand All @@ -27,12 +26,6 @@ public struct SenderInSpecifiedAddressBookRuleElementData: RuleElementData {
}

public init(dataStream: inout DataStream, version: OutlookRulesVersion) throws {
/// Extended (4 bytes)
self.extended = try dataStream.read(endianess: .littleEndian)
guard self.extended == 0x00000001 else {
throw OutlookRulesReadError.corrupted
}

/// Reserved (4 bytes)
self.reserved = try dataStream.read(endianess: .littleEndian)

Expand All @@ -43,10 +36,7 @@ public struct SenderInSpecifiedAddressBookRuleElementData: RuleElementData {
self.name = try UTF16String(dataStream: &dataStream).value
}

public func write(to dataStream: inout OutputDataStream) {
/// Extended (4 bytes)
dataStream.write(extended, endianess: .littleEndian)

public func write(to dataStream: inout OutputDataStream, version: OutlookRulesVersion) {
/// Reserved (4 bytes)
dataStream.write(reserved, endianess: .littleEndian)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,50 +1,41 @@
//
// PeopleOrPublicGroupList.swift
// AddressParameter.swift
//
//
// Created by Hugh Bellamy on 08/08/2020.
//

import DataStream

public struct PeopleOrPublicGroupListRuleElementData: RuleElementData {
public struct AddressParameter: RuleParameter {
public var dataSize: UInt32 {
let result: UInt32 = 20
let result: UInt32 = 16
for _ in values {
// TODO
}
return result
}

public var extended: UInt32 = 1
public var reserved: UInt32 = 0
public var numberOfValues: UInt32 = 0
public var values: [[UInt16 : Any]] = []
public var unknown1: UInt32 = 1
public var unknown2: UInt32 = 0

public init(values: [[UInt16: Any]]) {
self.numberOfValues = UInt32(values.count)
self.values = values
}

public init(dataStream: inout DataStream, version: OutlookRulesVersion) throws {
/// Extended (4 bytes)
self.extended = try dataStream.read(endianess: .littleEndian)
guard self.extended == 0x00000001 else {
throw OutlookRulesReadError.corrupted
}

/// Reserved (4 bytes)
self.reserved = try dataStream.read(endianess: .littleEndian)

/// Number of Values (4 bytes)
self.numberOfValues = try dataStream.read(endianess: .littleEndian)
let numberOfValues: UInt32 = try dataStream.read(endianess: .littleEndian)

/// Values (variable)
var values: [[UInt16 : Any]] = []
values.reserveCapacity(Int(self.numberOfValues))
for _ in 0..<self.numberOfValues {
values.reserveCapacity(Int(numberOfValues))
for _ in 0..<numberOfValues {
let list = try PropertiesList(dataStream: &dataStream)
values.append(list.properties)
}
Expand All @@ -58,7 +49,7 @@ public struct PeopleOrPublicGroupListRuleElementData: RuleElementData {
self.unknown2 = try dataStream.read(endianess: .littleEndian)
}

public func write(to dataStream: inout OutputDataStream) {
public func write(to dataStream: inout OutputDataStream, version: OutlookRulesVersion) {
// TODO
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
//
// AlertRuleElementData.swift
// AlertParameter.swift
//
//
// Created by Hugh Bellamy on 08/08/2020.
//

import DataStream

public struct AlertRuleElementData: RuleElementData {
public struct AlertParameter: RuleParameter {
public var dataSize: UInt32 {
return 8 + UTF16String(value: name).dataSize
4 + UTF16String(value: name).dataSize
}

public var extended: UInt32 = 1
public var reserved: UInt32 = 0
public var name: String

Expand All @@ -21,23 +20,14 @@ public struct AlertRuleElementData: RuleElementData {
}

public init(dataStream: inout DataStream, version: OutlookRulesVersion) throws {
/// Extended (4 bytes)
self.extended = try dataStream.read(endianess: .littleEndian)
guard self.extended == 0x00000001 else {
throw OutlookRulesReadError.corrupted
}

/// Reserved (4 bytes)
self.reserved = try dataStream.read(endianess: .littleEndian)

/// Name (variable)
self.name = try UTF16String(dataStream: &dataStream).value
}

public func write(to dataStream: inout OutputDataStream) {
/// Extended (4 bytes)
dataStream.write(extended, endianess: .littleEndian)

public func write(to dataStream: inout OutputDataStream, version: OutlookRulesVersion) {
/// Reserved (4 bytes)
dataStream.write(reserved, endianess: .littleEndian)

Expand Down
Loading