diff --git a/enzevalos_iphone.xcodeproj/project.pbxproj b/enzevalos_iphone.xcodeproj/project.pbxproj index 2887ac1fd3a4d5aed723a1e9576e454b23ecc377..81ceb198a6c026f6828923486512295ff595fedf 100644 --- a/enzevalos_iphone.xcodeproj/project.pbxproj +++ b/enzevalos_iphone.xcodeproj/project.pbxproj @@ -399,6 +399,7 @@ 47F867E32052B49800AA832F /* libbz2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libbz2.tbd; path = usr/lib/libbz2.tbd; sourceTree = SDKROOT; }; 48C250BB32BF11B683003BA1 /* Pods-enzevalos_iphone-enzevalos_iphoneUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-enzevalos_iphone-enzevalos_iphoneUITests.debug.xcconfig"; path = "../enzevalos_iphone_workspace/Pods/Target Support Files/Pods-enzevalos_iphone-enzevalos_iphoneUITests/Pods-enzevalos_iphone-enzevalos_iphoneUITests.debug.xcconfig"; sourceTree = "<group>"; }; 66E758F271CD65AB3E5FE7A7 /* Pods-enzevalos_iphoneUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-enzevalos_iphoneUITests.debug.xcconfig"; path = "../enzevalos_iphone_workspace/Pods/Target Support Files/Pods-enzevalos_iphoneUITests/Pods-enzevalos_iphoneUITests.debug.xcconfig"; sourceTree = "<group>"; }; + 670159DF240FB4E800797FA5 /* enzevalos_iphone 9.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "enzevalos_iphone 9.xcdatamodel"; sourceTree = "<group>"; }; 6EBCCD02AD3B95D8317810E2 /* Pods-enzevalos_iphoneTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-enzevalos_iphoneTests.debug.xcconfig"; path = "../enzevalos_iphone_workspace/Pods/Target Support Files/Pods-enzevalos_iphoneTests/Pods-enzevalos_iphoneTests.debug.xcconfig"; sourceTree = "<group>"; }; 71DFE5B9240679E80042019C /* HeaderExtractionValues.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeaderExtractionValues.swift; sourceTree = "<group>"; }; 796D16D79BED5D60B580E602 /* Pods-enzevalos_iphoneUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-enzevalos_iphoneUITests.release.xcconfig"; path = "../enzevalos_iphone_workspace/Pods/Target Support Files/Pods-enzevalos_iphoneUITests/Pods-enzevalos_iphoneUITests.release.xcconfig"; sourceTree = "<group>"; }; @@ -2149,6 +2150,7 @@ A135267F1D955BDF00D3BFE1 /* enzevalos_iphone.xcdatamodeld */ = { isa = XCVersionGroup; children = ( + 670159DF240FB4E800797FA5 /* enzevalos_iphone 9.xcdatamodel */, 4751C6FD2344D169006B2A4D /* enzevalos_iphone 8.xcdatamodel */, 4751C6F0233CE1E4006B2A4D /* enzevalos_iphone 7.xcdatamodel */, A1909719220F887D00FA7B2A /* enzevalos_iphone 6.xcdatamodel */, @@ -2158,7 +2160,7 @@ 47B2318A1F0D458100961B28 /* enzevalos_iphone 2.xcdatamodel */, A13526801D955BDF00D3BFE1 /* enzevalos_iphone.xcdatamodel */, ); - currentVersion = 4751C6FD2344D169006B2A4D /* enzevalos_iphone 8.xcdatamodel */; + currentVersion = 670159DF240FB4E800797FA5 /* enzevalos_iphone 9.xcdatamodel */; path = enzevalos_iphone.xcdatamodeld; sourceTree = "<group>"; versionGroupType = wrapper.xcdatamodel; diff --git a/enzevalos_iphone/DataHandler.swift b/enzevalos_iphone/DataHandler.swift index be2dc7370c4ef75907927ae13f8bfa49d5f36397..3850314e83d900fa481ca1ab1a809aa147b0a6aa 100644 --- a/enzevalos_iphone/DataHandler.swift +++ b/enzevalos_iphone/DataHandler.swift @@ -272,6 +272,20 @@ class DataHandler { } } + func deleteRelatedSecretKeys() { + let keys = findSecretKeys() + let pgp = SwiftPGP() + pgp.deleteSecretKeys() + for key in keys { + if let mails = key.relatedDecryptedMails as? Set<PersistentMail> { + for mail in mails { + mail.relatedSecrectKey = nil + } + } + delete(key: key) + } + } + func deleteMail(with uid: UInt64) { self.deleteNum("PersistentMail", type: "uid", search: uid) } @@ -841,7 +855,7 @@ class DataHandler { } // -------- End handle to, cc, from addresses -------- - func createMail(_ uid: UInt64, sender: MCOAddress?, receivers: [MCOAddress], cc: [MCOAddress], time: Date, received: Bool, subject: String, body: String?, readableAttachments: Set<TempAttachment> = Set<TempAttachment>(), flags: MCOMessageFlag, record: KeyRecord?, autocrypt: Autocrypt?, decryptedData: CryptoObject?, folderPath: String, secretKey: String?, references: [String] = [], mailagent: String? = nil, messageID: String? = nil, encryptedBody: String?, storeEncrypted: Bool = false) -> PersistentMail? { + func createMail(_ uid: UInt64, sender: MCOAddress?, receivers: [MCOAddress], cc: [MCOAddress], time: Date, received: Bool, subject: String, body: String?, readableAttachments: Set<TempAttachment> = Set<TempAttachment>(), flags: MCOMessageFlag, record: KeyRecord?, autocrypt: Autocrypt?, decryptedData: CryptoObject?, folderPath: String, secretKey: String?, references: [String] = [], mailagent: String? = nil, messageID: String? = nil, encryptedBody: String?, storeEncrypted: Bool = false, isKeyImported: Bool = true, attachedSignature: Data? = nil) -> PersistentMail? { guard let sender = sender else { return nil @@ -872,6 +886,7 @@ class DataHandler { } else { mail.body = nil } + // relatedSecretKey mail.secretKey = secretKey mail.folder = myfolder @@ -890,7 +905,7 @@ class DataHandler { mail.unableToDecrypt = false mail.storeEncrypted = storeEncrypted mail.received = received - + mail.attachedSignature = attachedSignature handleFromAddress(sender, fromMail: mail, autocrypt: autocrypt) diff --git a/enzevalos_iphone/OutgoingMail.swift b/enzevalos_iphone/OutgoingMail.swift index 797b0405079748539729f290c501a50d441b889f..6b34d58d34cf1f877d92c51bd9f0c0766c8ada6d 100644 --- a/enzevalos_iphone/OutgoingMail.swift +++ b/enzevalos_iphone/OutgoingMail.swift @@ -46,6 +46,7 @@ class OutgoingMail { private let textContent: String? private var htmlContent: String? = nil private var attachments: [MCOAttachment] = [] + private var attachedSignature: Data? var pgpData: Data? { get { return createEncData() @@ -115,6 +116,7 @@ class OutgoingMail { self.sendEncryptedIfPossible = sendEncryptedIfPossible self.attachments = attachments self.orderReceivers() + self.attachedSignature = IncomingMail.extractPGPSignature(attachment: attachments) } init(mail: PersistentMail){ @@ -129,6 +131,7 @@ class OutgoingMail { self.orderReceivers() self.mail = mail self.loggingMail = mail.isCorrectlySigned //TODO FIX HERE + self.attachedSignature = mail.attachedSignature } func store() -> PersistentMail? { @@ -137,6 +140,7 @@ class OutgoingMail { mail?.decryptedBody = htmlContent mail?.isEncrypted = sendEncryptedIfPossible mail?.isCorrectlySigned = self.loggingMail + mail?.attachedSignature = self.attachedSignature self.mail = mail return mail } diff --git a/enzevalos_iphone/PersistentMail +CoreDataProperties.swift b/enzevalos_iphone/PersistentMail +CoreDataProperties.swift index e032c064af288dbb73d4f397fabe1a365f2f8056..35c3c616bbcd175574ff1fabff7ab03899541778 100644 --- a/enzevalos_iphone/PersistentMail +CoreDataProperties.swift +++ b/enzevalos_iphone/PersistentMail +CoreDataProperties.swift @@ -79,10 +79,20 @@ extension PersistentMail { } } + /** + Default value: True (in case no key was in mail is provided) + True: Provided key in mail body is imported or discareded. + False: No actions have be done yet + */ + @NSManaged public var isKeyImported: Bool /** Please use encryption state */ @NSManaged public var isEncrypted: Bool + /** + Some Mail have the signature attached to them separately + */ + @NSManaged public var attachedSignature: Data? /** This mail is signed but check isSigned, too. We recommand to use signature state @@ -149,7 +159,10 @@ extension PersistentMail { Only for traveler scenario. */ @NSManaged public var decryptedKey: PersistentKey? - + /** + Related secrect Key for mail. + */ + @NSManaged public var relatedSecrectKey: SecretKey? /** Sender mail client. */ diff --git a/enzevalos_iphone/SecretKey+CoreDataProperties.swift b/enzevalos_iphone/SecretKey+CoreDataProperties.swift index 47d468117e3f0405a370242a77bf88c526e708ac..9c3470fad3931cbd50fc232aec613e3d2ec1e7c4 100644 --- a/enzevalos_iphone/SecretKey+CoreDataProperties.swift +++ b/enzevalos_iphone/SecretKey+CoreDataProperties.swift @@ -44,6 +44,10 @@ extension SecretKey { A Set of mails where as the key was used for decryption. */ @NSManaged public var decryptedMails: NSSet? + /** + A Set of mails where the relatedSecrectKey was used for decryption. + */ + @NSManaged public var relatedDecryptedMails: NSSet? } diff --git a/enzevalos_iphone/enzevalos_iphone.xcdatamodeld/.xccurrentversion b/enzevalos_iphone/enzevalos_iphone.xcdatamodeld/.xccurrentversion index b24719e7c69bc07e985d15759e78b50ea73a1a2e..8723d24cbe7999b90840d81bec8c2e4809b58ee6 100644 --- a/enzevalos_iphone/enzevalos_iphone.xcdatamodeld/.xccurrentversion +++ b/enzevalos_iphone/enzevalos_iphone.xcdatamodeld/.xccurrentversion @@ -3,6 +3,6 @@ <plist version="1.0"> <dict> <key>_XCCurrentVersionName</key> - <string>enzevalos_iphone 8.xcdatamodel</string> + <string>enzevalos_iphone 9.xcdatamodel</string> </dict> </plist> diff --git a/enzevalos_iphone/enzevalos_iphone.xcdatamodeld/enzevalos_iphone 9.xcdatamodel/contents b/enzevalos_iphone/enzevalos_iphone.xcdatamodeld/enzevalos_iphone 9.xcdatamodel/contents new file mode 100644 index 0000000000000000000000000000000000000000..a537bc2263e93c6d9eedf4ba3c0983aa767712d7 --- /dev/null +++ b/enzevalos_iphone/enzevalos_iphone.xcdatamodeld/enzevalos_iphone 9.xcdatamodel/contents @@ -0,0 +1,180 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="15702" systemVersion="19D76" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier=""> + <entity name="Account" representedClassName="Account" syncable="YES" codeGenerationType="class"> + <attribute name="archiveFolderPath" attributeType="String"/> + <attribute name="displayName" attributeType="String"/> + <attribute name="draftFolderPath" attributeType="String"/> + <attribute name="inboxFolderPath" attributeType="String"/> + <attribute name="loginName" attributeType="String"/> + <attribute name="prefEnc" optional="YES" attributeType="String"/> + <attribute name="prefMailAdr" optional="YES" attributeType="String"/> + <attribute name="prefSecretKeyID" optional="YES" attributeType="String"/> + <attribute name="sentFolderPath" attributeType="String"/> + <attribute name="trashFolderPath" attributeType="String"/> + <relationship name="aliase" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Mail_Address" inverseName="account" inverseEntity="Mail_Address"/> + <relationship name="imap" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Server" inverseName="imap" inverseEntity="Server"/> + <relationship name="keys" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="SecretKey" inverseName="account" inverseEntity="SecretKey"/> + <relationship name="smtp" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Server" inverseName="smtp" inverseEntity="Server"/> + </entity> + <entity name="Attachment" representedClassName="Attachment" syncable="YES" codeGenerationType="class"> + <attribute name="contentID" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/> + <attribute name="data" attributeType="Binary"/> + <attribute name="encryptionState" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/> + <attribute name="isExplicitAttachment" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/> + <attribute name="mcoPartType" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/> + <attribute name="mimeType" attributeType="String"/> + <attribute name="name" attributeType="String"/> + <attribute name="signatureState" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/> + <relationship name="mail" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="PersistentMail" inverseName="attachments" inverseEntity="PersistentMail"/> + <relationship name="parentOf" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Attachment" inverseName="partOf" inverseEntity="Attachment"/> + <relationship name="partOf" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Attachment" inverseName="parentOf" inverseEntity="Attachment"/> + </entity> + <entity name="EnzevalosContact" representedClassName="EnzevalosContact" syncable="YES"> + <attribute name="cnidentifier" optional="YES" attributeType="String"/> + <attribute name="color" optional="YES" attributeType="Transformable" customClassName="UIColor"/> + <attribute name="displayname" attributeType="String"/> + <relationship name="addresses" toMany="YES" deletionRule="Cascade" destinationEntity="Mail_Address" inverseName="contact" inverseEntity="Mail_Address"/> + <relationship name="keyrecords" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="KeyRecord" inverseName="contact" inverseEntity="KeyRecord"/> + </entity> + <entity name="Folder" representedClassName="Folder" syncable="YES"> + <attribute name="delimiter" optional="YES" attributeType="String"/> + <attribute name="flags" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/> + <attribute name="icon" optional="YES" attributeType="String"/> + <attribute name="lastUpdate" optional="YES" attributeType="Date" usesScalarValueType="NO"/> + <attribute name="maxID" optional="YES" attributeType="Decimal" defaultValueString="1"/> + <attribute name="minUID" optional="YES" attributeType="Decimal" defaultValueString="0.0"/> + <attribute name="path" attributeType="String"/> + <attribute name="pseudonym" attributeType="String"/> + <attribute name="uidvalidity" optional="YES" attributeType="Decimal" defaultValueString="0.0"/> + <relationship name="keyRecords" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="KeyRecord" inverseName="folder" inverseEntity="KeyRecord"/> + <relationship name="mails" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="PersistentMail" inverseName="folder" inverseEntity="PersistentMail"/> + <relationship name="parent" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Folder" inverseName="subfolder" inverseEntity="Folder"/> + <relationship name="subfolder" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Folder" inverseName="parent" inverseEntity="Folder"/> + </entity> + <entity name="KeyRecord" representedClassName="KeyRecord" syncable="YES"> + <attribute name="newestDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/> + <attribute name="nick" optional="YES" attributeType="String"/> + <relationship name="contact" maxCount="1" deletionRule="Nullify" destinationEntity="EnzevalosContact" inverseName="keyrecords" inverseEntity="EnzevalosContact"/> + <relationship name="folder" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Folder" inverseName="keyRecords" inverseEntity="Folder"/> + <relationship name="key" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="PersistentKey" inverseName="record" inverseEntity="PersistentKey"/> + <relationship name="persistentMails" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="PersistentMail" inverseName="record" inverseEntity="PersistentMail"/> + </entity> + <entity name="Mail_Address" representedClassName="Mail_Address" syncable="YES"> + <attribute name="address" attributeType="String" defaultValueString=""""/> + <attribute name="invitations" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/> + <attribute name="primaryKeyID" optional="YES" attributeType="String"/> + <attribute name="pseudonym" attributeType="String"/> + <relationship name="account" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Account" inverseName="aliase" inverseEntity="Account"/> + <relationship name="bcc" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="PersistentMail" inverseName="bcc" inverseEntity="PersistentMail"/> + <relationship name="cc" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="PersistentMail" inverseName="cc" inverseEntity="PersistentMail"/> + <relationship name="contact" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="EnzevalosContact" inverseName="addresses" inverseEntity="EnzevalosContact"/> + <relationship name="from" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="PersistentMail" inverseName="from" inverseEntity="PersistentMail"/> + <relationship name="keys" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="PersistentKey" inverseName="mailaddress" inverseEntity="PersistentKey"/> + <relationship name="to" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="PersistentMail" inverseName="to" inverseEntity="PersistentMail"/> + </entity> + <entity name="PersistentKey" representedClassName="PersistentKey" syncable="YES"> + <attribute name="autocryptGossip" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/> + <attribute name="discoveryDate" attributeType="Date" usesScalarValueType="NO"/> + <attribute name="encryptionType" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/> + <attribute name="gossip_timestamp" optional="YES" attributeType="Date" usesScalarValueType="NO"/> + <attribute name="gotFailedCallForUse" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/> + <attribute name="isMisstrusted" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/> + <attribute name="isRepealed" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/> + <attribute name="keyID" attributeType="String"/> + <attribute name="lastSeen" optional="YES" attributeType="Date" usesScalarValueType="NO"/> + <attribute name="lastSeenAutocrypt" optional="YES" attributeType="Date" usesScalarValueType="NO"/> + <attribute name="origin" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/> + <attribute name="preferEncryption" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/> + <attribute name="pseudonym" attributeType="String"/> + <attribute name="sentOwnPublicKey" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/> + <attribute name="verifiedDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/> + <relationship name="activeKey" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="PersistentKey"/> + <relationship name="activeRepeal" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="PersistentMail"/> + <relationship name="childKeys" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="PersistentKey" inverseName="parentKey" inverseEntity="PersistentKey"/> + <relationship name="firstMail" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="PersistentMail" inverseName="attachedKeys" inverseEntity="PersistentMail"/> + <relationship name="mailaddress" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Mail_Address" inverseName="keys" inverseEntity="Mail_Address"/> + <relationship name="parentKey" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="PersistentKey" inverseName="childKeys" inverseEntity="PersistentKey"/> + <relationship name="record" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="KeyRecord" inverseName="key" inverseEntity="KeyRecord"/> + <relationship name="repealedByMails" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="PersistentMail" inverseName="repealsKey" inverseEntity="PersistentMail"/> + <relationship name="signedMails" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="PersistentMail" inverseName="signedKey" inverseEntity="PersistentMail"/> + </entity> + <entity name="PersistentMail" representedClassName="PersistentMail" syncable="YES"> + <attribute name="attachedSignature" optional="YES" attributeType="Binary"/> + <attribute name="body" optional="YES" attributeType="String"/> + <attribute name="date" attributeType="Date" defaultDateTimeInterval="-31582140" usesScalarValueType="NO"/> + <attribute name="decryptedBody" optional="YES" attributeType="String"/> + <attribute name="decrytionCode" optional="YES" attributeType="String"/> + <attribute name="deleteWhileTravel" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/> + <attribute name="encryptedBody" optional="YES" attributeType="String"/> + <attribute name="flag" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/> + <attribute name="gmailMessageID" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/> + <attribute name="gmailThreadID" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/> + <attribute name="isCorrectlySigned" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/> + <attribute name="isEncrypted" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/> + <attribute name="isKeyImported" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/> + <attribute name="isSigned" attributeType="Boolean" usesScalarValueType="YES"/> + <attribute name="keyID" optional="YES" attributeType="String"/> + <attribute name="messageID" optional="YES" attributeType="String"/> + <attribute name="modSeqValue" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/> + <attribute name="notLoadedMessageIDs" optional="YES" attributeType="String"/> + <attribute name="received" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/> + <attribute name="secretKey" optional="YES" attributeType="String"/> + <attribute name="storeEncrypted" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/> + <attribute name="subject" attributeType="String"/> + <attribute name="trouble" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/> + <attribute name="uid" attributeType="Decimal" defaultValueString="0"/> + <attribute name="uidvalidity" optional="YES" attributeType="Decimal" defaultValueString="0.0"/> + <attribute name="unableToDecrypt" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/> + <attribute name="visibleBody" optional="YES" attributeType="String"/> + <attribute name="xMailer" optional="YES" attributeType="String"/> + <relationship name="attachedKeys" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="PersistentKey" inverseName="firstMail" inverseEntity="PersistentKey"/> + <relationship name="attachments" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Attachment" inverseName="mail" inverseEntity="Attachment"/> + <relationship name="bcc" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Mail_Address" inverseName="bcc" inverseEntity="Mail_Address"/> + <relationship name="cc" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Mail_Address" inverseName="cc" inverseEntity="Mail_Address"/> + <relationship name="decryptedKey" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="SecretKey" inverseName="decryptedMails" inverseEntity="SecretKey"/> + <relationship name="folder" maxCount="1" deletionRule="Nullify" destinationEntity="Folder" inverseName="mails" inverseEntity="Folder"/> + <relationship name="from" maxCount="1" deletionRule="Nullify" destinationEntity="Mail_Address" inverseName="from" inverseEntity="Mail_Address"/> + <relationship name="record" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="KeyRecord" inverseName="persistentMails" inverseEntity="KeyRecord"/> + <relationship name="referenceMails" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="PersistentMail" inverseName="referenceMails" inverseEntity="PersistentMail"/> + <relationship name="relatedSecretKey" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="SecretKey" inverseName="relatedDecryptedMails" inverseEntity="SecretKey"/> + <relationship name="repealsKey" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="PersistentKey" inverseName="repealedByMails" inverseEntity="PersistentKey"/> + <relationship name="signedKey" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="PersistentKey" inverseName="signedMails" inverseEntity="PersistentKey"/> + <relationship name="to" toMany="YES" deletionRule="Nullify" destinationEntity="Mail_Address" inverseName="to" inverseEntity="Mail_Address"/> + <fetchIndex name="byDateIndex"> + <fetchIndexElement property="date" type="Binary" order="ascending"/> + </fetchIndex> + </entity> + <entity name="SecretKey" representedClassName="SecretKey" syncable="YES"> + <attribute name="exported" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/> + <attribute name="importedDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/> + <attribute name="keyID" attributeType="String" defaultValueString="no"/> + <attribute name="obsolete" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/> + <attribute name="origin" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/> + <relationship name="account" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Account" inverseName="keys" inverseEntity="Account"/> + <relationship name="decryptedMails" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="PersistentMail" inverseName="decryptedKey" inverseEntity="PersistentMail"/> + <relationship name="relatedDecryptedMails" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="PersistentMail" inverseName="relatedSecretKey" inverseEntity="PersistentMail"/> + </entity> + <entity name="Server" representedClassName="Server" syncable="YES" codeGenerationType="class"> + <attribute name="authType" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/> + <attribute name="connectionType" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/> + <attribute name="hostname" attributeType="String"/> + <attribute name="port" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/> + <relationship name="imap" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Account" inverseName="imap" inverseEntity="Account"/> + <relationship name="smtp" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Account" inverseName="smtp" inverseEntity="Account"/> + </entity> + <fetchRequest name="allKeyRecords" entity="KeyRecord" predicateString="NOT (FALSEPREDICATE)" returnDistinctResults="YES"/> + <fetchRequest name="getFolder" entity="Folder" predicateString="name == "$folder""/> + <fetchRequest name="getMailAddress" entity="Mail_Address" predicateString="address == "$adr""/> + <elements> + <element name="Account" positionX="-315" positionY="-36" width="128" height="255"/> + <element name="Attachment" positionX="-315" positionY="-36" width="128" height="210"/> + <element name="EnzevalosContact" positionX="-209" positionY="198" width="128" height="120"/> + <element name="Folder" positionX="-297" positionY="-18" width="128" height="240"/> + <element name="KeyRecord" positionX="-315" positionY="-36" width="128" height="135"/> + <element name="Mail_Address" positionX="-297" positionY="-18" width="128" height="210"/> + <element name="PersistentKey" positionX="-315" positionY="-36" width="128" height="405"/> + <element name="PersistentMail" positionX="-416" positionY="-189" width="128" height="658"/> + <element name="SecretKey" positionX="-306" positionY="-27" width="128" height="163"/> + <element name="Server" positionX="-306" positionY="-27" width="128" height="135"/> + </elements> +</model> \ No newline at end of file diff --git a/enzevalos_iphone/mail/IncomingMail.swift b/enzevalos_iphone/mail/IncomingMail.swift index 1b63dd842c058138db22097eb961c71231b7e283..cdee31bc94d7df41f4baeb734ac55db8b7ce4015 100644 --- a/enzevalos_iphone/mail/IncomingMail.swift +++ b/enzevalos_iphone/mail/IncomingMail.swift @@ -155,6 +155,7 @@ class IncomingMail { return keyIds } } + private var attachedSignature: Data? = nil private var subject: String = "" private var date: Date = Date() private var autocrypt: Autocrypt? = nil @@ -181,6 +182,7 @@ class IncomingMail { private var body: String = "" private var encryptedBody: String? private var secretKeys: [String] = [] + private var relaedSecrectKey: SecretKey? = nil private var newPublicKeys: [String] = [] private var newAutocrypPublicKeys: [String] = [] private var newSecretKeyIDs: [String]? = [] @@ -264,7 +266,7 @@ class IncomingMail { func store(keyRecord: KeyRecord?) -> PersistentMail? { let sk = secretKeys.first //TODO FIX: may import more secret keys? - let mail = DataHandler.handler.createMail(uID, sender: from, receivers: rec, cc: cc, time: date, received: true, subject: subject, body: body, readableAttachments: readableAttachments, flags: flags, record: keyRecord, autocrypt: autocrypt, decryptedData: cryptoObj, folderPath: folderPath, secretKey: sk, references: references, mailagent: userAgent, messageID: msgID, encryptedBody: encryptedBody, storeEncrypted: storeEncrypted) + let mail = DataHandler.handler.createMail(uID, sender: from, receivers: rec, cc: cc, time: date, received: true, subject: subject, body: body, readableAttachments: readableAttachments, flags: flags, record: keyRecord, autocrypt: autocrypt, decryptedData: cryptoObj, folderPath: folderPath, secretKey: sk, references: references, mailagent: userAgent, messageID: msgID, encryptedBody: encryptedBody, storeEncrypted: storeEncrypted, attachedSignature: attachedSignature) if let m = mail { let pgp = SwiftPGP() if let autoc = autocrypt, let adr = from?.mailbox { @@ -375,6 +377,7 @@ class IncomingMail { signedStrings = IncomingMail.extractSignedMessage(text: body) inlineSigned = true } + var text: String? var signedObject: CryptoObject? if signedStrings.count == 1 { @@ -383,7 +386,9 @@ class IncomingMail { else if signedStrings.count > 1 { text = signedStrings.joined(separator: "\r\n") } - if let signedData = text?.data(using: .utf8){ // No Signed Data! + if let signedData = text?.data(using: .utf8) { // No Signed Data! + // First Signature as main attachedSignature for mail -- not optimal + self.attachedSignature = try? Armor.readArmored(signaturesRaw.first) for sig in signaturesRaw { if let signature = try? Armor.readArmored(sig), let adr = from?.mailbox { for id in fromKeyIds {