diff --git a/enzevalos_iphone.xcodeproj/project.pbxproj b/enzevalos_iphone.xcodeproj/project.pbxproj index 90d6c625f715802d4f281448c527365d698b7f17..9bfc828ae78ecec1d3687e0de69c9049a034a73e 100644 --- a/enzevalos_iphone.xcodeproj/project.pbxproj +++ b/enzevalos_iphone.xcodeproj/project.pbxproj @@ -57,11 +57,6 @@ 471876F7223FACA900912135 /* BobPWTEST1234.asc in Resources */ = {isa = PBXBuildFile; fileRef = 471876F5223FACA900912135 /* BobPWTEST1234.asc */; }; 471876F8223FACA900912135 /* BobWithoutPW.asc in Resources */ = {isa = PBXBuildFile; fileRef = 471876F6223FACA900912135 /* BobWithoutPW.asc */; }; 472F396E1E14F384009260FB /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 472F396D1E14F384009260FB /* CoreData.framework */; }; - 472F39701E14F75C009260FB /* DataHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472F396F1E14F75C009260FB /* DataHandler.swift */; }; - 472F397C1E1D0B0B009260FB /* PersistentMail +CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472F39781E1D0B0B009260FB /* PersistentMail +CoreDataProperties.swift */; }; - 472F397E1E1D0B0B009260FB /* EnzevalosContact+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472F397A1E1D0B0B009260FB /* EnzevalosContact+CoreDataProperties.swift */; }; - 472F39811E1E5347009260FB /* Mail_Address+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472F397F1E1E5347009260FB /* Mail_Address+CoreDataClass.swift */; }; - 472F39821E1E5347009260FB /* Mail_Address+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472F39801E1E5347009260FB /* Mail_Address+CoreDataProperties.swift */; }; 472F39861E1FA34E009260FB /* Record.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472F39851E1FA34E009260FB /* Record.swift */; }; 472F398A1E251787009260FB /* Contact.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472F39891E251787009260FB /* Contact.swift */; }; 472F398C1E2519C8009260FB /* CNContactExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472F398B1E2519C8009260FB /* CNContactExtension.swift */; }; @@ -77,16 +72,10 @@ 4751C6F82343B37C006B2A4D /* Onboarding.Video.Click.Eng.m4v in Resources */ = {isa = PBXBuildFile; fileRef = 4751C6F72343B377006B2A4D /* Onboarding.Video.Click.Eng.m4v */; }; 4751C6FA23449699006B2A4D /* CryptoManagementViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4751C6F923449699006B2A4D /* CryptoManagementViewController.swift */; }; 4751C6FC2344C8D1006B2A4D /* KeyTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4751C6FB2344C8D1006B2A4D /* KeyTableViewController.swift */; }; - 4751C7002344D37C006B2A4D /* SecretKey+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4751C6FE2344D37C006B2A4D /* SecretKey+CoreDataClass.swift */; }; - 4751C7012344D37C006B2A4D /* SecretKey+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4751C6FF2344D37C006B2A4D /* SecretKey+CoreDataProperties.swift */; }; 4756DE0E20402F8E00452288 /* invitationTextCensor.html in Resources */ = {isa = PBXBuildFile; fileRef = 4756DE0D20402F8E00452288 /* invitationTextCensor.html */; }; 475B00331F7B9565006CDD41 /* SwiftPGP.swift in Sources */ = {isa = PBXBuildFile; fileRef = 475B00301F7B9565006CDD41 /* SwiftPGP.swift */; }; 475B00341F7B9565006CDD41 /* Cryptography.swift in Sources */ = {isa = PBXBuildFile; fileRef = 475B00311F7B9565006CDD41 /* Cryptography.swift */; }; 475B00351F7B9565006CDD41 /* CryptoObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 475B00321F7B9565006CDD41 /* CryptoObject.swift */; }; - 475B00421F7BB6D6006CDD41 /* PersistentKey+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 475B00401F7BB6D6006CDD41 /* PersistentKey+CoreDataClass.swift */; }; - 475B00431F7BB6D6006CDD41 /* PersistentKey+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 475B00411F7BB6D6006CDD41 /* PersistentKey+CoreDataProperties.swift */; }; - 475DF4791F0D54C9009D807F /* Folder+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 475DF4771F0D54C9009D807F /* Folder+CoreDataClass.swift */; }; - 475DF47A1F0D54C9009D807F /* Folder+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 475DF4781F0D54C9009D807F /* Folder+CoreDataProperties.swift */; }; 476142081E07E52B00FD5E4F /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 476142071E07E52B00FD5E4F /* Theme.swift */; }; 4761420A1E082F9C00FD5E4F /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 476142091E082F9C00FD5E4F /* Settings.bundle */; }; 476373C21E09BA88004D5EFE /* UserData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 476373C11E09BA88004D5EFE /* UserData.swift */; }; @@ -106,8 +95,6 @@ 476406A12416B5C800C7D426 /* OnboardingIntro.swift in Sources */ = {isa = PBXBuildFile; fileRef = 476406A02416B5C800C7D426 /* OnboardingIntro.swift */; }; 476801DB218436B600F7F259 /* Autocrypt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 476801DA218436B600F7F259 /* Autocrypt.swift */; }; 476801DE21846A5A00F7F259 /* OutgoingMail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 476801DD21846A5A00F7F259 /* OutgoingMail.swift */; }; - 476916A0216B86A100491527 /* PersistentMail +CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4769169F216B86A100491527 /* PersistentMail +CoreDataClass.swift */; }; - 476916A2216B86CF00491527 /* EnzevalosContact+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 476916A1216B86CF00491527 /* EnzevalosContact+CoreDataClass.swift */; }; 47691A8A1ECB56D1004BCFC5 /* Mail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47691A891ECB56D1004BCFC5 /* Mail.swift */; }; 47691A8C1ECC3EC7004BCFC5 /* EphemeralMail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47691A8B1ECC3EC7004BCFC5 /* EphemeralMail.swift */; }; 476EEF9922A872BF00BB4EF7 /* enzevalos_iphoneUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 476EEF9822A872BF00BB4EF7 /* enzevalos_iphoneUITests.swift */; }; @@ -195,8 +182,6 @@ 47EABF3024240BD300774A93 /* AccountSetupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47EABF2F24240BD300774A93 /* AccountSetupView.swift */; }; 47EABF342424FD1900774A93 /* SwiftUIOnboardingUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47EABF332424FD1800774A93 /* SwiftUIOnboardingUITests.swift */; }; 47F0376E22A7278A0005C9DE /* accounts.json in Resources */ = {isa = PBXBuildFile; fileRef = 47F0376D22A7278A0005C9DE /* accounts.json */; }; - 47F79240203492E3005E7DB6 /* KeyRecord+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47F7923E203492E3005E7DB6 /* KeyRecord+CoreDataClass.swift */; }; - 47F79241203492E3005E7DB6 /* KeyRecord+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47F7923F203492E3005E7DB6 /* KeyRecord+CoreDataProperties.swift */; }; 47F867E02052B47C00AA832F /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 47F867DF2052B47C00AA832F /* Security.framework */; }; 47F867E22052B48E00AA832F /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 47F867E12052B48E00AA832F /* libz.tbd */; }; 47F867E42052B49800AA832F /* libbz2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 47F867E32052B49800AA832F /* libbz2.tbd */; }; @@ -244,7 +229,6 @@ A12F91D821F3A99800AB0589 /* NSLayoutConstraintExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A12F91D721F3A99800AB0589 /* NSLayoutConstraintExtension.swift */; }; A12FC23120221A1400196008 /* ExportInfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A12FC23020221A1400196008 /* ExportInfoViewController.swift */; }; A13526791D955BDF00D3BFE1 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A13526781D955BDF00D3BFE1 /* AppDelegate.swift */; }; - A13526811D955BDF00D3BFE1 /* enzevalos_iphone.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = A135267F1D955BDF00D3BFE1 /* enzevalos_iphone.xcdatamodeld */; }; A13526861D955BDF00D3BFE1 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A13526841D955BDF00D3BFE1 /* LaunchScreen.storyboard */; }; A142E70921E7919F000395E3 /* IntroContactViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A142E70821E7919F000395E3 /* IntroContactViewController.swift */; }; A15D215B223BE5F4003E0CE0 /* TempAttachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = A15D215A223BE5F4003E0CE0 /* TempAttachment.swift */; }; @@ -406,11 +390,6 @@ 471876F5223FACA900912135 /* BobPWTEST1234.asc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = BobPWTEST1234.asc; sourceTree = "<group>"; }; 471876F6223FACA900912135 /* BobWithoutPW.asc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = BobWithoutPW.asc; sourceTree = "<group>"; }; 472F396D1E14F384009260FB /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; - 472F396F1E14F75C009260FB /* DataHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataHandler.swift; sourceTree = "<group>"; }; - 472F39781E1D0B0B009260FB /* PersistentMail +CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "PersistentMail +CoreDataProperties.swift"; sourceTree = "<group>"; }; - 472F397A1E1D0B0B009260FB /* EnzevalosContact+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "EnzevalosContact+CoreDataProperties.swift"; sourceTree = "<group>"; }; - 472F397F1E1E5347009260FB /* Mail_Address+CoreDataClass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Mail_Address+CoreDataClass.swift"; sourceTree = "<group>"; }; - 472F39801E1E5347009260FB /* Mail_Address+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Mail_Address+CoreDataProperties.swift"; sourceTree = "<group>"; }; 472F39851E1FA34E009260FB /* Record.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Record.swift; sourceTree = "<group>"; }; 472F39891E251787009260FB /* Contact.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Contact.swift; sourceTree = "<group>"; }; 472F398B1E2519C8009260FB /* CNContactExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CNContactExtension.swift; sourceTree = "<group>"; }; @@ -423,21 +402,13 @@ 474054972244D7A9007CF83B /* MailServerConfigurationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MailServerConfigurationTest.swift; sourceTree = "<group>"; }; 474994012261E4E6000F8DA5 /* SimpleSendIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleSendIcon.swift; sourceTree = "<group>"; }; 4751C6ED233CA583006B2A4D /* DateExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateExtension.swift; sourceTree = "<group>"; }; - 4751C6F0233CE1E4006B2A4D /* enzevalos_iphone 7.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "enzevalos_iphone 7.xcdatamodel"; sourceTree = "<group>"; }; 4751C6F72343B377006B2A4D /* Onboarding.Video.Click.Eng.m4v */ = {isa = PBXFileReference; lastKnownFileType = file; path = Onboarding.Video.Click.Eng.m4v; sourceTree = "<group>"; }; 4751C6F923449699006B2A4D /* CryptoManagementViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CryptoManagementViewController.swift; sourceTree = "<group>"; }; 4751C6FB2344C8D1006B2A4D /* KeyTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyTableViewController.swift; sourceTree = "<group>"; }; - 4751C6FD2344D169006B2A4D /* enzevalos_iphone 8.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "enzevalos_iphone 8.xcdatamodel"; sourceTree = "<group>"; }; - 4751C6FE2344D37C006B2A4D /* SecretKey+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SecretKey+CoreDataClass.swift"; sourceTree = "<group>"; }; - 4751C6FF2344D37C006B2A4D /* SecretKey+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SecretKey+CoreDataProperties.swift"; sourceTree = "<group>"; }; 4756DE0D20402F8E00452288 /* invitationTextCensor.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = invitationTextCensor.html; path = Invitation/invitationTextCensor.html; sourceTree = "<group>"; }; 475B00301F7B9565006CDD41 /* SwiftPGP.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftPGP.swift; sourceTree = "<group>"; }; 475B00311F7B9565006CDD41 /* Cryptography.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cryptography.swift; sourceTree = "<group>"; }; 475B00321F7B9565006CDD41 /* CryptoObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CryptoObject.swift; sourceTree = "<group>"; }; - 475B00401F7BB6D6006CDD41 /* PersistentKey+CoreDataClass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "PersistentKey+CoreDataClass.swift"; sourceTree = "<group>"; }; - 475B00411F7BB6D6006CDD41 /* PersistentKey+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "PersistentKey+CoreDataProperties.swift"; sourceTree = "<group>"; }; - 475DF4771F0D54C9009D807F /* Folder+CoreDataClass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Folder+CoreDataClass.swift"; sourceTree = "<group>"; }; - 475DF4781F0D54C9009D807F /* Folder+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Folder+CoreDataProperties.swift"; sourceTree = "<group>"; }; 476142071E07E52B00FD5E4F /* Theme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; }; 476142091E082F9C00FD5E4F /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; }; 476373C11E09BA88004D5EFE /* UserData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserData.swift; sourceTree = "<group>"; }; @@ -567,8 +538,6 @@ 476406A02416B5C800C7D426 /* OnboardingIntro.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnboardingIntro.swift; sourceTree = "<group>"; }; 476801DA218436B600F7F259 /* Autocrypt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Autocrypt.swift; sourceTree = "<group>"; }; 476801DD21846A5A00F7F259 /* OutgoingMail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OutgoingMail.swift; sourceTree = "<group>"; }; - 4769169F216B86A100491527 /* PersistentMail +CoreDataClass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "PersistentMail +CoreDataClass.swift"; sourceTree = "<group>"; }; - 476916A1216B86CF00491527 /* EnzevalosContact+CoreDataClass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "EnzevalosContact+CoreDataClass.swift"; sourceTree = "<group>"; }; 47691A891ECB56D1004BCFC5 /* Mail.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Mail.swift; sourceTree = "<group>"; }; 47691A8B1ECC3EC7004BCFC5 /* EphemeralMail.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EphemeralMail.swift; sourceTree = "<group>"; }; 476EEF9622A872BF00BB4EF7 /* enzevalos_iphoneUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = enzevalos_iphoneUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -609,8 +578,6 @@ 47A5D6DD2294B5480084F81D /* AppAuth.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = AppAuth.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 47A5D6E12294BF3A0084F81D /* TempKey.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TempKey.swift; sourceTree = "<group>"; }; 47A5D6E32294BFF50084F81D /* Logger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = "<group>"; }; - 47AAFA6B243CB58F00949015 /* enzevalos_iphone 11.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "enzevalos_iphone 11.xcdatamodel"; sourceTree = "<group>"; }; - 47B2318A1F0D458100961B28 /* enzevalos_iphone 2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "enzevalos_iphone 2.xcdatamodel"; sourceTree = "<group>"; }; 47C036FE2347C0F4006295E8 /* ImportKeyOverviewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImportKeyOverviewController.swift; sourceTree = "<group>"; }; 47C037022347D4D1006295E8 /* PasteKeyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasteKeyViewController.swift; sourceTree = "<group>"; }; 47C09C75243B3395007F74A2 /* SmallContactListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmallContactListView.swift; sourceTree = "<group>"; }; @@ -638,7 +605,6 @@ 47CEF4EA2052C3C700887CDB /* ObjectivePGP.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = ObjectivePGP.framework; sourceTree = "<group>"; }; 47CEF4EC2052C3E600887CDB /* ObjectivePGP.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ObjectivePGP.framework; path = ../enzevalos_iphone_workspace/ObjectivePGP.framework; sourceTree = "<group>"; }; 47D1302A1F7CEE6D007B14DF /* DebugSettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DebugSettings.swift; sourceTree = "<group>"; }; - 47D1BB052431F81C001F1EC9 /* enzevalos_iphone 10.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "enzevalos_iphone 10.xcdatamodel"; sourceTree = "<group>"; }; 47E7376D22845EC400972401 /* SecretKeyTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecretKeyTableViewController.swift; sourceTree = "<group>"; }; 47E7376F22845F3A00972401 /* KeyViews.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = KeyViews.storyboard; sourceTree = "<group>"; }; 47E737732284610E00972401 /* KeyCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = KeyCell.xib; sourceTree = "<group>"; }; @@ -658,8 +624,6 @@ 47EABF2F24240BD300774A93 /* AccountSetupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountSetupView.swift; sourceTree = "<group>"; }; 47EABF332424FD1800774A93 /* SwiftUIOnboardingUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIOnboardingUITests.swift; sourceTree = "<group>"; }; 47F0376D22A7278A0005C9DE /* accounts.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = accounts.json; sourceTree = "<group>"; }; - 47F7923E203492E3005E7DB6 /* KeyRecord+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "KeyRecord+CoreDataClass.swift"; sourceTree = "<group>"; }; - 47F7923F203492E3005E7DB6 /* KeyRecord+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "KeyRecord+CoreDataProperties.swift"; sourceTree = "<group>"; }; 47F867DF2052B47C00AA832F /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; 47F867E12052B48E00AA832F /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; 47F867E32052B49800AA832F /* libbz2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libbz2.tbd; path = usr/lib/libbz2.tbd; sourceTree = SDKROOT; }; @@ -671,7 +635,6 @@ 47FAE3482524FB58005A1BCB /* AddressRecord.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressRecord.swift; sourceTree = "<group>"; }; 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>"; }; 676C2D2F24321F8100B631B3 /* TyposquattingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TyposquattingTests.swift; sourceTree = "<group>"; }; 6789425E2430C3B300C746D1 /* MailComparison.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MailComparison.swift; sourceTree = "<group>"; }; 678942602430C3D600C746D1 /* Typosquatting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Typosquatting.swift; sourceTree = "<group>"; }; @@ -722,14 +685,12 @@ A12FC23020221A1400196008 /* ExportInfoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExportInfoViewController.swift; sourceTree = "<group>"; }; A13526751D955BDF00D3BFE1 /* enzevalos_iphone.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = enzevalos_iphone.app; sourceTree = BUILT_PRODUCTS_DIR; }; A13526781D955BDF00D3BFE1 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; - A13526801D955BDF00D3BFE1 /* enzevalos_iphone.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = enzevalos_iphone.xcdatamodel; sourceTree = "<group>"; }; A135268C1D955BE000D3BFE1 /* enzevalos_iphoneTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = enzevalos_iphoneTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; A13526921D955BE000D3BFE1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; A142E70821E7919F000395E3 /* IntroContactViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntroContactViewController.swift; sourceTree = "<group>"; }; A15D215A223BE5F4003E0CE0 /* TempAttachment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TempAttachment.swift; sourceTree = "<group>"; }; A15D215C223BE614003E0CE0 /* attachment.eml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = attachment.eml; sourceTree = "<group>"; }; A15D215E223BE6E4003E0CE0 /* MailTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MailTest.swift; sourceTree = "<group>"; }; - A15D2D0B21F4CF13007AF2F4 /* enzevalos_iphone 5.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "enzevalos_iphone 5.xcdatamodel"; sourceTree = "<group>"; }; A16BA2111E0439B6005E29E3 /* providers.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; lineEnding = 0; path = providers.json; sourceTree = "<group>"; }; A1735DF9205AB88500B336DB /* SendViewState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendViewState.swift; sourceTree = "<group>"; }; A17FDFF2202C685800F7BA89 /* StudySettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StudySettings.swift; sourceTree = "<group>"; }; @@ -739,11 +700,8 @@ A182183121E518A400918A29 /* IntroContactCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = IntroContactCell.xib; sourceTree = "<group>"; }; A182183321E51DD200918A29 /* IntroContactCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntroContactCell.swift; sourceTree = "<group>"; }; A18E7D761FBDE5D9002F7CC9 /* LoggingEventType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggingEventType.swift; sourceTree = "<group>"; }; - A1909719220F887D00FA7B2A /* enzevalos_iphone 6.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "enzevalos_iphone 6.xcdatamodel"; sourceTree = "<group>"; }; A198270D1D9A8ABC0027F65C /* enzevalos_iphone-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "enzevalos_iphone-Bridging-Header.h"; sourceTree = "<group>"; }; A198D2282056B384004CC838 /* SendViewDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendViewDelegate.swift; sourceTree = "<group>"; }; - A19BD0A721ED62AE00E4D603 /* enzevalos_iphone 3.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "enzevalos_iphone 3.xcdatamodel"; sourceTree = "<group>"; }; - A19F3FFB21F0BE79005334F2 /* enzevalos_iphone 4.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "enzevalos_iphone 4.xcdatamodel"; sourceTree = "<group>"; }; A1A9DE721F864B0500B808AA /* ExportCells.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExportCells.swift; sourceTree = "<group>"; }; A1ACDD0821EB9C4C00A059D0 /* IntroInputViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntroInputViewController.swift; sourceTree = "<group>"; }; A1AEBA5821E808CB00C84E59 /* IntroYesNoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntroYesNoViewController.swift; sourceTree = "<group>"; }; @@ -1262,28 +1220,6 @@ path = StyleKits; sourceTree = "<group>"; }; - 47B91AC01EC0C1CF000AE3EE /* coredata */ = { - isa = PBXGroup; - children = ( - 4751C6FE2344D37C006B2A4D /* SecretKey+CoreDataClass.swift */, - 4751C6FF2344D37C006B2A4D /* SecretKey+CoreDataProperties.swift */, - 47F7923E203492E3005E7DB6 /* KeyRecord+CoreDataClass.swift */, - 47F7923F203492E3005E7DB6 /* KeyRecord+CoreDataProperties.swift */, - 475B00401F7BB6D6006CDD41 /* PersistentKey+CoreDataClass.swift */, - 475B00411F7BB6D6006CDD41 /* PersistentKey+CoreDataProperties.swift */, - 472F39781E1D0B0B009260FB /* PersistentMail +CoreDataProperties.swift */, - 4769169F216B86A100491527 /* PersistentMail +CoreDataClass.swift */, - 472F396F1E14F75C009260FB /* DataHandler.swift */, - 475DF4771F0D54C9009D807F /* Folder+CoreDataClass.swift */, - 475DF4781F0D54C9009D807F /* Folder+CoreDataProperties.swift */, - 472F397A1E1D0B0B009260FB /* EnzevalosContact+CoreDataProperties.swift */, - 472F39801E1E5347009260FB /* Mail_Address+CoreDataProperties.swift */, - 476916A1216B86CF00491527 /* EnzevalosContact+CoreDataClass.swift */, - 472F397F1E1E5347009260FB /* Mail_Address+CoreDataClass.swift */, - ); - name = coredata; - sourceTree = "<group>"; - }; 47B91AC11EC0C1FB000AE3EE /* data */ = { isa = PBXGroup; children = ( @@ -1295,7 +1231,6 @@ 472F398B1E2519C8009260FB /* CNContactExtension.swift */, 472F398F1E252470009260FB /* CNMailAddressesExtension.swift */, A1EB05871D956879008659C1 /* AddressHandler.swift */, - 47B91AC01EC0C1CF000AE3EE /* coredata */, ); name = data; sourceTree = "<group>"; @@ -1627,7 +1562,6 @@ A1EB05A31D956E32008659C1 /* Assets.xcassets */, 476142091E082F9C00FD5E4F /* Settings.bundle */, A1BE3FF81E9664660040114B /* InfoPlist.strings */, - A135267F1D955BDF00D3BFE1 /* enzevalos_iphone.xcdatamodeld */, 3E9708AC1FAC925D005825C9 /* PLists */, ); path = enzevalos_iphone; @@ -2306,9 +2240,7 @@ A1F8541021E8A60800614514 /* IntroSecretViewController.swift in Sources */, A1ACDD0921EB9C4C00A059D0 /* IntroInputViewController.swift in Sources */, 476406952416B54D00C7D426 /* KeyRecordRow.swift in Sources */, - 476916A0216B86A100491527 /* PersistentMail +CoreDataClass.swift in Sources */, 47EABF3024240BD300774A93 /* AccountSetupView.swift in Sources */, - 4751C7002344D37C006B2A4D /* SecretKey+CoreDataClass.swift in Sources */, A1AEBA5921E808CB00C84E59 /* IntroYesNoViewController.swift in Sources */, A1EB05941D956931008659C1 /* InboxCellDelegator.swift in Sources */, 47C822602437A143005BCE73 /* CornerRounder.swift in Sources */, @@ -2318,11 +2250,9 @@ 47C8225B24379EAE005BCE73 /* MessageViewMain.swift in Sources */, 47FAE30E2524AA97005A1BCB /* DataModel.xcdatamodeld in Sources */, 8428A8651F436A11007649A5 /* BadgeCaseCollectionViewCell.swift in Sources */, - 472F39811E1E5347009260FB /* Mail_Address+CoreDataClass.swift in Sources */, A1EB05821D95685B008659C1 /* CollectionDataDelegate.swift in Sources */, 47A5D6E22294BF3B0084F81D /* TempKey.swift in Sources */, 47C8226B2438A86B005BCE73 /* SenderViewMain.swift in Sources */, - 4751C7012344D37C006B2A4D /* SecretKey+CoreDataProperties.swift in Sources */, 476406992416B54D00C7D426 /* SearchView.swift in Sources */, 47D1302B1F7CEE6D007B14DF /* DebugSettings.swift in Sources */, A1EB05801D956851008659C1 /* SendViewController.swift in Sources */, @@ -2375,7 +2305,6 @@ 4733B1E52527196100AB5600 /* PersistentDataProvider.swift in Sources */, 8428A8711F436A1E007649A5 /* GamificationStatusViewController.swift in Sources */, F1866C86201F707200B72453 /* EmailHelper.m in Sources */, - 47F79241203492E3005E7DB6 /* KeyRecord+CoreDataProperties.swift in Sources */, A10DE4201EFAA2CE005E8189 /* FolderViewController.swift in Sources */, 3EB4FA9F2012007C001D0625 /* DialogViewController.swift in Sources */, 476142081E07E52B00FD5E4F /* Theme.swift in Sources */, @@ -2387,8 +2316,6 @@ 4751C6EE233CA583006B2A4D /* DateExtension.swift in Sources */, 47FAE31C2524C07B005A1BCB /* MailRecord.swift in Sources */, 477548DE21F5DABE000B22A8 /* MailServerConnectionError.swift in Sources */, - 475DF47A1F0D54C9009D807F /* Folder+CoreDataProperties.swift in Sources */, - 475B00431F7BB6D6006CDD41 /* PersistentKey+CoreDataProperties.swift in Sources */, 479C649A21F45DAF00A01071 /* HideShowPasswordTextField.swift in Sources */, 47C112C62531DBDD00621A07 /* SecretKeyRecord.swift in Sources */, 47CEAC98222541B40075B7DC /* MailSession.swift in Sources */, @@ -2397,13 +2324,10 @@ 4707096D1F8F9F4900657F41 /* ExportViewController.swift in Sources */, F12060801DA540FE00F6EF37 /* RefreshControlExtension.swift in Sources */, 4751C6FC2344C8D1006B2A4D /* KeyTableViewController.swift in Sources */, - A13526811D955BDF00D3BFE1 /* enzevalos_iphone.xcdatamodeld in Sources */, - 472F39821E1E5347009260FB /* Mail_Address+CoreDataProperties.swift in Sources */, 477548E221F77466000B22A8 /* SecurityIndicator.swift in Sources */, 476373C21E09BA88004D5EFE /* UserData.swift in Sources */, A1EB05A01D95696C008659C1 /* MessageBodyTableViewCell.swift in Sources */, F18B44621E73286C0080C041 /* ReadVENDelegate.swift in Sources */, - 475B00421F7BB6D6006CDD41 /* PersistentKey+CoreDataClass.swift in Sources */, A10DAA5721F37600005D8BBB /* IntroInfoButton.swift in Sources */, 47A2A57223599D180013883D /* FeedbackButtonHelper.swift in Sources */, 476406842416AA9100C7D426 /* TestOpenSSL.swift in Sources */, @@ -2424,22 +2348,18 @@ 47C8225324379EAE005BCE73 /* AttachmentsViewMain.swift in Sources */, A182183421E51DD200918A29 /* IntroContactCell.swift in Sources */, 678942612430C3D600C746D1 /* Typosquatting.swift in Sources */, - 472F397C1E1D0B0B009260FB /* PersistentMail +CoreDataProperties.swift in Sources */, 8428A85C1F436A05007649A5 /* ArrowView.swift in Sources */, 47E737762284632F00972401 /* KeyCell.swift in Sources */, A1EB05961D956939008659C1 /* InboxTableViewCell.swift in Sources */, - 47F79240203492E3005E7DB6 /* KeyRecord+CoreDataClass.swift in Sources */, 47C112CA2531E9B000621A07 /* AttachmentRecord.swift in Sources */, A1083A541E8BFEA6003666B7 /* Onboarding.swift in Sources */, 476406982416B54D00C7D426 /* CiricleImage.swift in Sources */, A111F6AD1FA77B170060AFDE /* LoggerDetail.swift in Sources */, 47358D92244A5AEA000116D7 /* SelectableTextView.swift in Sources */, A13526791D955BDF00D3BFE1 /* AppDelegate.swift in Sources */, - 476916A2216B86CF00491527 /* EnzevalosContact+CoreDataClass.swift in Sources */, 0EF148052422543E00B3C198 /* Certificate.swift in Sources */, A1ECE54B1EFBE7ED0009349F /* FolderCell.swift in Sources */, 8428A85F1F436A05007649A5 /* GamificationData.swift in Sources */, - 475DF4791F0D54C9009D807F /* Folder+CoreDataClass.swift in Sources */, A15D215B223BE5F4003E0CE0 /* TempAttachment.swift in Sources */, 4706D65F225B7B6B00B3F1D3 /* ItunesHandler.swift in Sources */, 3EC35F2D200376A1008BDF95 /* SendViewController+Invitation.swift in Sources */, @@ -2454,7 +2374,6 @@ 47EABF09241A9C8700774A93 /* AuthenticationModel.swift in Sources */, 47C036FF2347C0F5006295E8 /* ImportKeyOverviewController.swift in Sources */, A1EB05881D956879008659C1 /* AddressHandler.swift in Sources */, - 472F39701E14F75C009260FB /* DataHandler.swift in Sources */, A1C62E9A2018F716000E5273 /* OnboardingValueState.swift in Sources */, A1EB05901D956923008659C1 /* ReadViewController.swift in Sources */, 472F398E1E251B8D009260FB /* MailAddress.swift in Sources */, @@ -2483,7 +2402,6 @@ F18B445E1E7044B70080C041 /* FlipTransition.swift in Sources */, 47C8225E24379EAE005BCE73 /* ReadMainView.swift in Sources */, 47FAE3122524BFDB005A1BCB /* PersistentDataError.swift in Sources */, - 472F397E1E1D0B0B009260FB /* EnzevalosContact+CoreDataProperties.swift in Sources */, 4751C6FA23449699006B2A4D /* CryptoManagementViewController.swift in Sources */, 478154AC21FF6A9600A931EC /* Mailbot.swift in Sources */, 8428A86E1F436A1E007649A5 /* BadgeCase.swift in Sources */, @@ -3063,26 +2981,6 @@ sourceTree = "<group>"; versionGroupType = wrapper.xcdatamodel; }; - A135267F1D955BDF00D3BFE1 /* enzevalos_iphone.xcdatamodeld */ = { - isa = XCVersionGroup; - children = ( - 47AAFA6B243CB58F00949015 /* enzevalos_iphone 11.xcdatamodel */, - 47D1BB052431F81C001F1EC9 /* enzevalos_iphone 10.xcdatamodel */, - 670159DF240FB4E800797FA5 /* enzevalos_iphone 9.xcdatamodel */, - 4751C6FD2344D169006B2A4D /* enzevalos_iphone 8.xcdatamodel */, - 4751C6F0233CE1E4006B2A4D /* enzevalos_iphone 7.xcdatamodel */, - A1909719220F887D00FA7B2A /* enzevalos_iphone 6.xcdatamodel */, - A15D2D0B21F4CF13007AF2F4 /* enzevalos_iphone 5.xcdatamodel */, - A19F3FFB21F0BE79005334F2 /* enzevalos_iphone 4.xcdatamodel */, - A19BD0A721ED62AE00E4D603 /* enzevalos_iphone 3.xcdatamodel */, - 47B2318A1F0D458100961B28 /* enzevalos_iphone 2.xcdatamodel */, - A13526801D955BDF00D3BFE1 /* enzevalos_iphone.xcdatamodel */, - ); - currentVersion = 47D1BB052431F81C001F1EC9 /* enzevalos_iphone 10.xcdatamodel */; - path = enzevalos_iphone.xcdatamodeld; - sourceTree = "<group>"; - versionGroupType = wrapper.xcdatamodel; - }; /* End XCVersionGroup section */ }; rootObject = A135266D1D955BDF00D3BFE1 /* Project object */; diff --git a/enzevalos_iphone/AddressHandler.swift b/enzevalos_iphone/AddressHandler.swift index 910c7ebf23219c13f4c149b082bd5f2b279f5083..dc7c79007173b4c269359b0efa9b288a345bdbcc 100644 --- a/enzevalos_iphone/AddressHandler.swift +++ b/enzevalos_iphone/AddressHandler.swift @@ -79,7 +79,7 @@ class AddressHandler { return list } - +/* TODO static var freqAlgorithm2: ([String]) -> [(UIImage, String, String, UIImage?, UIColor)] = { (inserted: [String]) -> [(UIImage, String, String, UIImage?, UIColor)] in @@ -131,7 +131,7 @@ class AddressHandler { return list - } + } */ static func getContact(_ name: String) -> [CNContact] { if name == "" { @@ -170,6 +170,7 @@ class AddressHandler { } /* [insertedEmail] -> [(contactImage, name, address, emailLabelImage, backgroundcolor)] */ + /* TODO static func frequentAddresses (_ inserted: [String]) -> [(UIImage, String, String, UIImage?, UIColor)] { let cons = DataHandler.handler.folderRecords(folderPath: UserManager.backendInboxFolderPath) var list: [(UIImage, String, String, UIImage?, UIColor)] = [] @@ -223,21 +224,20 @@ class AddressHandler { return list } - - static func findContact(_ econtact: EnzevalosContact) -> [CNContact] { +*/ + static func findContact(_ econtact: Contact) -> [CNContact] { var result = [CNContact]() - if let identifier = econtact.cnidentifier { + if let identifier = econtact.cnContact?.identifier { // 1. Look up identifier string result = getContactByID(identifier) } if result.count == 0 { - if let name = econtact.displayname?.trimmingCharacters(in: .decimalDigits) { - // 2. look for name - let query = getContact(name) - for res in query { - if (proveMatching(res, addresses: econtact.getMailAddresses())) { - result.append(res) - } + let name = econtact.name.trimmingCharacters(in: .decimalDigits) + // 2. look for name + let query = getContact(name) + for res in query { + if (proveMatching(res, addresses: econtact.getMailAddresses())) { + result.append(res) } } } @@ -283,17 +283,17 @@ class AddressHandler { static func updateCNContacts(save: Bool = true) { - let enzContacts = DataHandler.handler.getContacts() + let enzContacts = [Contact]() // TODODataHandler.handler.getContacts() for contact in enzContacts { let contacts = findContact(contact) if contact.cnContact == nil { if contacts.count > 0 { - contact.cnidentifier = contacts.first?.identifier + // TODO contact.cnContact = contacts.first?.identifier } } else if contacts.count > 0 && contact.cnContact != nil { - contact.cnidentifier = nil + //TODO contact.cnContact = nil } else if contacts.count > 0 { let cnContact = contacts.first @@ -312,18 +312,18 @@ class AddressHandler { } } if !hasSame { - contact.cnidentifier = nil + //TODO contact.cnContact = nil } } else { - contact.cnidentifier = nil + //TODO contact.cnContact = nil } } } if save { - DataHandler.handler.save(during: "updateCNContacts") + //TODO DataHandler.handler.save(during: "updateCNContacts") } } } diff --git a/enzevalos_iphone/AppDelegate.swift b/enzevalos_iphone/AppDelegate.swift index c215fcd10682dd043cd94bee27d14c46e256ad21..c835feb6c78fa67f40f880987f4e07f92666e0e8 100644 --- a/enzevalos_iphone/AppDelegate.swift +++ b/enzevalos_iphone/AppDelegate.swift @@ -29,12 +29,13 @@ import UserNotifications @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { - + typealias C = AddressRecord + typealias M = MailRecord var newOnboarding = true var newReadView = true - var inboxCoordinator: InboxCoordinator? = nil - var readViewCoordinator: ReadViewCoordinator? = nil + var inboxCoordinator: InboxCoordinator<M,C>? + var readViewCoordinator: ReadViewCoordinator<M, C>? var window: UIWindow? @@ -95,7 +96,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { if let con = window?.rootViewController { ItunesKeyHandling.simpleImportSecretKey(con: con) } - DataHandler.handler.startToSendMore() + // TODO DataHandler.handler.startToSendMore() } return true } @@ -146,7 +147,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Option removed from Settings app, but this might still be usefull in the future func resetApp() { if UserDefaults.standard.bool(forKey: "reset") { - DataHandler.handler.reset() + PersitentDataProvider.dataProvider.deleteAll(completionHandler: { error in + print("Delete All data") + //TODO What about the keychain? + }) Onboarding.credentials = nil Onboarding.credentialFails = 0 Onboarding.manualSet = false @@ -160,11 +164,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate { UserDefaults.standard.set(false, forKey: "reset") } } - +/* TODO func setupKeys() { DispatchQueue.main.async(execute: { self.window?.rootViewController = Onboarding.keyHandlingView() - }) + } + let handler = DataHandler.init() let keyId = handler.createNewSecretKey(adr: UserManager.loadUserValue(Attribute.userAddr) as! String) _ = handler.getContact(name: UserManager.loadUserValue(Attribute.accountname) as! String, address: UserManager.loadUserValue(Attribute.userAddr) as! String, key: keyId.keyID, prefer_enc: true) @@ -189,11 +194,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate { UserManager.storeUserValue(f.path as AnyObject?, attribute: Attribute.inboxFolderPath) } } + DispatchQueue.main.async(execute: { self.onboardingDone() });}) } - + */ func onboardingDone() { Logger.log(onboardingState: .Finish, duration: 0) UserDefaults.standard.set(true, forKey: "launchedBefore") diff --git a/enzevalos_iphone/Autocrypt.swift b/enzevalos_iphone/Autocrypt.swift index ad218766154dc27cf218d4f6556e05d72f7f6406..8b94e9cdff8c9c62e463ca154286194bdb72b675 100644 --- a/enzevalos_iphone/Autocrypt.swift +++ b/enzevalos_iphone/Autocrypt.swift @@ -106,9 +106,11 @@ class Autocrypt { } static func addAutocryptHeader(_ builder: MCOMessageBuilder) { + /* TODO guard let prefKey = DataHandler.handler.prefSecretKey() else { return } + let adr = (UserManager.loadUserValue(Attribute.userAddr) as! String).lowercased() let skID = prefKey.keyID let encPref = AutocryptState.MUTUAL @@ -120,15 +122,16 @@ class Autocrypt { string = string + "; \(KEY)=" + key builder.header.setExtraHeaderValue(string, forName: AUTOCRYPTHEADER) } + */ } static func recommandateEncryption (receiver: MailAddress) -> (hasAutocrypt: Bool, recommandEnc: Bool){ if receiver.hasKey, let key = receiver.primaryKey { - if key.prefer_encryption == .NOAUTOCRYPT { + if key.preferEncryption == AutocryptState.NOAUTOCRYPT.asInt() { return (false, ENFORCEENCRYPTION) } - else if key.prefer_encryption == .MUTUAL { + else if key.preferEncryption == AutocryptState.MUTUAL.asInt() { return (true, true) } return (true, false) diff --git a/enzevalos_iphone/CNMailAddressesExtension.swift b/enzevalos_iphone/CNMailAddressesExtension.swift index 11f5086e83ee2a109dd2cb5c3635041f87a2cb07..d2998304f7a62cb10de9acb42c3e3239fdb5b04b 100644 --- a/enzevalos_iphone/CNMailAddressesExtension.swift +++ b/enzevalos_iphone/CNMailAddressesExtension.swift @@ -31,9 +31,9 @@ open class CNMailAddressExtension: MailAddress { } } - public var primaryKey: PersistentKey? + public var primaryKey: PublicKeyRecord? - public var publicKeys: Set<PersistentKey> + public var publicKeys: Set<PublicKeyRecord> open var mailAddress: String { @@ -57,13 +57,13 @@ open class CNMailAddressExtension: MailAddress { } - open var Key: PersistentKey? { + open var Key: PublicKeyRecord? { get { return nil } } - open var contact: EnzevalosContact? { + open var contact: Contact? { get { return nil } @@ -71,7 +71,7 @@ open class CNMailAddressExtension: MailAddress { init(addr: CNLabeledValue<NSString>) { self.label = addr - self.publicKeys = Set<PersistentKey>() + self.publicKeys = Set<PublicKeyRecord>() } convenience init(addr: NSString) { diff --git a/enzevalos_iphone/Contact.swift b/enzevalos_iphone/Contact.swift index 938d0970bcb59be2eeac1fe077842626aa316a75..bb6c6f20504caae8aed29442695e5460516fc8ee 100644 --- a/enzevalos_iphone/Contact.swift +++ b/enzevalos_iphone/Contact.swift @@ -86,14 +86,9 @@ extension Contact { func getColor() -> UIColor { - if let enzCon = self as? EnzevalosContact { - if let color = enzCon.color { - return color - } - - enzCon.color = UIColor(hue: CGFloat(arc4random()) / CGFloat(UINT32_MAX), saturation: 1, brightness: 0.75, alpha: 1) - return enzCon.color! - } + + //enzCon.color = UIColor(hue: CGFloat(arc4random()) / CGFloat(UINT32_MAX), saturation: 1, brightness: 0.75, alpha: 1) + // TODO: How to calculate the color? // Overflow?! let prim = 653 diff --git a/enzevalos_iphone/ContactViewController.swift b/enzevalos_iphone/ContactViewController.swift index 9857f9b7ff35c9581f2eb5603096f749fee0509d..f253153e860f4d190b9731dcd26b055feb9ba380 100644 --- a/enzevalos_iphone/ContactViewController.swift +++ b/enzevalos_iphone/ContactViewController.swift @@ -25,13 +25,13 @@ import ContactsUI class ContactViewController: UIViewController { static let HideVerifycation = true - var keyRecord: KeyRecord? = nil + var keyRecord: Contact? = nil var addressWithKey: MailAddress? /// This email will be highlighted blue to indicate from which addres a mail was received var highlightEmail: String? = nil private var uiContact: CNContact? = nil private var vc: CNContactViewController? = nil - fileprivate var otherRecords: [KeyRecord]? = nil + fileprivate var otherRecords: [Contact]? = nil var isUser: Bool = false @IBOutlet weak var tableView: UITableView! @@ -49,25 +49,25 @@ class ContactViewController: UIViewController { self.navigationController?.navigationBar.barTintColor = ThemeManager.defaultColor if let con = keyRecord { - for adr in con.ezContact.addresses { + for adr in con.getMailAddresses() { let a = adr as! MailAddress if a.hasKey { addressWithKey = a } } - - + self.title = con.name //TODO REMOVE + /* if let record = keyRecord, record.isUser { self.title = NSLocalizedString("you", comment: "String decribing this as the account of the user") isUser = true } else { self.title = con.name - } + }*/ prepareContactSheet() - otherRecords = con.ezContact.records.filter({ $0 != keyRecord }).sorted() - Logger.log(contactViewOpen: self.keyRecord, otherRecords: self.otherRecords, isUser: self.isUser) + //TODO otherRecords = con.ezContact.records.filter({ $0 != keyRecord }).sorted() + //Logger.log(contactViewOpen: self.keyRecord, otherRecords: self.otherRecords, isUser: self.isUser) let feedbackButton = UIBarButtonItem(title: FeedbackButtonHelper.Name, style: .plain, target: self, action:#selector(feedback)) let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil) diff --git a/enzevalos_iphone/DataHandler.swift b/enzevalos_iphone/DataHandler.swift deleted file mode 100644 index 29253e0b71d24b2161b98c91175145e82e5fb0d4..0000000000000000000000000000000000000000 --- a/enzevalos_iphone/DataHandler.swift +++ /dev/null @@ -1,1162 +0,0 @@ -// -// DataHandler.swift -// enzevalos_iphone -// -// Created by Oliver Wiese on 29/12/16. -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. -// - -import UIKit -import CoreData -import Contacts -// FIXME: comparison operators with optionals were removed from the Swift Standard Libary. -// Consider refactoring the code to use the non-optional operators. -fileprivate func < <T : Comparable>(lhs: T?, rhs: T?) -> Bool { - switch (lhs, rhs) { - case let (l?, r?): - return l < r - case (nil, _?): - return true - default: - return false - } -} - -// FIXME: comparison operators with optionals were removed from the Swift Standard Libary. -// Consider refactoring the code to use the non-optional operators. -fileprivate func > <T : Comparable>(lhs: T?, rhs: T?) -> Bool { - switch (lhs, rhs) { - case let (l?, r?): - return l > r - default: - return rhs < lhs - } -} - - -fileprivate func == (lhs: NSDate, rhs: NSDate) -> Bool { - return lhs === rhs || lhs.compare(rhs as Date) == .orderedSame -} - -fileprivate func < (lhs: NSDate, rhs: NSDate) -> Bool { - return lhs.compare(rhs as Date) == .orderedAscending - -} - -typealias requestTuple = (request: String, value: Any) - -class DataHandler { - static let handler: DataHandler = DataHandler() - - private var mainMOC: NSManagedObjectContext - private var backMOC: NSManagedObjectContext - var managedObjectContext: NSManagedObjectContext { - get { - if Thread.current.isMainThread { - return mainMOC - } - else { - return backMOC - } - } - } - /** - Make coredata available to SwiftUI - See: https://www.hackingwithswift.com/quick-start/swiftui/how-to-configure-core-data-to-work-with-swiftui - */ - lazy var persistentContainer: NSPersistentContainer = { - let container = NSPersistentContainer(name: "enzevalos_iphone") - container.loadPersistentStores { description, error in - if let error = error { - fatalError("Could not load data...") - } - } - return container - }() - - func saveContext () { - let context = persistentContainer.viewContext - if context.hasChanges { - do { - try context.save() - } catch { - // Show the error here - } - } - } - - - public let outgoingFolder = "OutgoingMails" - - func addOutgoingMail(mail: OutgoingMail) { - let outgoingFolder = findFolder(with: self.outgoingFolder) - let isOnlyMail = outgoingFolder.counterMails == 0 - _ = mail.store() - if isOnlyMail { - mail.send(informUser: true) - } - } - - func startToSendMore(){ - let outgoingFolder = findFolder(with: self.outgoingFolder) - if outgoingFolder.counterMails == 0 { - return - } - let m = OutgoingMail(mail: outgoingFolder.mailsOfFolder[0]) - m.send() - } - - var allFolders: [Folder] { - get { - var folders = [Folder]() - if let objects = findAll("Folder") { - for case let folder as Folder in objects { - folders.append(folder) - } - } - return folders - } - } - - //All Folders, which are not a subfolder - var allRootFolders: [Folder] { - var root: [Folder] = [] - for f in allFolders { - if !f.path.contains(f.delimiter) { - root.append(f) - } - } - return root - } - - func callForFolders(done: @escaping ((_ error: Error?) -> ())) { // Maybe call back? Look for new Folder? - AppDelegate.getAppDelegate().mailHandler.allFolders { (err, array) -> Void in - guard err == nil else { - done(err) - return - } - - if let newFolders = array { - for new in newFolders { - if case let folder as MCOIMAPFolder = new { - let f = self.findFolder(with: folder.path) - f.delimiter = String(Character(UnicodeScalar(UInt8(folder.delimiter)))) - f.flags = folder.flags - } - } - } - done(nil) - } - } - - func allMailsInFolder(key: String?, contact: EnzevalosContact?, folder: Folder?, isSecure: Bool?, searchForRelatedKeys: Bool = false) -> [PersistentMail] { - let fReq = NSFetchRequest<NSFetchRequestResult>(entityName: "PersistentMail") - var predicates = [NSPredicate]() - if let k = key, k != "" { - if let keyObject = findKey(keyID: k), searchForRelatedKeys { - var subPredicates: [NSPredicate] = [] - for singleKey in keyObject.relatedKeys { - subPredicates.append(NSPredicate(format: "signedKey.keyID = %@", singleKey.keyID)) - } - predicates.append(NSCompoundPredicate.init(orPredicateWithSubpredicates: subPredicates)) - } else { - predicates.append(NSPredicate(format: "signedKey.keyID = %@", k)) - } - } - if let c = contact { - if c.getMailAddresses().count == 0 { - } else { - let adr: Mail_Address = c.getMailAddresses()[0] as! Mail_Address - predicates.append(NSPredicate(format: "from == %@", adr)) - } - } - if let f = folder { - predicates.append(NSPredicate(format: "folder == %@", f)) - } - let andPredicates = NSCompoundPredicate(andPredicateWithSubpredicates: predicates) - - fReq.predicate = andPredicates - fReq.sortDescriptors = [NSSortDescriptor(key: "date", ascending: false)] - if let result = (try? self.managedObjectContext.fetch(fReq)) as? [PersistentMail] { - if let isSecure = isSecure { - if isSecure { - let secureMails = result.filter({ - return $0.isSecure - }) - return secureMails - } else { - let inSecureMails = result.filter({ - return !$0.isSecure - }) - return inSecureMails - - } - } - return result - } - return [] - } - - - init() { - // This resource is the same name as your xcdatamodeld contained in your project. - guard let modelURL = Bundle.main.url(forResource: "enzevalos_iphone", withExtension: "momd") else { - fatalError("Error loading model from bundle") - } - // The managed object model for the application. It is a fatal error for the application not to be able to find and load its model. - guard let mom = NSManagedObjectModel(contentsOf: modelURL) else { - fatalError("Error initializing mom from: \(modelURL)") - } - let psc = NSPersistentStoreCoordinator(managedObjectModel: mom) - self.mainMOC = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType) // This is why we have trouble with concurrency: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/Concurrency.html - self.mainMOC.persistentStoreCoordinator = psc - - let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) - let docURL = urls[urls.endIndex - 1] - /* The directory the application uses to store the Core Data store file. - This code uses a file named "DataModel.sqlite" in the application's documents directory. - */ - let storeURL = docURL.appendingPathComponent("enzevalos_iphone.sqlite") - do { - let options = [ NSInferMappingModelAutomaticallyOption : true, - NSMigratePersistentStoresAutomaticallyOption : true] - try psc.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: storeURL, options: options) - } catch { - fatalError("Error migrating store: \(error)") - } - mainMOC.mergePolicy = NSMergePolicy(merge: NSMergePolicyType.mergeByPropertyObjectTrumpMergePolicyType); - backMOC = NSManagedObjectContext.init(concurrencyType: .privateQueueConcurrencyType) - backMOC.parent = mainMOC - - callForFolders(done: { _ in return }) - - } - - func terminate() { - save(during: "Terminating") - } - - func save(during: String) { - do { - try managedObjectContext.save() - } catch { - print("Error during saving while: \(during)") - NSLog("Error during saving while %@", during) - } - } - - private func deleteNum(_ entityName: String, type: String, search: UInt64) { - let fReq: NSFetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entityName) - fReq.predicate = NSPredicate(format: "\(type) = %D ", search) - if let result = (try? self.managedObjectContext.fetch(fReq)) as? [NSManagedObject] { - for object in result { - self.managedObjectContext.delete(object) - } - save(during: "delete num") - } - } - - func delete(mail: PersistentMail) { - self.managedObjectContext.delete(mail as NSManagedObject) - save(during: "delete ") - } - - private func delete(key: SecretKey) { - self.managedObjectContext.delete(key as NSManagedObject) - save(during: "delete SecretKey") - } - - func delete(mail: OutgoingMail) { - if let m = mail.store() { - delete(mail: m) - } - } - - func deleteSecretKeys() { - let keys = findSecretKeys() - let pgp = SwiftPGP() - pgp.deleteSecretKeys() - for key in keys { - if let mails = key.decryptedMails as? Set<PersistentMail> { - for mail in mails { - mail.decryptedKey = nil - } - } - delete(key: key) - } - } - - 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) - } - - private func removeAll(entity: String) { - let DelAllReqVar = NSBatchDeleteRequest(fetchRequest: NSFetchRequest<NSFetchRequestResult>(entityName: entity)) - do { - try managedObjectContext.execute(DelAllReqVar) - } catch { - print(error) - } - } - - func reset() { - removeAll(entity: "PersistentMail") - removeAll(entity: "Folder") - removeAll(entity: "EnzevalosContact") - removeAll(entity: "SecretKey") - removeAll(entity: "PersistentKey") - removeAll(entity: "Mail_Address") - save(during: "reset") - } - - // Save, load, search - func newSecretKey(keyID: String, addPk: Bool, saveKey: Bool = true) -> SecretKey { - let sk: SecretKey - if let key = findSecretKey(keyID: keyID) { - sk = key - } else { - sk = NSEntityDescription.insertNewObject(forEntityName: "SecretKey", into: managedObjectContext) as! SecretKey - sk.keyID = keyID - sk.obsolete = false - sk.importedDate = Date() as NSDate - UserManager.storeUserValue(keyID as AnyObject, attribute: Attribute.prefSecretKeyID) - let adr = UserManager.loadUserValue(Attribute.userAddr) as! String - let name = adr // TODO Change here displayname - _ = getContact(name: name, address: adr, key: keyID, prefer_enc: true) - if addPk { - _ = newPublicKey(keyID: keyID, cryptoType: CryptoScheme.PGP, adr: adr, autocrypt: false, transferType: nil) - } - } - if saveKey { - save(during: "new sk") - } - return sk - } - - func newSecretKeys(keyIds: [String], addPKs: Bool) -> [SecretKey] { - var sks = [SecretKey]() - for id in keyIds { - sks.append(newSecretKey(keyID: id, addPk: addPKs)) - } - return sks - } - - func createNewSecretKey(adr: String) -> SecretKey { - let keys = findSecretKeys() - if keys.count > 0 { - return findSecretKeys().first! - } - let pgp = SwiftPGP() - let key = pgp.generateKey(adr: adr) - let sk = DataHandler.handler.newSecretKey(keyID: key, addPk: false) - let pk = DataHandler.handler.newPublicKey(keyID: key, cryptoType: CryptoScheme.PGP, adr: adr, autocrypt: false, newGenerated: true, transferType: nil) - pk.sentOwnPublicKey = true - return sk - } - - func newPublicKey(keyID: String, cryptoType: CryptoScheme, adr: String, autocrypt: Bool, firstMail: PersistentMail? = nil, newGenerated: Bool = false, saveKey: Bool = true, transferType: LogData.TransferType?) -> PersistentKey { - var date = Date.init() - if let mail = firstMail { - if date.compare(mail.date).rawValue > 0 { - date = mail.date - } - } - let adr = getMailAddress(adr, temporary: false) as! Mail_Address - var pk: PersistentKey - if let search = findKey(keyID: keyID) { - if search.lastSeen < date { - search.lastSeen = date - if search.lastSeen > search.currentlyActiveKey.lastSeen { - search.currentlyActiveKey = search - let repeals = AppDelegate.getAppDelegate().mailHandler.getRepeals(for: search.keyID) - if search.repealed, let first = repeals.first { - var maxRepeal = first - for repeal in repeals { - if repeal.date > maxRepeal.date && repeal.date <= Date.init() { - maxRepeal = repeal - } - } - if maxRepeal.date < date { - search.repealed = false - } - } - } - } - if autocrypt { - if search.lastSeenAutocrypt < date { - search.lastSeenAutocrypt = date - } - search.sentOwnPublicKey = true - } - search.addToMailaddresses(adr) - pk = search - if Logger.logging { - var importChannel = LogData.TransferType.autocrypt - if newGenerated { - importChannel = LogData.TransferType.generated - } else if let transferType = transferType { - importChannel = transferType - } else if !autocrypt { - importChannel = .mail - } - Logger.log(discover: pk.keyID, mailAddress: adr, importChannel: importChannel, knownPrivateKey: DataHandler.handler.findSecretKeys().map { ($0.keyID) == keyID }.reduce(false, { $0 || $1 }), knownBefore: true) - } - } else { - pk = NSEntityDescription.insertNewObject(forEntityName: "PersistentKey", into: managedObjectContext) as! PersistentKey - pk.addToMailaddresses(adr) - pk.keyID = keyID - pk.encryptionType = cryptoType - pk.lastSeen = date - pk.discoveryDate = date - pk.firstMail = firstMail - if autocrypt { - pk.lastSeenAutocrypt = date - pk.sentOwnPublicKey = true - } - var found = false - while !found { - let pseudo = String.random() - let response = find("PersistentKey", type: "pseudonym", search: pseudo) as? [PersistentKey] - if (response ?? []).count == 0 || response![0].pseudonym == "" { - pk.pseudonym = pseudo - found = true - } - } - if saveKey{ - save(during: "new pk") - } - if Logger.logging { - var importChannel = LogData.TransferType.autocrypt - if newGenerated { - importChannel = .generated - } else if !autocrypt { - importChannel = .mail - } - Logger.log(discover: pk.keyID, mailAddress: adr, importChannel: importChannel, knownPrivateKey: DataHandler.handler.findSecretKeys().map { ($0.keyID) == keyID }.reduce(false, { $0 || $1 }), knownBefore: false) - } - } - let travelHandler = TravelHandler.instance() - if let prim = adr.primaryKey, let last = prim.lastSeen, let currentLast = pk.lastSeen { - if last < currentLast && travelHandler.mode != .borderCrossing { - adr.primaryActiveKeyID = pk.keyID - } - } - else if travelHandler.mode != .borderCrossing { - adr.primaryActiveKeyID = keyID - } - if saveKey { - save(during: "new PK") - } - adr.addToKeys(key: pk) - return pk - } - - func prefSecretKey() -> SecretKey? { - guard TravelHandler.instance().mode != .borderCrossing else { - return nil - } - if let prefId = UserManager.loadUserValue(Attribute.prefSecretKeyID) { - if let id = prefId as? String { - if let key = findSecretKey(keyID: id) { - return key - } - } - } - var allSKs = findSecretKeys() - allSKs = allSKs.sorted(by: { ($0.importedDate)! < ($1.importedDate)! }) - if allSKs.count > 0 { - UserManager.storeUserValue(allSKs[0].keyID as AnyObject, attribute: Attribute.prefSecretKeyID) - return allSKs[0] - } - if let adr = UserManager.loadUserValue(Attribute.userAddr) { - if let adrString = adr as? String { - return createNewSecretKey(adr: adrString) - } - } - return createNewSecretKey(adr: "") - } - - func changePrefKey(newPrefKey: SecretKey) { - UserManager.storeUserValue(newPrefKey.keyID as AnyObject, attribute: Attribute.prefSecretKeyID) - } - - func findSecretKeys() -> [SecretKey] { - if let result = findAll("SecretKey") { - return result as! [SecretKey] - } - return [SecretKey]() - } - - func findPublicKeys() -> [PersistentKey] { - if let result = findAll("PersistentKey") { - return result as! [PersistentKey] - } - return [PersistentKey]() - } - - func findSecretKey(keyID: String) -> SecretKey? { - if let result = find("SecretKey", type: "keyID", search: keyID) { - for r in result { - return r as? SecretKey - } - } - return nil - } - - func findKey(keyID: String) -> PersistentKey? { - if let result = find("PersistentKey", type: "keyID", search: keyID) { - for r in result { - return r as? PersistentKey - } - } - return nil - } - - private func find(_ entityName: String, type: String, search: String) -> [AnyObject]? { - let fReq: NSFetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entityName) - fReq.predicate = NSPredicate(format: "\(type) CONTAINS %@ ", search) - let result: [AnyObject]? - do { - result = try self.managedObjectContext.fetch(fReq) - } catch _ as NSError { - result = nil - return nil - } - return result - } - - private func findNum (_ entityName: String, type: String, search: UInt64) -> [AnyObject]? { - let fReq: NSFetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entityName) - fReq.predicate = NSPredicate(format: "\(type) = %D ", search) - let result: [AnyObject]? - do { - result = try self.managedObjectContext.fetch(fReq) - } catch _ as NSError { - result = nil - return nil - } - return result - } - - private func findAll(_ entityName: String) -> [AnyObject]? { - let fReq: NSFetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entityName) - if entityName == "KeyRecord" { - let sortDescriptor = NSSortDescriptor(key: "newestDate", ascending: false) - fReq.sortDescriptors = [sortDescriptor] - } - else if entityName == "PersistentMail" { - let sortDescriptor = NSSortDescriptor(key: "date", ascending: false) - fReq.sortDescriptors = [sortDescriptor] - } - let result: [AnyObject]? - do { - result = try self.managedObjectContext.fetch(fReq) - } catch _ as NSError { - result = nil - return nil - } - return result - } - - func newAttachment(temp: TempAttachment, mail: PersistentMail) -> Attachment{ - let entityName = "Attachment" - if let attachments = mail.attachments, attachments.count > 0 { - for at in attachments { - if let at = at as? Attachment { - if temp.equal(at: at) { - return at - } - } - } - } - let attachment = NSEntityDescription.insertNewObject(forEntityName: entityName, into: managedObjectContext) as! Attachment - attachment.name = temp.name - attachment.data = temp.data - attachment.mimeType = temp.mimeType.rawValue - attachment.encryptionState = temp.encState.rawValue - attachment.signatureState = temp.sigState.rawValue - attachment.mail = mail - mail.addToAttachments(attachment) - save(during: "Create attachment") - return attachment - } - - func findFolder(with path: String) -> Folder { - if let search = find("Folder", type: "path", search: path) { - if search.count > 0 { - return search[0] as! Folder - } - } - let folder = NSEntityDescription.insertNewObject(forEntityName: "Folder", into: managedObjectContext) as! Folder - folder.path = path - var found = false - while !found { - let pseudo = String.random() - let response = find("Folder", type: "pseudonym", search: pseudo) as? [Folder] - if (response ?? []).count == 0 || response![0].pseudonym == "" { - folder.pseudonym = pseudo - found = true - } - } - return folder - } - - func existsFolder(with path: String) -> Bool { - if let search = find("Folder", type: "path", search: path), search.count > 0 { - return true - } - return false - } - - func getKeyRecord(addr: String, keyID: String?, saveRecord: Bool = true) -> KeyRecord { - if let id = keyID { - if let key = findKey(keyID: id) { - if let record = key.keyRecord { - return record - } - // Create KeyRecord - let record = NSEntityDescription.insertNewObject(forEntityName: "KeyRecord", into: managedObjectContext) as! KeyRecord - record.key = key - if let contact = getContact(keyID: id) { - record.contact = contact - } - else { - record.contact = getContactByAddress(addr) - } - if saveRecord { - save(during: "create keyRecord with key") - } - return record - } - } - - if let address = findMailAddress(adr: addr) { - if let contact = address.contact { - for record in contact.records { - if !record.hasKey { - for a in record.addresses { - if a.mailAddress == addr { - return record - } - } - } - } - } - } - // create KeyRecord - let record = NSEntityDescription.insertNewObject(forEntityName: "KeyRecord", into: managedObjectContext) as! KeyRecord - record.contact = getContactByAddress(addr) - if saveRecord { - save(during: "create keyRecord without key") - } - return record - } - - // -------- Handle mail addresses --------- - func getMailAddress(_ address: String, temporary: Bool) -> MailAddress { - let adr = address.lowercased() - let search = find("Mail_Address", type: "address", search: adr) - if search == nil || search!.count == 0 { - if temporary { - return CNMailAddressExtension(addr: adr as NSString) - } else { - let mail_address = NSEntityDescription.insertNewObject(forEntityName: "Mail_Address", into: managedObjectContext) as! Mail_Address - mail_address.address = adr - var found = false - while !found { - let pseudo = String.random() - let response = find("Mail_Address", type: "pseudonym", search: pseudo) as? [Mail_Address] - if (response ?? []).count == 0 || response![0].pseudonym == "" { - mail_address.pseudonym = pseudo - found = true - } - } - return mail_address - } - } else { - return search![0] as! Mail_Address - } - } - - func findMailAddress(adr: String) -> Mail_Address? { - if let search = find("Mail_Address", type: "address", search: adr) { - if search.count > 0 { - return search[0] as? Mail_Address - } - } - return nil - } - - func findMailAddress(withKey: Bool) -> [Mail_Address] { - let fReq: NSFetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Mail_Address") - if withKey { - fReq.predicate = NSPredicate(format: "keys.@count > 0") - } - else { - fReq.predicate = NSPredicate(format: "keys.@count == 0") - } - do { - let result = try self.managedObjectContext.fetch(fReq) - if let res = result as? [Mail_Address] { - return res - } - } catch _ as NSError { - print("error") - } - return [Mail_Address]() - } - - - func getMailAddressByMCOAddress(_ address: MCOAddress, temporary: Bool) -> MailAddress { - return getMailAddress(address.mailbox!, temporary: temporary) - } - - func getMailAddressesByMCOAddresses(_ addresses: [MCOAddress]) -> [Mail_Address] { - var mailaddresses = [Mail_Address]() - for adr in addresses { - mailaddresses.append(getMailAddressByMCOAddress(adr, temporary: false) as! Mail_Address) - } - return mailaddresses - } - - - // -------- Start Access to contact(s) -------- - // Find one or a list of enzevalos contacts - // By mail-address via String or MCOAddress - // If no enzevalos contact exists. One is created. - - func getContactByAddress(_ address: String) -> EnzevalosContact { - let lowerAdr = address.lowercased() - if let mailAdr = findMailAddress(adr: address) { - if let contact = mailAdr.contact { - return contact - } - } - if let contacts = findAll("EnzevalosContact") { - for c in contacts { - if case let contact as EnzevalosContact = c { - for adr in contact.addresses { - if case let mailAdr as Mail_Address = adr { - if mailAdr.address == address { - return contact - } - } - } - if let cnContact = contact.cnContact { - for adr in cnContact.emailAddresses { - let name = adr.value as String - if name == lowerAdr { - let adr = getMailAddress(lowerAdr, temporary: false) as! Mail_Address - c.addToAddresses(adr) - adr.contact = contact - return contact - } - } - } - } - } - } - var contact: EnzevalosContact - contact = NSEntityDescription.insertNewObject(forEntityName: "EnzevalosContact", into: managedObjectContext) as! EnzevalosContact - contact.displayname = lowerAdr - let adr = getMailAddress(lowerAdr, temporary: false) as! Mail_Address - adr.contact = contact - let cncontacts = AddressHandler.findContact(contact) - if cncontacts.count > 0 { - contact.cnidentifier = cncontacts.first?.identifier - } - return contact - } - - func getContact(keyID: String) -> EnzevalosContact? { - if let key = findKey(keyID: keyID) { - if let adrs = key.mailaddresses { - for item in adrs { - let adr = item as! Mail_Address - if adr.contact != nil { - return adr.contact - } - } - } - } - return nil - } - - func getContact(name: String, address: String, key: String, prefer_enc: Bool) -> EnzevalosContact { - let contact = getContactByAddress(address) - contact.displayname = name - if let mykey = findKey(keyID: key) { - contact.getAddress(address)?.addToKeys(key: mykey) - } - return contact - } - - func getContactByMCOAddress(address: MCOAddress) -> EnzevalosContact { - let contact = getContactByAddress(address.mailbox!) - if address.displayName != nil { - contact.displayname = address.displayName - } - return contact - } - // -------- End Access to contact(s) -------- - - - // -------- Start handle to, cc, from addresses -------- - private func handleFromAddress(_ sender: MCOAddress, fromMail: PersistentMail, autocrypt: Autocrypt?) { - let adr: Mail_Address - adr = getMailAddressByMCOAddress(sender, temporary: false) as! Mail_Address - if adr.contact == nil { - adr.contact = getContactByMCOAddress(address: sender) - } - if let contact = adr.contact { - if !(contact.addresses.contains(adr)) { - contact.addToAddresses(adr) - } - } - fromMail.from = adr - } - - private func handleToAddresses(_ receivers: [MCOAddress], mail: PersistentMail) { - mail.addToTo(NSSet(array: getMailAddressesByMCOAddresses(receivers))) - } - - private func handleCCAddresses(_ cc: [MCOAddress], mail: PersistentMail) { - mail.addToCc(NSSet(array: getMailAddressesByMCOAddresses(cc))) - } - - private func findMail(msgID: String) -> PersistentMail? { - if let result = find("PersistentMail", type: "messageID", search: msgID) as?[PersistentMail] { - if result.count > 0 { - return result[0] - } - } - return nil - } - - func removeAttachments() -> Int { - var safedStorage = 0 - var counterAttachments = 0 - var counterManipulatedMails = 0 - for m in getAllPersistentMails() { - if m.hasAttachment { - counterManipulatedMails += 1 - if let atts = m.attachments { - counterAttachments += atts.count - for x in atts { - if let data = x as? Attachment { - safedStorage += data.data?.count ?? 0 - m.removeFromAttachments(data) - } - } - } - } - } - return safedStorage - } - // -------- 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, isKeyImported: Bool = true, attachedSignature: Data? = nil) -> PersistentMail? { - - guard let sender = sender else { - return nil - } - let myfolder = findFolder(with: folderPath) as Folder - let finding = findNum("PersistentMail", type: "uid", search: uid) - - let mail: PersistentMail - var mails: [PersistentMail] = [] - - if let tmpMails = finding as? [PersistentMail] { - mails = tmpMails - } - if finding == nil || finding!.count == 0 || mails.filter({ $0.folder.path == folderPath}).count == 0 || uid == 0 || !myfolder.uids.contains(uid) { - // create new mail object - mail = NSEntityDescription.insertNewObject(forEntityName: "PersistentMail", into: managedObjectContext) as! PersistentMail - - let now = Date.init() - if time <= now { - mail.date = time - } else { - mail.date = now - } - mail.subject = subject - if !storeEncrypted, let body = body { - mail.body = body - } else { - mail.body = nil - } - // relatedSecretKey - mail.secretKey = secretKey - - mail.folder = myfolder - mail.uidvalidity = myfolder.uidvalidity - mail.uid = uid - mail.messageID = messageID - mail.xMailer = mailagent - mail.encryptedBody = encryptedBody - mail.repealsKey = nil - - mail.flag = flags - // Default values - mail.isSigned = false - mail.isEncrypted = false - mail.trouble = false - mail.unableToDecrypt = false - mail.storeEncrypted = storeEncrypted - mail.received = received - mail.attachedSignature = attachedSignature - - handleFromAddress(sender, fromMail: mail, autocrypt: autocrypt) - - handleToAddresses(receivers, mail: mail) - handleCCAddresses(cc, mail: mail) - - - if let decData = decryptedData { - let encState: EncryptionState = decData.encryptionState - let signState: SignatureState = decData.signatureState - - switch encState { - case EncryptionState.NoEncryption: - mail.isEncrypted = false - mail.trouble = false - mail.unableToDecrypt = false - case EncryptionState.UnableToDecrypt: - mail.unableToDecrypt = true - mail.isEncrypted = true - mail.trouble = false - case EncryptionState.ValidEncryptedWithOldKey: - mail.isEncrypted = true - mail.trouble = false - mail.unableToDecrypt = false - if !storeEncrypted { - mail.decryptedBody = body - } - mail.decryptedWithOldPrivateKey = true - case EncryptionState.ValidedEncryptedWithCurrentKey: - mail.isEncrypted = true - mail.trouble = false - mail.unableToDecrypt = false - if !storeEncrypted { - mail.decryptedBody = body - } - } - - switch signState { - case SignatureState.NoSignature: - mail.isSigned = false - case SignatureState.NoPublicKey: - mail.isSigned = true - mail.isCorrectlySigned = false - case SignatureState.InvalidSignature: - mail.isSigned = true - mail.isCorrectlySigned = false - mail.trouble = true - case SignatureState.ValidSignature: - mail.isCorrectlySigned = true - mail.isSigned = true - if let signedKey = findKey(keyID: decData.signKey!) { - mail.signedKey = signedKey - mail.keyID = signedKey.keyID - if let lastSeen = signedKey.currentlyActiveKey.lastSeen, lastSeen < time { - signedKey.currentlyActiveKey = signedKey - signedKey.lastSeen = lastSeen - let repeals = AppDelegate.getAppDelegate().mailHandler.getRepeals(for: signedKey.keyID) - if signedKey.repealed, let first = repeals.first { - var maxRepeal = first - for repeal in repeals { - if repeal.date > maxRepeal.date && repeal.date <= Date.init() { - maxRepeal = repeal - } - } - if maxRepeal.date < time { - signedKey.repealed = false - } - } - } - } - else { - mail.signedKey = newPublicKey(keyID: decData.signKey!, cryptoType: decData.encType, adr: decData.signedAdrs.first!, autocrypt: false, firstMail: mail, newGenerated: false, saveKey: false, transferType: nil) - } - - } - } - else { - // Maybe PGPInline? - // TODO: Refactoring! - } - } - else { - return nil - } - myfolder.addToMails(mail) - if mail.uid > myfolder.maxID { - myfolder.maxID = mail.uid - } - var record = getKeyRecord(addr: mail.from.mailAddress, keyID: nil, saveRecord: false) - if let signedID = mail.signedKey?.keyID, mail.isSecure { - record = getKeyRecord(addr: mail.from.mailAddress, keyID: signedID, saveRecord: false) - } - record.addToPersistentMails(mail) - mail.folder.addToKeyRecords(record) - if record.firstMail == nil { - record.firstMail = mail - } else if let first = record.firstMail, mail < first { - record.firstMail = mail - record.secondMail = first - } else if let second = record.secondMail, mail < second { - record.secondMail = mail - } - let isInbox = mail.folder.path == Folder.inbox.path - - if record.newestDate == nil, isInbox { - record.newestDate = mail.date - } - if let date = record.newestDate, date.timeIntervalSince(mail.date) < 0, isInbox { - // We should update our records... - record.newestDate = mail.date - } - - for at in readableAttachments{ - _ = self.newAttachment(temp: at, mail: mail) - } - save(during: "new mail") - return mail - } - - func getAddresses() -> [MailAddress] { - var adrs = [MailAddress]() - let result = findAll("Mail_Address") - if result != nil { - for r in result! { - let adr = r as! MailAddress - adrs.append(adr) - } - } - return adrs - } - - func getContacts() -> [EnzevalosContact] { - var contacts = [EnzevalosContact]() - let result = findAll("EnzevalosContact") - if result != nil { - for r in result! { - let c = r as! EnzevalosContact - let ms = c.from - if ms.count > 0 { - contacts.append(c) - } - } - } - return contacts - } - - func hasKey(adr: String) -> Bool { - if let madr = findMailAddress(adr: adr) { - return madr.hasKey - } - return false - } - - func folderRecords(folderPath: String) -> [KeyRecord] { - let folder = findFolder(with: folderPath) as Folder - return folder.records - } - - func getAllKeyRecords() -> [KeyRecord] { - var result: [KeyRecord] = [] - if let records = findAll("KeyRecord") as? [KeyRecord] { - result = records.filter{ - if let mails = $0.persistentMails { - return mails.count != 0 - } - return false - } - } - return result - } - - func findRecordsInbox() -> [KeyRecord] { - let fReq: NSFetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "KeyRecord") - fReq.predicate = NSPredicate(format: "persistentMails.@count > 0") - let sortDescriptor = NSSortDescriptor(key: "newestDate", ascending: false) - fReq.sortDescriptors = [sortDescriptor] - - do { - let result = try self.managedObjectContext.fetch(fReq) - if let res = result as? [KeyRecord] { - return res - } - } catch _ as NSError { - print("error") - } - return [KeyRecord]() - - } - - func getAllPersistentMails() -> [PersistentMail] { - if let mails = findAll("PersistentMail") as? [PersistentMail] { - return mails - } - return [] - } - - /** - Filters all Presistent Mails with encState == EncryptionState.UnableToDecrypt - */ - func getAllNotDecryptedPersistentMail() -> [PersistentMail] { - let result = getAllPersistentMails().filter({ $0.encState == EncryptionState.UnableToDecrypt }) - return result - } - - /** - Filters all Presistent Mails with sigState == SignatureState.NoPublicKey - */ - func getAllNotSignedPersistentMail() -> [PersistentMail] { - let result = getAllPersistentMails().filter({ $0.sigState == SignatureState.NoPublicKey }) - return result - } - - func deleteDecryptedMailCopies() { - let secureMails = getAllPersistentMails().filter({ $0.isSecure }) - for mail in secureMails { - mail.decryptedBody = nil - mail.body = nil - mail.deleteWhileTravel = true - if let attachments = mail.attachments { - mail.attachments = NSSet(array: attachments.filter({ - if let attachment = $0 as? Attachment { - return attachment.encryptionState <= 0 - } - return false - })) - } - - } - } -} diff --git a/enzevalos_iphone/DateExtension.swift b/enzevalos_iphone/DateExtension.swift index e4c361792260ee7e83067b12834734fa6b43c839..8292566807c7d87662d6cd32b503754f3298075e 100644 --- a/enzevalos_iphone/DateExtension.swift +++ b/enzevalos_iphone/DateExtension.swift @@ -57,4 +57,31 @@ extension Date{ } return self.description(with: .autoupdatingCurrent) } + // TODO: Refactor -> Other name + var dateToString: String { + get { + var returnString = "" + let dateFormatter = DateFormatter() + dateFormatter.locale = Locale.current + let mailTime = self + let interval = Date().timeIntervalSince(mailTime as Date) + switch interval { + case -55..<55: + returnString = NSLocalizedString("Now", comment: "New email") + case 55..<120: + returnString = NSLocalizedString("OneMinuteAgo", comment: "Email came one minute ago") + case 120..<24 * 60 * 60: + dateFormatter.timeStyle = .short + returnString = dateFormatter.string(from: mailTime as Date) + case 86400..<172800: //24 * 60 * 60..<48 * 60 * 60: + returnString = NSLocalizedString("Yesterday", comment: "Email came yesterday") + case 172800..<259200: //48 * 60 * 60..<72 * 60 * 60: + returnString = NSLocalizedString("TwoDaysAgo", comment: "Email came two days ago") + default: + dateFormatter.dateStyle = .short + returnString = dateFormatter.string(from: mailTime as Date) + } + return returnString + } + } } diff --git a/enzevalos_iphone/EnzevalosContact+CoreDataClass.swift b/enzevalos_iphone/EnzevalosContact+CoreDataClass.swift deleted file mode 100644 index d1408ebc3442853f002e1e866715feefd385e93d..0000000000000000000000000000000000000000 --- a/enzevalos_iphone/EnzevalosContact+CoreDataClass.swift +++ /dev/null @@ -1,316 +0,0 @@ -// -// EnzevalosContact+CoreDataClass.swift -// enzevalos_iphone -// -// Created by Oliver Wiese on 27/12/16. -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. -// This file was automatically generated and should not be edited. -// - -import Foundation -import CoreData -import UIKit -import Contacts - -// FIXME: comparison operators with optionals were removed from the Swift Standard Libary. -// Consider refactoring the code to use the non-optional operators. -fileprivate func < <T : Comparable>(lhs: T?, rhs: T?) -> Bool { - switch (lhs, rhs) { - case let (l?, r?): - return l < r - case (nil, _?): - return true - default: - return false - } -} - -/** - EnzevalosContact is used for persons and items of the address book (by apple). - One enzevalosContact maps to one person/item of the address book. - One enzevalosContact links to multiple key records since the person have multiple keys. - */ -@objc(EnzevalosContact) -open class EnzevalosContact: NSManagedObject, Contact, Comparable { - - override open var debugDescription: String { - get { - var string = "" - string = string + "Name: \(name) #Keys: \(publicKeys.count) #Addr: \(addresses.count) \n Addresses: \n" - for addr in addresses { - if let a = addr as? Mail_Address { - string = string + a.address + "\n" - } - } - string = string + "public Keys: \n" - for pk in publicKeys { - string = string + "\(pk.keyID) \n" - } - return string - } - } - - /** - Just like nameOptional or a localized variant of "no name". Just in case you like to enforce a name. - */ - open var name: String { - if let name = nameOptional { - return name - } else if let displayname = displayname { - return displayname - } else { - return NSLocalizedString("noName", comment: "We have no name for this one") - } - } - - open var nameOptional: String? { - var name = String() - - if let cnc = cnContact { - if cnc.givenName.count > 0 { - name += cnc.givenName - } - if cnc.familyName.count > 0 { - if name.count > 0 { - name += " " - } - name += cnc.familyName - } - } - if name.count > 0 { - return name - } else { - return nil - } - } - - open var to: [PersistentMail] { - get { - var mails = [PersistentMail]() - for adr in addresses { - if let a = adr as? Mail_Address, let to = a.to { - for m in to { - mails.append(m as! PersistentMail) - } - } - } - return mails - } - } - - open var bcc: [PersistentMail] { - get { - var mails = [PersistentMail]() - for adr in addresses { - if let a = adr as? Mail_Address, let bcc = a.bcc { - for m in bcc { - mails.append(m as! PersistentMail) - } - } - } - return mails - } - } - - - - open var cc: [PersistentMail] { - get { - var mails = [PersistentMail]() - for adr in addresses { - if let a = adr as? Mail_Address, let cc = a.cc { - for m in cc { - mails.append(m as! PersistentMail) - } - } - } - return mails - } - } - - open var from: [PersistentMail] { - get { - var mails = [PersistentMail]() - for adr in addresses { - if let a = adr as? Mail_Address, let from = a.from { - for m in from { - mails.append(m as! PersistentMail) - } - } - } - return mails - } - } - - /** - A set of associated public keys - */ - var publicKeys: Set<PersistentKey> { - get { - var pks = Set<PersistentKey>() - for adr in getMailAddresses() { - pks = pks.union(adr.publicKeys) - } - return pks - } - } - /** - A set of associated key records - */ - open var records: [KeyRecord] { - get { - if let krecords = self.keyrecords as? Set<KeyRecord> { - return Array(krecords) - } - return [] - } - - } - open var hasKey: Bool { - get { - for item in addresses { - let adr = item as! MailAddress - if adr.hasKey { - return true - } - } - return false - } - } - - open var firstSecureMailReceived: Date? { - if !hasKey { - return nil - } - var date: Date? = nil - for r in records { - if date == nil { - date = r.firstSecureMailReceived - } - else if let current = r.firstSecureMailReceived, let d = date { - if current < d { - date = r.firstSecureMailReceived - } - } - } - return date - } - - /** - Related item in the address book (from apple) - */ - open var cnContact: CNContact? { - get { - if let cn = cnidentifier { - let contacts = AddressHandler.getContactByID(cn) - if contacts.count > 0 { - return contacts.first - } - } - return nil - } - } - - /** - Create a new cnContact in the address book. - */ - open var newCnContact: CNContact { - let con = CNMutableContact() - let name = self.displayname - if let n = name { - let nameArray = n.split(separator: " ").map(String.init) - switch nameArray.count { - case 1: - con.givenName = nameArray.first! - case 2..<20: // who has more than two names?! - con.givenName = nameArray.first! - con.familyName = nameArray.last! - default: - con.givenName = "NO" - con.familyName = "NAME" - } - } - - if let adr = addresses.anyObject() as? Mail_Address { - con.emailAddresses.append(CNLabeledValue(label: CNLabelOther, value: adr.address as NSString)) - } - return con - } - - func getAddress(_ address: String) -> Mail_Address? { - var addr: Mail_Address - for obj in addresses { - addr = obj as! Mail_Address - if(addr.address == address) { - return addr - } - } - return nil - } - - open func getMailAddresses() -> [MailAddress] { - var adr = [MailAddress] () - for a in addresses { - let b = a as! Mail_Address - adr.append(b) - } - return adr - } - - /** - Is the address associated to the person(enzevalos contact) - */ - func isAddress(mailadr: String) -> Bool { - for adr in getMailAddresses() { - if mailadr.lowercased() == adr.mailAddress.lowercased() { - return true - } - } - return false - } -} - -private func isEmpty(_ contact: EnzevalosContact) -> Bool { - let mails = contact.from - if(mails.count == 0) { - return true - } - return false -} - -func == (lhs: EnzevalosContact, rhs: EnzevalosContact) -> Bool { - if isEmpty(lhs) { - return false - } - if isEmpty(rhs) { - return false - } - let mailLHS = lhs.from.last - let mailRHS = rhs.from.last - - return mailLHS == mailRHS -} - -public func < (lhs: EnzevalosContact, rhs: EnzevalosContact) -> Bool { - if isEmpty(lhs) { - return true - } - if isEmpty(rhs) { - return false - } - let mailLHS = lhs.from.last - let mailRHS = rhs.from.last - - return mailLHS < mailRHS -} diff --git a/enzevalos_iphone/EnzevalosContact+CoreDataProperties.swift b/enzevalos_iphone/EnzevalosContact+CoreDataProperties.swift deleted file mode 100644 index 106d86af4e10628f76d4affb25e04ff493498c2b..0000000000000000000000000000000000000000 --- a/enzevalos_iphone/EnzevalosContact+CoreDataProperties.swift +++ /dev/null @@ -1,77 +0,0 @@ -// -// EnzevalosContact+CoreDataProperties.swift -// enzevalos_iphone -// -// Created by Oliver Wiese on 04/01/17. -// Copyright © 2018 fu-berlin. -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. -// - -import Foundation -import CoreData - - -extension EnzevalosContact { - - @nonobjc open override class func fetchRequest() -> NSFetchRequest<NSFetchRequestResult> { - return NSFetchRequest(entityName: "EnzevalosContact"); - } - - @NSManaged public var displayname: String? - /** - Identifier to look up contact in the address book - */ - @NSManaged public var cnidentifier: String? - @NSManaged public var color: UIColor? - @NSManaged public var addresses: NSSet - @NSManaged public var keyrecords: NSSet? - -} - - -// MARK: Generated accessors for addresses -extension EnzevalosContact { - - @objc(addAddressesObject:) - @NSManaged public func addToAddresses(_ value: Mail_Address) - - @objc(removeAddressesObject:) - @NSManaged public func removeFromAddresses(_ value: Mail_Address) - - @objc(addAddresses:) - @NSManaged public func addToAddresses(_ values: NSSet) - - @objc(removeAddresses:) - @NSManaged public func removeFromAddresses(_ values: NSSet) - -} - -// MARK: Generated accessors for mailaddress -extension EnzevalosContact { - - @objc(addKeyrecordsObject:) - @NSManaged public func addToKeyrecords(_ value: KeyRecord) - - @objc(removeKeyrecordsObject:) - @NSManaged public func removeFromKeyrecords(_ value: KeyRecord) - - @objc(addKeyrecords:) - @NSManaged public func addToKeyrecords(_ values: NSSet) - - @objc(removeKeyrecords:) - @NSManaged public func removeFromKeyrecords(_ values: NSSet) - -} - - diff --git a/enzevalos_iphone/EphemeralMail.swift b/enzevalos_iphone/EphemeralMail.swift index 6db9848cdf70ead045cc5dcb32f31820464a87a5..01cd9263fb9c437908151a68bb3076fe7cc65caa 100644 --- a/enzevalos_iphone/EphemeralMail.swift +++ b/enzevalos_iphone/EphemeralMail.swift @@ -29,9 +29,9 @@ open class EphemeralMail: Mail { public var subject: String? public var body: String? public var uid: UInt64 - public var predecessor: PersistentMail? + public var predecessor: MailRecord? - public init(to: NSSet = [], cc: NSSet = [], bcc: NSSet = [], date: Date = Date(), subject: String? = nil, body: String? = ""/*UserManager.loadUserSignature()*/, uid: UInt64 = 0, predecessor: PersistentMail? = nil) { + public init(to: NSSet = [], cc: NSSet = [], bcc: NSSet = [], date: Date = Date(), subject: String? = nil, body: String? = ""/*UserManager.loadUserSignature()*/, uid: UInt64 = 0, predecessor: MailRecord? = nil) { self.cc = cc self.bcc = bcc self.to = to diff --git a/enzevalos_iphone/ExportViewController.swift b/enzevalos_iphone/ExportViewController.swift index 62ef3c0ce11824367972b5e3e7ab291c2cda483f..af97656e6654b8657aad68592552bc88d78d65d8 100644 --- a/enzevalos_iphone/ExportViewController.swift +++ b/enzevalos_iphone/ExportViewController.swift @@ -51,11 +51,11 @@ class ExportViewController: UITableViewController { Logger.log(exportKeyViewButton: !alreadySent) // } - let handler = DataHandler.handler - let sk = handler.prefSecretKey() //handler.findSecretKeys() + let handler = PersitentDataProvider.dataProvider + let sk: SecretKeyRecord? //handler.prefSecretKey() //handler.findSecretKeys() let pgp = SwiftPGP() if let sk = sk { - let keyId = sk.keyID + let keyId = sk.fingerprint if alreadySent { if let message = pgp.exportKey(id: keyId, isSecretkey: true, autocrypt: true, newPasscode: true) { passcode = pgp.loadExportPasscode(id: keyId)! @@ -144,12 +144,12 @@ class ExportViewController: UITableViewController { tableView.estimatedRowHeight = 140 navigationItem.rightBarButtonItem?.title = NSLocalizedString("Done", comment: "") - let handler = DataHandler.handler - let ids = handler.findSecretKeys() + let handler = PersitentDataProvider.dataProvider + let ids = [SecretKeyRecord]()//handler.findSecretKeys() if ids.count > 0 { let id = ids[0] let pgp = SwiftPGP() - let keyId = id.keyID + let keyId = id.fingerprint ?? "" passcode = pgp.loadExportPasscode(id: keyId) ?? "" alreadySent = passcode != "" } diff --git a/enzevalos_iphone/Folder+CoreDataClass.swift b/enzevalos_iphone/Folder+CoreDataClass.swift deleted file mode 100644 index 68b5157fa38b1dd6a7dec566b8eb5401251188a1..0000000000000000000000000000000000000000 --- a/enzevalos_iphone/Folder+CoreDataClass.swift +++ /dev/null @@ -1,98 +0,0 @@ -// -// Folder+CoreDataClass.swift -// -// -// Created by Oliver Wiese on 05.07.17. -// -// - -import Foundation -import CoreData - -@objc(Folder) -public class Folder: NSManagedObject { - static var inbox: Folder { - get { - return DataHandler.handler.findFolder(with: UserManager.backendInboxFolderPath) - } - } - - var name: String { - get { - if let n = path.components(separatedBy: delimiter).last { - return n - } - return path - } - } - - var counterMails: Int { - get { - if let mails = self.mails { - return mails.count - } - return 0 - } - } - - var frontendName: String { - get { - return UserManager.convertToFrontendFolderPath(from: name) - } - } - - /** - Please read the RFC. - */ - var uids: MCOIndexSet { - - get { - let ids = MCOIndexSet() - mailsOfFolder.forEach{ids.add($0.uid)} - return ids - } - } - - - - var records: [KeyRecord] { - get { - guard keyRecords != nil && keyRecords?.count ?? 0 > 0 else { - return [] - } - if UserManager.backendInboxFolderPath == self.path { - return DataHandler.handler.findRecordsInbox() - } - let rs = DataHandler.handler.getAllKeyRecords() - return rs - } - } - - - var mailsOfFolder: [PersistentMail] { - get { - var ms = [PersistentMail]() - if let mymails = mails { - if let m = mymails as? Set<PersistentMail> { - return Array(m) - } - for case let m as PersistentMail in mymails { - ms.append(m) - } - } - return ms - } - } - - var subfolders: [Folder] { - get { - var folders: [Folder] = [] - for f in DataHandler.handler.allFolders { - if f.path.hasPrefix(path + delimiter) && f.path != path { - folders.append(f) - } - } - return folders - } - } -} diff --git a/enzevalos_iphone/Folder+CoreDataProperties.swift b/enzevalos_iphone/Folder+CoreDataProperties.swift deleted file mode 100644 index 8918988235fea555f3eea0b3ff92c8fecd3d2ceb..0000000000000000000000000000000000000000 --- a/enzevalos_iphone/Folder+CoreDataProperties.swift +++ /dev/null @@ -1,166 +0,0 @@ -// -// Folder+CoreDataProperties.swift -// -// -// Created by Oliver Wiese on 05.07.17. -// -// - -import Foundation -import CoreData - - -extension Folder { - - @nonobjc public class func fetchRequest() -> NSFetchRequest<Folder> { - return NSFetchRequest<Folder>(entityName: "Folder") - } - - @NSManaged public var parent: Folder? - @NSManaged public var subfolder: NSSet? - @NSManaged public var mails: NSSet? - @NSManaged public var keyRecords: NSSet? - @NSManaged public var path: String //backendFolderPath - @NSManaged public var lastUpdate: Date? - /** - Used for logging. - */ - @NSManaged public var pseudonym: String - @NSManaged public var icon: String? - - /** - Please read the RFC! - */ - public var uidvalidity: UInt32? { - set { - if let num = newValue { - self.willChangeValue(forKey: "uidvalidity") - self.setPrimitiveValue(NSDecimalNumber.init(value: num as UInt32), forKey: "uidvalidity") - self.didChangeValue(forKey: "uidvalidity") - } - } - get { - self.willAccessValue(forKey: "uidvalidity") - let text = (self.primitiveValue(forKey: "uidvalidity") as? NSDecimalNumber)?.uint32Value - self.didAccessValue(forKey: "uidvalidity") - if let num = text { - return num - } - return nil - } - } - - - @NSManaged public var delimiter: String - public var flags: MCOIMAPFolderFlag { - get { - self.willAccessValue(forKey: "flags") - let ms = self.primitiveValue(forKey: "flags") - - self.didAccessValue(forKey: "flags") - if let num = ms { - if case let i as Int = num { - return MCOIMAPFolderFlag.init(rawValue: i) - } - } - return MCOIMAPFolderFlag.unmarked - } - set { - self.willChangeValue(forKey: "flags") - self.setPrimitiveValue(Int16(newValue.rawValue), forKey: "flags") - self.didChangeValue(forKey: "flags") - } - } - - public var maxID: UInt64 { - - set { - self.willChangeValue(forKey: "maxID") - self.setPrimitiveValue(NSDecimalNumber.init(value: newValue as UInt64), forKey: "maxID") - self.didChangeValue(forKey: "maxID") - } - get { - self.willAccessValue(forKey: "maxID") - let text = (self.primitiveValue(forKey: "maxID") as? NSDecimalNumber)?.uint64Value - self.didAccessValue(forKey: "maxID") - if text == nil { - return 1 - } - return text! - } - } - - public var minID: UInt64 { - set { - self.willChangeValue(forKey: "minUID") - self.setPrimitiveValue(NSDecimalNumber.init(value: newValue as UInt64), forKey: "minUID") - self.didChangeValue(forKey: "minUID") - } - get { - self.willAccessValue(forKey: "minUID") - let id = (self.primitiveValue(forKey: "minUID") as? NSDecimalNumber)?.uint64Value - self.didAccessValue(forKey: "minUID") - if id == nil { - var min = maxID - mailsOfFolder.forEach{ - if $0.uid < min { - min = $0.uid - } - } - return min - } - return id! - } - } -} - -// MARK: Generated accessors for mails -extension Folder { - - @objc(addMailsObject:) - @NSManaged public func addToMails(_ value: PersistentMail) - - @objc(removeMailsObject:) - @NSManaged public func removeFromMails(_ value: PersistentMail) - - @objc(addSubfolderObject:) - @NSManaged public func addToSubfolder(_ value: Folder) - - @objc(removeSubfolderObject:) - @NSManaged public func removeFromSubfolder(_ value: Folder) - - @objc(addKeyRecordsObject:) - @NSManaged public func addToKeyRecords(_ value: KeyRecord) - - @objc(removeKeyRecordsObject:) - @NSManaged public func removeFromKeyRecords(_ value: KeyRecord) - - @objc(addMails:) - @NSManaged public func addToMails(_ values: NSSet) - - @objc(removeMails:) - @NSManaged public func removeFromMails(_ values: NSSet) - - @objc(addSubfolder:) - @NSManaged public func addToSubfolder(_ values: NSSet) - - @objc(removeSubfolder:) - @NSManaged public func removeFromSubfolder(_ values: NSSet) - - @objc(addKeyRecords:) - @NSManaged public func addToKeyRecords(_ values: NSSet) - - @objc(removeKeyRecords:) - @NSManaged public func removeFromKeyRecords(_ values: NSSet) - -} - -extension Folder: Comparable { - public static func < (lhs: Folder, rhs: Folder) -> Bool { - return lhs.name < rhs.name - } - - public static func == (lhs: Folder, rhs: Folder) -> Bool { - return lhs.name == rhs.name && lhs.path == rhs.path - } -} diff --git a/enzevalos_iphone/FolderViewController.swift b/enzevalos_iphone/FolderViewController.swift index c62c58dbcae260acbfe904ce74e0e7febfbdab4d..b900adbeb0125e06e1bef8694d3d9ca9401b1c28 100644 --- a/enzevalos_iphone/FolderViewController.swift +++ b/enzevalos_iphone/FolderViewController.swift @@ -23,11 +23,11 @@ import UIKit class FolderViewController: UITableViewController { var mailHandler = AppDelegate.getAppDelegate().mailHandler - var folders: [Folder] = [] + var folders: [FolderRecord] = [] @IBOutlet weak var manageButton: UIBarButtonItem! var isFirstFolderViewController = true - var presentedFolder: Folder? = nil + var presentedFolder: FolderRecord? = nil @IBOutlet weak var lastUpdateButton: UIBarButtonItem! var lastUpdateLabel = UILabel(frame: CGRect.zero) @@ -48,17 +48,17 @@ class FolderViewController: UITableViewController { manageButton.title = NSLocalizedString("Management.Button", comment: "Manage") if isFirstFolderViewController { - folders = DataHandler.handler.allRootFolders.sorted().filter { $0.path != UserManager.backendInboxFolderPath } - DataHandler.handler.callForFolders(done: endRefreshing) + //TODO folders = DataHandler.handler.allRootFolders.sorted().filter { $0.path != UserManager.backendInboxFolderPath } + //TOTO DataHandler.handler.callForFolders(done: endRefreshing) navigationItem.title = NSLocalizedString("Folders", comment: "") } else { navigationItem.setLeftBarButton(navigationItem.backBarButtonItem, animated: false) } if let thisFolder = presentedFolder { - navigationItem.title = UserManager.convertToFrontendFolderPath(from: thisFolder.name) + navigationItem.title = UserManager.convertToFrontendFolderPath(from: thisFolder.path ?? "") refreshControl?.beginRefreshing() mailHandler.updateFolder(folder: thisFolder, completionCallback: endRefreshing) - folders = thisFolder.subfolders.sorted() + //folders = thisFolder.subfolders.sorted() } NotificationCenter.default.addObserver(forName: Notification.Name.NSManagedObjectContextDidSave, object: nil, queue: nil, using: { [weak self] _ in @@ -135,14 +135,14 @@ class FolderViewController: UITableViewController { let mail = getMails()[indexPath.row] cell.body.text = mail.body - if let contact = mail.from.contact { + if let contact = mail.fromAddress { cell.from.text = contact.name } else { - cell.from.text = mail.from.mailAddress + cell.from.text = mail.fromAddress?.mailAddress } cell.from.font = UIFont.boldSystemFont(ofSize: cell.from.font.pointSize) cell.subject.text = mail.subject - cell.date.text = mail.timeString + cell.date.text = mail.date?.dateToString if mail.isSecure { cell.secureImageView.image = StudySettings.securityIndicator.imageOfSecureIndicator() @@ -160,11 +160,12 @@ class FolderViewController: UITableViewController { cell.body.font = UIFont.systemFont(ofSize: cell.body.font.pointSize) cell.subject.font = UIFont.systemFont(ofSize: cell.subject.font.pointSize) } - if mail.isAnwered { + let flags = MCOMessageFlag(rawValue: Int(mail.flag)) + if flags.contains(.answered) { cell.replyImageView.image = "↩️".image() } else { cell.replyImageView.image = nil - } + } if let markImageView = cell.markImageView { if markImageView.image == nil { @@ -186,8 +187,8 @@ class FolderViewController: UITableViewController { return cell } } else if indexPath.row < folders.count { - cell.folderName.text = folders[indexPath.row].frontendName - cell.folderImage.image = getImage(for: UserManager.convertToFrontendFolderPath(from: folders[indexPath.row].path, with: folders[indexPath.row].delimiter)) + cell.folderName.text = folders[indexPath.row].path + cell.folderImage.image = getImage(for: UserManager.convertToFrontendFolderPath(from: folders[indexPath.row].path ?? "", with: folders[indexPath.row].delimiter ?? "")) } return cell @@ -218,7 +219,7 @@ class FolderViewController: UITableViewController { } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "readFolderMailSegue" { - if let destinationVC = segue.destination as? ReadViewController, let mail = sender as? PersistentMail { + if let destinationVC = segue.destination as? ReadViewController, let mail = sender as? MailRecord { destinationVC.mail = mail } } @@ -230,16 +231,16 @@ class FolderViewController: UITableViewController { refreshControl?.beginRefreshing() mailHandler.updateFolder(folder: thisFolder, completionCallback: endRefreshing(_:)) } else { - DataHandler.handler.callForFolders(done: endRefreshing) + //TODO DataHandler.handler.callForFolders(done: endRefreshing) } } func endRefreshing(_ error: Error?) { if let thisFolder = presentedFolder { - folders = thisFolder.subfolders.sorted() + //TODO folders = thisFolder.subfolders.sorted() presentedFolder = thisFolder } if isFirstFolderViewController { - folders = DataHandler.handler.allRootFolders.sorted().filter { $0.path != UserManager.backendInboxFolderPath } + //TODO folders = DataHandler.handler.allRootFolders.sorted().filter { $0.path != UserManager.backendInboxFolderPath } } tableView.reloadData() refreshControl?.endRefreshing() @@ -253,9 +254,11 @@ class FolderViewController: UITableViewController { /* TODO: Add more in here*/ return #imageLiteral(resourceName: "Inbox") } - func getMails() -> [PersistentMail] { + func getMails() -> [MailRecord] { if let folder = self.presentedFolder { - return folder.mailsOfFolder.sorted() + if let mails = folder.mailsInFolder?.allObjects as? [MailRecord] { + return mails //TODO Sort? + } } return [] } diff --git a/enzevalos_iphone/InboxCellDelegator.swift b/enzevalos_iphone/InboxCellDelegator.swift index ba745dace5a01e94907739768df81f844fb3e7b0..4c9350c22501d370a2a464cc14ab46ea5eb80c25 100644 --- a/enzevalos_iphone/InboxCellDelegator.swift +++ b/enzevalos_iphone/InboxCellDelegator.swift @@ -19,7 +19,7 @@ protocol InboxCellDelegator: class { - func callSegueFromCell(_ mail: PersistentMail?) - func callSegueFromCell2(_ contact: KeyRecord?) - func callSegueToContact(_ contact: KeyRecord?) + func callSegueFromCell(_ mail: MailRecord?) + func callSegueFromCell2(_ contact: AddressRecord?) + func callSegueToContact(_ contact: AddressRecord?) } diff --git a/enzevalos_iphone/IntroContactCell.swift b/enzevalos_iphone/IntroContactCell.swift index 331a16f2ff5652529991a56440a656659c62717a..939bc04b1f5f7bd0cbcc7e0924d48f40ef298bae 100644 --- a/enzevalos_iphone/IntroContactCell.swift +++ b/enzevalos_iphone/IntroContactCell.swift @@ -13,17 +13,11 @@ class IntroContactCell: UITableViewCell { @IBOutlet weak var nameLabel: UILabel! @IBOutlet weak var planeImage: UIImageView! - var enzContact: EnzevalosContact? { + var enzContact: AddressRecord? { didSet { if let con = enzContact { - var cont: Contact - if let contact = con.cnContact { - cont = contact - } else { - cont = con - } - nameLabel.text = cont.name - contactImage.image = cont.getImageOrDefault() + nameLabel.text = con.name + contactImage.image = con.getImageOrDefault() contactImage.layer.cornerRadius = contactImage.frame.height / 2 contactImage.clipsToBounds = true } diff --git a/enzevalos_iphone/IntroContactTableViewController.swift b/enzevalos_iphone/IntroContactTableViewController.swift index 31040d6395a83939e346979bc0462ce9051ce075..de444eda747f13da7a736a333f37f462615af517 100644 --- a/enzevalos_iphone/IntroContactTableViewController.swift +++ b/enzevalos_iphone/IntroContactTableViewController.swift @@ -9,7 +9,7 @@ import Foundation class IntroContactTableViewController: UITableViewController, IntroInfoButton { - var contacts: [String: [(EnzevalosContact, PersistentKey, [Mail_Address])]] = [:] + var contacts: [String: [(AddressRecord, PublicKeyRecord, [AddressRecord])]] = [:] var selected: Set<IndexPath> = Set<IndexPath>.init() var nextAction: (() -> ())? = nil var titleText: String = "" @@ -23,7 +23,7 @@ class IntroContactTableViewController: UITableViewController, IntroInfoButton { @IBOutlet var doubleTapRecognizer: UITapGestureRecognizer! static let storyboardID = "contactTableViewController" - static func storyboardInstance(contacts: [String: [(EnzevalosContact, PersistentKey, [Mail_Address])]], nextAction: (() -> ())? = nil, titleText: String = "", titleDescription: String = "", titleAction: ((_ sender: Any) -> ())? = nil, url: String? = TravelHandler.website, titleImage: UIImage? = TravelHandler.planeIcon) -> IntroContactTableViewController? { + static func storyboardInstance(contacts: [String: [(AddressRecord, PublicKeyRecord, [AddressRecord])]], nextAction: (() -> ())? = nil, titleText: String = "", titleDescription: String = "", titleAction: ((_ sender: Any) -> ())? = nil, url: String? = TravelHandler.website, titleImage: UIImage? = TravelHandler.planeIcon) -> IntroContactTableViewController? { let storyboard = UIStoryboard(name: "Intro", bundle: nil) if let controller = storyboard.instantiateViewController(withIdentifier: storyboardID) as? IntroContactTableViewController { @@ -199,7 +199,9 @@ class IntroContactTableViewController: UITableViewController, IntroInfoButton { var result: [String] = [] for index in selected { for addr in contacts[intToAlphabet(value: index.section)]![index.row].2 { - result.append(addr.address) + if let email = addr.email { + result.append(email) + } } } return result diff --git a/enzevalos_iphone/IntroContactViewController.swift b/enzevalos_iphone/IntroContactViewController.swift index a12661316efc89a5856787a94fee841e1d0be1fa..f2bfca6f521f549ba78d6a6a8a242c90ed6acd3a 100644 --- a/enzevalos_iphone/IntroContactViewController.swift +++ b/enzevalos_iphone/IntroContactViewController.swift @@ -15,13 +15,13 @@ class IntroContactViewController: UIViewController { @IBOutlet weak var nameLabel: UILabel! @IBOutlet weak var tableView: UITableView! - var enzContact: EnzevalosContact? - var key: PersistentKey? - var addresses: [Mail_Address] = [] + var enzContact: Contact? + var key: PublicKeyRecord? + var addresses: [MailAddress] = [] static let storyboardID = "contactViewController" - static func storyboardInstance(enzContact: EnzevalosContact?, key: PersistentKey?, addresses: [Mail_Address]) -> IntroContactViewController? { + static func storyboardInstance(enzContact: Contact?, key: PublicKeyRecord?, addresses: [MailAddress]) -> IntroContactViewController? { let storyboard = UIStoryboard(name: "Intro", bundle: nil) if let controller = storyboard.instantiateViewController(withIdentifier: storyboardID) as? IntroContactViewController { @@ -81,7 +81,7 @@ extension IntroContactViewController: UITableViewDataSource { case 0://keyID let cell = tableView.dequeueReusableCell(withIdentifier: "KeyIDCell")! cell.textLabel?.text = NSLocalizedString("KeyID", comment: "Identifier of the key") - cell.detailTextLabel?.text = key?.keyID + cell.detailTextLabel?.text = key?.fingerprint return cell case 1://Fingerprint let cell = tableView.dequeueReusableCell(withIdentifier: "FingerprintCell")! @@ -106,7 +106,7 @@ extension IntroContactViewController: UITableViewDataSource { return cell case 2://EncryptionType let cell = tableView.dequeueReusableCell(withIdentifier: "EncryptionTypeCell")! - let cryptoscheme: String = key?.encryptionType.description ?? "" + let cryptoscheme: String = CryptoScheme.find(i: key?.cryptoProtocol ?? CryptoScheme.UNKNOWN.asInt()) cell.detailTextLabel?.text = cryptoscheme cell.textLabel?.text = NSLocalizedString("EncryptionType", comment: "Type of Encryption") return cell @@ -125,7 +125,7 @@ extension IntroContactViewController: UITableViewDataSource { } } let cell = tableView.dequeueReusableCell(withIdentifier: "MailAddressCell")! - cell.textLabel?.text = addresses[cellForRowAt.row].address + cell.textLabel?.text = addresses[cellForRowAt.row].mailAddress return cell } diff --git a/enzevalos_iphone/InviteFriendViewController.swift b/enzevalos_iphone/InviteFriendViewController.swift index 596eb6ec18c3c5558792c53801016cfcf4485c0c..ca0207f114ae1588e526eed88c768e447ad7d3d5 100755 --- a/enzevalos_iphone/InviteFriendViewController.swift +++ b/enzevalos_iphone/InviteFriendViewController.swift @@ -32,9 +32,9 @@ class InviteFriendViewController: UIViewController, UITableViewDataSource, UITab // MARK:- Variables var superBadge : Badges? var subBadges : [Badges] = [] - var contacts: [EnzevalosContact] = [EnzevalosContact]() + var contacts: [Contact] = [Contact]() - var selectedContact : EnzevalosContact? + var selectedContact : Contact? @IBOutlet weak var inviteFriendLabel: UILabel! @@ -45,13 +45,15 @@ class InviteFriendViewController: UIViewController, UITableViewDataSource, UITab // MARK:- UIViewController override func viewDidLoad() { - contacts = [EnzevalosContact]() + contacts = [Contact]() + /* TODO let localcontacts = DataHandler.handler.getContacts() for element in localcontacts { if !element.hasKey{ contacts.append(element) } } + */ guard let badge = superBadge else { @@ -150,10 +152,11 @@ class InviteFriendViewController: UIViewController, UITableViewDataSource, UITab let cell = UITableViewCell() cell.textLabel?.text = "\( self.contacts[indexPath.row].name )" + /* TODO if self.contacts[indexPath.row].hasKey { cell.isUserInteractionEnabled = false cell.textLabel?.textColor = UIColor.green - } + } */ return cell } diff --git a/enzevalos_iphone/KeyCell.swift b/enzevalos_iphone/KeyCell.swift index 82d6b6f7348b8682776bc82b71628afd4c2f819f..8274ea8dded15bc055945678f7ee4b94700e1651 100644 --- a/enzevalos_iphone/KeyCell.swift +++ b/enzevalos_iphone/KeyCell.swift @@ -16,11 +16,12 @@ class KeyCell: UITableViewCell { @IBOutlet weak var mailAddress: UILabel! - func setLabels(key: PersistentKey) { + func setLabels(key: PublicKeyRecord) { var mailAddrString: String? - var id = key.keyID + var id = key.fingerprint ?? "" let date = key.discoveryDate let pref = false + /* TODO if let record = key.keyRecord { mailAddrString = record.addressNames.first id = record.myNick @@ -35,20 +36,21 @@ class KeyCell: UITableViewCell { } } } + */ setLabels(id: id, addr: mailAddrString, date: date, origin: nil, pref: pref) } - func setLabels(key: SecretKey) { - var id = key.keyID + func setLabels(key: SecretKeyRecord) { + var id = key.fingerprint ?? "" var mail: String? = nil - let date = key.importDate - let pref = DataHandler.handler.prefSecretKey()?.keyID == key.keyID + let date = key.importedDate + // TODO let pref = DataHandler.handler.prefSecretKey()?.keyID == key.keyID if let addr = UserManager.loadUserValue(.userAddr) as? String { mail = addr - let record = DataHandler.handler.getKeyRecord(addr: addr, keyID: id) - id = record.myNick + //let record = DataHandler.handler.getKeyRecord(addr: addr, keyID: id) + // TODO id = record.myNick } - setLabels(id: id, addr: mail, date: date, origin: nil, pref: pref) + setLabels(id: id, addr: mail, date: date, origin: nil, pref: true)//pref) } func setLabels(key: DisplayKey) { diff --git a/enzevalos_iphone/KeyRecord+CoreDataClass.swift b/enzevalos_iphone/KeyRecord+CoreDataClass.swift deleted file mode 100644 index b1103a916545c5d80fd5e9e2be88cc1645f56b2f..0000000000000000000000000000000000000000 --- a/enzevalos_iphone/KeyRecord+CoreDataClass.swift +++ /dev/null @@ -1,348 +0,0 @@ -// -// KeyRecord+CoreDataClass.swift -// enzevalos_iphone -// -// Created by Oliver Wiese on 14.02.18. -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. -// -// - -import Foundation -import CoreData -import Contacts -import UIKit -import SwiftUI - -/** - Key records are mostly used in the inbox and for id (views). For each key we have a single key record. There are also key records for each mail address without keys, for instance when receiving unsigned mails. - - One person can have multiple key records, e.g. one with key, one without a key or multiple keys. - */ -@objc(KeyRecord) -public class KeyRecord: NSManagedObject, Record, Identifiable { - public var isUser: Bool { - get{ - /** - A keyrecord matches to the user if: - * we know the secret key, because we are the key owner - * the mail addresses matches - */ - - if isSecretKey { - return true - } - if let userAdr = UserManager.loadUserValue(Attribute.userAddr) as? String{ - let myAddrs = self.addressNames.map{$0.lowercased()} - return myAddrs.contains(userAdr.lowercased()) - } - return false - } - } - - /** - Does the key record has a secret key? - */ - public var isSecretKey: Bool { - if let id = self.keyID { - return DataHandler.handler.findSecretKey(keyID: id) != nil - } - return false - } - - public var name: String { - get { - return self.ezContact.name - } - } - - public var hasKey: Bool { - get { - return activeKey != nil - } - } - - public var isSecure: Bool { - get { - return hasKey - } - } - - public var isVerified: Bool { - get { - if let k = activeKey { - return k.isVerified() - } - return false - } - } - - public var keyID: String? { - if let k = activeKey { - return k.keyID - } - return nil - } - - - /** - MyNick is unique where as multiple key records can have the same name. - It is used to display different key records. - */ - public var myNick: String { - if let n = self.nick { - return n - } else { - return defaultNick() - } - } - - private func defaultNick() -> String { - let records = ezContact.records - var i = 1 - for r in records.sorted() { - if r.fingerprint == self.fingerprint { - break - } - i = i+1 - } - let id = "\(i)) \(name)" - self.nick = id - DataHandler.handler.save(during: "change id") - return id - } - - /** - One person can have multiple key records, e.g. one with key, one without a key or multiple keys. - In case of multiple keys we have a primaryID. The key of this id is used for decryption etc. - */ - public var isPrimaryID: Bool { - if let keyID = self.keyID { - for addr in self.addresses { - if keyID == addr.primaryKey?.keyID { - return true - } - } - } - return false - } - - public var cryptoscheme: CryptoScheme { - get { - if let k = activeKey { - return k.encryptionType - } - return CryptoScheme.UNKNOWN - } - } - - /** - It is the current fingerprint of the public key. - */ - public var fingerprint: String? { - get { - if let k = pgpKey { - if let pk = k.publicKey { - return pk.fingerprint.description() - } - else if let sk = k.secretKey { - return sk.fingerprint.description() - } - return k.keyID.longIdentifier - } - return nil - } - } - - private var pgpKey: Key? { - get { - if let id = activeKey?.keyID { - let pgp = SwiftPGP() - return pgp.loadKey(id: id) - } - return nil - } - } - - /** - EnzevalosContact provides some contact information about the key record. - */ - public var ezContact: EnzevalosContact { - get { - return contact - } - } - - - /** - Is a list of all received mails from this record. - */ - public var mails: [PersistentMail] { - get { - if let m = persistentMails as? Set<PersistentMail> { - return Array(m).sorted() - } - return [] - } - } - - /** - cnContact is the original corresponding contact in the address book. - */ - public var cnContact: CNContact? { - get { - return contact.cnContact - } - } - - public var color: UIColor { - get { - // Overflow?! - let prim = 653 - var text = self.ezContact.name - if let fingerprint = self.activeKey?.fingerprint { - text = fingerprint - } - let hash = (abs(text.hash)) % prim - return UIColor(hue: CGFloat(hash) / CGFloat(prim), saturation: 1, brightness: 0.75, alpha: 1) - } - } - - public var image: UIImage { - get { - return contact.getImageOrDefault() - - } - } - - /** - Corresponding mail addresses to the current key. - */ - public var addresses: [MailAddress] { - get { - if let k = activeKey { - if let addrs = k.mailaddresses as? Set<Mail_Address> { - return Array(addrs) - } - return [] - } - if let addrs = contact.addresses as? Set<Mail_Address> { - return Array(addrs) - } - return [] - } - } - - var addressNames: [String] { - get { - let adrs = addresses - var names = [String]() - for adr in adrs { - names.append(adr.mailAddress) - } - return names - } - } - - public func verify() { - if let k = activeKey { - k.verify() - } - } - - public func match(mail: PersistentMail) -> Bool { - if mail.folder == folder { - if let recordFingerprint = fingerprint, let signedKey = mail.signedKey { - let pgp = SwiftPGP() - if let key = pgp.loadKey(id: signedKey.keyID)?.publicKey { - return key.fingerprint.description() == recordFingerprint - } - return false - } - if !hasKey && !mail.isSigned { - for addr in addresses { - if mail.from.mailAddress == addr.mailAddress { - return true - } - } - return false - } - } - return false - } - - public func mailsInFolder(folder: Folder) -> [PersistentMail] { - let folderMails = DataHandler.handler.allMailsInFolder(key: keyID, contact: ezContact, folder: folder, isSecure: isSecure, searchForRelatedKeys: true) - if folderMails.count == 0 { - folder.removeFromKeyRecords(self) - } - let set = Set<PersistentMail>(folderMails) - return Array(set).sorted() - } - - - public var inboxMails: [PersistentMail] { - get { - let inbox = DataHandler.handler.findFolder(with: UserManager.backendInboxFolderPath) - return mailsInFolder(folder: inbox) - } - } - - public var firstSecureMailReceived: Date? { - if let key = activeKey { - return key.firstMail?.date - } - return nil - } -} - - -private func isEmpty(_ contact: KeyRecord) -> Bool { - return contact.mails.count == 0 -} - - -public func == (lhs: KeyRecord, rhs: KeyRecord) -> Bool { - if lhs.hasKey && rhs.hasKey { - if let keyLHS = lhs.activeKey, let keyRHS = rhs.activeKey { - return keyLHS.keyID == keyRHS.keyID - } - } - if lhs.hasKey != rhs.hasKey { - return false - } - return lhs.contact == rhs.contact - //return lhs.mails.first!.date == rhs.mails.first!.date && lhs.hasKey == rhs.hasKey && lhs.keyID == rhs.keyID -} - -public func < (lhs: KeyRecord, rhs: KeyRecord) -> Bool { - if isEmpty(lhs) { - return true - } - if isEmpty(rhs) { - return false - } - return lhs.mails.first!.date > rhs.mails.first!.date -} - - -extension UIImage { - /** - Same as image but different type - */ - public var img: Image { - get { - return Image(uiImage: self) - } - } -} diff --git a/enzevalos_iphone/KeyRecord+CoreDataProperties.swift b/enzevalos_iphone/KeyRecord+CoreDataProperties.swift deleted file mode 100644 index b1549e2d0463ed20f1b2c7b7b921ddf7fa9401d9..0000000000000000000000000000000000000000 --- a/enzevalos_iphone/KeyRecord+CoreDataProperties.swift +++ /dev/null @@ -1,162 +0,0 @@ -// -// KeyRecord+CoreDataProperties.swift -// enzevalos_iphone -// -// Created by Oliver Wiese on 14.02.18. -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. -// -// - -import Foundation -import CoreData -import SwiftUI - - -extension KeyRecord { - - @nonobjc public class func fetchRequest() -> NSFetchRequest<KeyRecord> { - return NSFetchRequest<KeyRecord>(entityName: "KeyRecord") - } - - @NSManaged public var contact: EnzevalosContact - @NSManaged public var folder: Folder? - @NSManaged public var key: PersistentKey? - @NSManaged public var persistentMails: NSSet? - @NSManaged public var newestDate: Date? - @NSManaged public var nick: String? - @NSManaged public var firstMail: PersistentMail? - @NSManaged public var secondMail: PersistentMail? - - - - var activeKey: PersistentKey? { - get { - if let key = key { - return key.rootKey.currentlyActiveKey - } - return nil - } - set(newKey) { - if key == nil { - key = newKey?.rootKey - } - } - } - -} - -// MARK: Generated accessors for persitentMails -extension KeyRecord { - - @objc(addPersistentMailsObject:) - @NSManaged public func addToPersistentMails(_ value: PersistentMail) - @objc(removePersistentMailsObject:) - @NSManaged public func removeFromPersistentMails(_ value: PersistentMail) - - @objc(addPersistentMails:) - @NSManaged public func addToPersistentMails(_ values: NSSet) - - @objc(removePersistentMails:) - @NSManaged public func removeFromPersistentMails(_ values: NSSet) - -} - -extension KeyRecord { - static func allRecordsFetchRequest(in folder: Folder) -> NSFetchRequest<KeyRecord> { - let request: NSFetchRequest<KeyRecord> = KeyRecord.fetchRequest() - //request.predicate = NSPredicate(format: "folder == %@", folder) - request.sortDescriptors = [NSSortDescriptor(key: "newestDate", ascending: false)] - return request - } - - static func allRecordsFetchRequest(in folder: Folder, query: String) -> NSFetchRequest<KeyRecord> { - let request: NSFetchRequest<KeyRecord> = KeyRecord.fetchRequest() - let folderPredicate = NSPredicate(format: "folder == %@", folder) - if !query.isEmpty { - let name = NSPredicate(format: "name CONTAINS %@", query) - request.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [folderPredicate, name]) - } else { - request.predicate = folderPredicate - } - request.sortDescriptors = [NSSortDescriptor(key: "newestDate", ascending: false)] - return request - } -} - -extension KeyRecord{ - static func findFirstMails(){ - let allRecord = DataHandler.handler.getAllKeyRecords() - for rec in allRecord { - if rec.firstMail == nil { - rec.firstMail = rec.mails.first - } - if rec.secondMail == nil && rec.mails.count > 1 { - rec.secondMail = rec.mails[1] - } - if rec.firstMail == nil { - print("Empty record: \(rec.name)") - } - } - DataHandler.handler.save(during: "Fix first mails") - } -} - -extension KeyRecord: DisplayContact { - var previousMails: Int { - return self.persistentMails?.count ?? 0 - } - - var previousResponses: Int { - return -1 - } - - var keyRecord: KeyRecord? { - return self - } - - var addr: String { - return self.addresses.first?.mailAddress ?? "No address" - } - - var myImage: Image { - return self.image.img - } - - var isInContactBook: Bool { - return self.cnContact != nil - } - - var otherAddresses: [String] { - return self.addressNames - } - - var keyIDs: [String] { - if let id = self.keyID { - return [id] - } - return [] - } - - var hasPreviousMails: Bool { - return self.persistentMails?.count ?? 0 > 1 - } - - var hasSimilarContacts: Bool { - return false // TODO! - } - - var similarContacts: [String] { - return [] // TODO! - } -} diff --git a/enzevalos_iphone/KeyTableViewController.swift b/enzevalos_iphone/KeyTableViewController.swift index f45b24c819e4e95e84277d7cc3420e411003f130..f395cb56784f86f8f9d28f51754dd46b4597549c 100644 --- a/enzevalos_iphone/KeyTableViewController.swift +++ b/enzevalos_iphone/KeyTableViewController.swift @@ -25,8 +25,8 @@ class KeyTableViewController: UITableViewController { } var type: KeyType = .SecretKey - var publicKeys: [PersistentKey] = [] - var secretKeys: [SecretKey] = [] + var publicKeys: [PublicKeyRecord] = [] + var secretKeys: [SecretKeyRecord] = [] var importableKeys: [TempKey] = [] var secretKeyPasswordField: UITextField? = nil @@ -38,11 +38,11 @@ class KeyTableViewController: UITableViewController { switch type { case .PublicKey: title = NSLocalizedString("KeyTable.Title.Other", comment: "Other people's IDs") - publicKeys = DataHandler.handler.findPublicKeys() + //TODO publicKeys = DataHandler.handler.findPublicKeys() showAddButton = true case .SecretKey: title = NSLocalizedString("KeyTable.Title.You", comment: "Your IDs") - secretKeys = DataHandler.handler.findSecretKeys() + //TODO secretKeys = DataHandler.handler.findSecretKeys() showAddButton = true case .ImportSecretKeyItunes: title = NSLocalizedString("KeyTable.Title.New.SecretKeys", comment: "New Secret Keys") @@ -178,13 +178,13 @@ class KeyTableViewController: UITableViewController { switch type { case .SecretKey: let key = secretKeys[indexPath.row] - keyID = key.keyID + keyID = key.fingerprint ?? "" addr = UserManager.loadUserValue(.userAddr) as? String ?? keyID case .PublicKey: let key = publicKeys[indexPath.row] - keyID = key.keyID + keyID = key.fingerprint ?? "" var mail: String? - if let addrs = key.mailaddresses { + if let addrs = key.usedAddress?.allObjects { for addr in addrs { if let addr = addr as? MailAddress { mail = addr.mailAddress @@ -202,7 +202,7 @@ class KeyTableViewController: UITableViewController { } let mainStoryboard = UIStoryboard(name: "Main", bundle: Bundle.main) if pushView, let viewController = mainStoryboard.instantiateViewController(withIdentifier: "UITableViewController-8Di-x2-cWQ") as? ContactViewController { - viewController.keyRecord = DataHandler.handler.getKeyRecord(addr: addr, keyID: keyID) + //TODO viewController.keyRecord = DataHandler.handler.getKeyRecord(addr: addr, keyID: keyID) self.navigationController?.pushViewController(viewController, animated: true) } } diff --git a/enzevalos_iphone/KeyViewController.swift b/enzevalos_iphone/KeyViewController.swift index f4301b2df9d1909b1e98ffb9738ff71d2cd2534c..62b8e019edb7604f4b1de5028bf476e08620e823 100644 --- a/enzevalos_iphone/KeyViewController.swift +++ b/enzevalos_iphone/KeyViewController.swift @@ -28,13 +28,13 @@ class KeyViewController: UIViewController { var openDate: Date = Date() //used for logging issues [see Logger.log(keyViewClose keyID:String, timevisited: Date)] - var record: KeyRecord? + var record: PublicKeyRecord? var copyButton: ButtonCell? override func viewDidLoad() { super.viewDidLoad() tableView.dataSource = self openDate = Date() - if let record = self.record, let keyID = record.keyID { + if let record = self.record, let keyID = record.fingerprint { Logger.log(keyViewOpen: keyID) } self.title = NSLocalizedString("KeyDetails", comment: "Details of the key") @@ -49,7 +49,7 @@ class KeyViewController: UIViewController { override func viewDidDisappear(_ animated: Bool) { // Logger.queue.async(flags: .barrier) { - if let record = self.record, let keyID = record.keyID { + if let record = self.record, let keyID = record.fingerprint { let duration = Date().timeIntervalSince(self.openDate) Logger.log(keyViewClose: keyID, secondsOpened: Int(duration)) @@ -72,13 +72,13 @@ extension KeyViewController: UITableViewDataSource { return returnValue } if toSectionType(section) == .addresses { - if let record = record { - return record.addresses.count + if let record = record, let addrs = record.usedAddress { + return addrs.count } return 0 } if toSectionType(section) == .keyActions { - if let isUser = record?.isUser, isUser { + if record?.mySecretKeyRecord != nil { return 2 } } @@ -90,7 +90,7 @@ extension KeyViewController: UITableViewDataSource { if toRowType(indexPath) == .keyID { let cell = tableView.dequeueReusableCell(withIdentifier: "KeyIDCell")! cell.textLabel?.text = NSLocalizedString("KeyID", comment: "Identifier of the key") - cell.detailTextLabel?.text = record?.keyID?.makeBlocks() + cell.detailTextLabel?.text = record?.fingerprint?.makeBlocks() return cell } else if toRowType(indexPath) == .fingerprint { @@ -110,7 +110,7 @@ extension KeyViewController: UITableViewDataSource { } else if toRowType(indexPath) == .encryptionType { let cell = tableView.dequeueReusableCell(withIdentifier: "EncryptionTypeCell")! - let cryptoscheme: String = record?.cryptoscheme.description ?? "" + let cryptoscheme: String = record?.cryptoProtocol.description ?? "" cell.detailTextLabel?.text = cryptoscheme cell.textLabel?.text = NSLocalizedString("EncryptionType", comment: "Type of Encryption") return cell @@ -122,7 +122,7 @@ extension KeyViewController: UITableViewDataSource { formatter.locale = Locale.current formatter.dateStyle = .medium formatter.timeStyle = .medium - if let discoveryDate = record?.activeKey?.discoveryDate { + if let discoveryDate = record?.discoveryDate { cell.detailTextLabel?.text = formatter.string(from: discoveryDate as Date) } @@ -132,7 +132,7 @@ extension KeyViewController: UITableViewDataSource { let cell = tableView.dequeueReusableCell(withIdentifier: "DiscoveryMailCell")! cell.textLabel?.text = NSLocalizedString("Key.DiscoveryChannel", comment: "Discovered by ") if let label = cell.detailTextLabel { - if record?.key?.firstMail != nil { + if record?.discoveryDate != nil { label.text = NSLocalizedString("Key.DiscoveryChannel.Mail", comment: "mail") } else { @@ -145,7 +145,7 @@ extension KeyViewController: UITableViewDataSource { } else if toRowType(indexPath) == .verified { let cell = tableView.dequeueReusableCell(withIdentifier: "VerifiedCell")! - cell.textLabel?.text = NSLocalizedString("KeyIsVerified", comment: "The Key is verified. The time when the Key was verified") + "\(String(describing: record?.activeKey?.verifiedDate))" + cell.textLabel?.text = NSLocalizedString("KeyIsVerified", comment: "The Key is verified. The time when the Key was verified") + "\(String(describing: record?.verificationDate))" return cell } else if toRowType(indexPath) == .revoked { @@ -157,15 +157,17 @@ extension KeyViewController: UITableViewDataSource { } else if toSectionType(indexPath.section) == .addresses { let cell = tableView.dequeueReusableCell(withIdentifier: "MailAddressCell")! - if let addr = record?.addressNames[indexPath.row] { //TODO: Or of key??? - for ourAddr in (record?.addressNames)! { + /* TODO: compare addresses? if let item = record?.usedAddress?.allObjects[indexPath.row], let addr = item as? String { //TODO: Or of key??? + for ourAddr in (record?.usedAddress?.allObjects)! { if addr.localizedCaseInsensitiveContains(ourAddr) { cell.accessoryType = UITableViewCell.AccessoryType.checkmark break } } + }*/ + if let item = record?.usedAddress?.allObjects[indexPath.row], let addr = item as? AddressRecord { + cell.textLabel?.text = addr.email } - cell.textLabel?.text = record?.addressNames[indexPath.row] return cell } else if toSectionType(indexPath.section) == .keyActions { @@ -189,9 +191,10 @@ extension KeyViewController: UITableViewDataSource { cell.button.setTitle("Change prefered key", for: UIControl.State()) cell.id = KeyActions.Change.hashValue cell.listener = self + /* TODO Fetchcontroller for secret keys if DataHandler.handler.findSecretKeys().count < 2 && !ItunesKeyHandling.iTunesKeyHandler.hasStoredKeys { cell.isHidden = true - } + }*/ cell.isHidden = true } return cell @@ -210,9 +213,9 @@ extension KeyViewController: UITableViewDataSource { } func numberOfSections(in tableView: UITableView) -> Int { - if let key = record?.activeKey { + if let key = record { var sections = 2 - if key.mailaddresses != nil { + if key.usedAddress != nil { sections += 1 } return sections @@ -245,13 +248,13 @@ extension KeyViewController: UITableViewDataSource { func toSectionType(_ sectionNumber: Int) -> KeyViewSectionType { var returnValue: KeyViewSectionType = .noKey - if let record = record, record.activeKey != nil { + if let record = record { returnValue = .keyDetails //addresses if sectionNumber != 0 { returnValue = .keyActions if sectionNumber == 1 { - if record.addresses.count > 0 { + if record.usedAddress?.count ?? 0 > 0 { returnValue = .addresses } } @@ -263,8 +266,8 @@ extension KeyViewController: UITableViewDataSource { func toRowType(_ index: IndexPath) -> KeyViewRowType { var returnValue: KeyViewRowType = .noKey var row = index.row - if let key = record?.activeKey, toSectionType(index.section) == .keyDetails { - returnValue = .keyID + if let key = record, toSectionType(index.section) == .keyDetails { + returnValue = .fingerprint //Fingerprint if row != 0 { returnValue = KeyViewRowType(rawValue: returnValue.rawValue + 1)! @@ -287,12 +290,12 @@ extension KeyViewController: UITableViewDataSource { row -= 1 } //verified - if row != 0 && key.isVerified() { + if row != 0 && key.verificationDate != nil { returnValue = KeyViewRowType(rawValue: returnValue.rawValue + 1)! row -= 1 } //TODO revoked - if row != 0 && key.isExpired() { + if row != 0 && key.expireDate != nil { returnValue = KeyViewRowType(rawValue: returnValue.rawValue + 1)! row -= 1 } @@ -305,7 +308,7 @@ extension KeyViewController: UITableViewDataSource { } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if let mail = record?.key?.firstMail { + if let mail = record?.signedMails?.allObjects.first as? MailRecord{ // Segue to the second view controller self.performSegue(withIdentifier: "firstMail", sender: mail) } @@ -315,7 +318,7 @@ extension KeyViewController: UITableViewDataSource { // This function is called before the segue override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "firstMail" { - if let mail = record?.key?.firstMail { + if let mail = record?.signedMails?.allObjects.first as? MailRecord { if AppDelegate.getAppDelegate().newReadView, let coord = AppDelegate.getAppDelegate().readViewCoordinator { coord.pushReadView(mail: mail) return @@ -332,7 +335,7 @@ extension KeyViewController: ButtonCellHandler { func touchDown(id: Int) { if id == KeyActions.Copy.hashValue { // copy key - guard let record = record, let keyId = record.keyID else { + guard let record = record, let keyId = record.fingerprint else { return } diff --git a/enzevalos_iphone/ListViewController.swift b/enzevalos_iphone/ListViewController.swift index f77dd228382854c050c54ad0981e2597318f060a..49c4e3d3b8a38e2e03b2f0dce2726e4b8a199075 100644 --- a/enzevalos_iphone/ListViewController.swift +++ b/enzevalos_iphone/ListViewController.swift @@ -57,13 +57,13 @@ fileprivate func >= <T : Comparable>(lhs: T?, rhs: T?) -> Bool { class ListViewController: UITableViewController { let searchController = UISearchController(searchResultsController: nil) - var filteredMails = [PersistentMail]() - var contact: KeyRecord? { + var filteredMails = [MailRecord]() + var contact: AddressRecord? { didSet { self.title = contact!.name - if contact!.mails.count < 20 { + if contact!.inToField?.count < 20 { loading = true - AppDelegate.getAppDelegate().mailHandler.loadMailsForRecord(contact!, folderPath: UserManager.backendInboxFolderPath, completionCallback: doneLoading) + // TODO: RELOAD MAILs AppDelegate.getAppDelegate().mailHandler.loadMailsForRecord(contact!, folderPath: UserManager.backendInboxFolderPath, completionCallback: doneLoading) } } } @@ -101,7 +101,7 @@ class ListViewController: UITableViewController { tableView.reloadData() } - func addNewMail(mail: PersistentMail?) { + func addNewMail(mail: MailRecord?) { tableView.reloadData() } @@ -134,21 +134,15 @@ class ListViewController: UITableViewController { str.append(mail.subject ?? "") } if scope == 1 || scope == 3 { - if let decryptedBody = mail.decryptedBody { - str.append(decryptedBody) - } else if let body = mail.body { - str.append(body) - } + str.append(mail.body ?? "") } if scope == 2 || scope == 3 { - var receivers: [MailAddress] = [] - receivers.append(contentsOf: mail.getReceivers()) - receivers.append(contentsOf: mail.getCCs()) + let receivers: [AddressRecord] = mail.addresses // build a string of all email addresses to input in the search function receivers.map({ addr -> String in - return addr.mailAddress + return addr.email ?? "" }).forEach({ addr in str.append(addr) }) @@ -172,7 +166,7 @@ class ListViewController: UITableViewController { } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let mail: PersistentMail? + let mail: MailRecord? if searchController.isActive && searchController.searchBar.text != "" { mail = filteredMails[indexPath.row] @@ -195,9 +189,9 @@ class ListViewController: UITableViewController { } else { cell.subjectLabel.font = UIFont.systemFont(ofSize: 17.0) } - cell.subjectLabel.text = mail?.getSubjectWithFlagsString() + cell.subjectLabel.text = mail?.subjectWithFlag cell.bodyLabel.text = mail?.shortBodyString - cell.dateLabel.text = mail?.timeString + cell.dateLabel.text = mail?.date?.dateToString return cell @@ -205,13 +199,14 @@ class ListViewController: UITableViewController { } override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - let mail: PersistentMail? + let mail: MailRecord? if searchController.isActive && searchController.searchBar.text != "" { mail = filteredMails[indexPath.row] if Logger.logging { // Logger.queue.async(flags: .barrier) { - Logger.log(search: self.filteredMails.count, category: self.searchController.searchBar.selectedScopeButtonIndex, opened: "searchedInMailList", keyRecordMailList: self.contact?.addresses) + // TODO: FIX LOGGING! + // Logger.log(search: self.filteredMails.count, category: self.searchController.searchBar.selectedScopeButtonIndex, opened: "searchedInMailList", keyRecordMailList: self.contact?.addresses) } // } } else if indexPath.row >= contact?.mails.count { @@ -234,14 +229,14 @@ class ListViewController: UITableViewController { let reload_distance: CGFloat = 50 if y > h + reload_distance && !loading { loading = true - AppDelegate.getAppDelegate().mailHandler.loadMailsForRecord(contact!, folderPath: UserManager.backendInboxFolderPath, completionCallback: doneLoading) + // TODO RELOAD MailsAppDelegate.getAppDelegate().mailHandler.loadMailsForRecord(contact!, folderPath: UserManager.backendInboxFolderPath, completionCallback: doneLoading) tableView.reloadData() } } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "readMailSegue" { - if let mail = sender as? PersistentMail { + if let mail = sender as? MailRecord { if AppDelegate.getAppDelegate().newReadView, let coord = AppDelegate.getAppDelegate().readViewCoordinator { coord.pushReadView(mail: mail) return diff --git a/enzevalos_iphone/Logger.swift b/enzevalos_iphone/Logger.swift index 23a4c12093d7dd98a3462660672cb4e8127c02b5..ab846925886ce7f487d51910d4deead14a3124ee 100644 --- a/enzevalos_iphone/Logger.swift +++ b/enzevalos_iphone/Logger.swift @@ -75,13 +75,13 @@ class Logger { return } } - + /* TODO static func log(contactViewOpen keyRecord: KeyRecord?, otherRecords: [KeyRecord]?, isUser: Bool) { if !logging { return } } - + */ static func log(badgeCaseViewOpen badges: [Badges]) { if !logging { return @@ -93,13 +93,13 @@ class Logger { return } } - + /* TODO static func log(contactViewClose keyRecord: KeyRecord?, otherRecords: [KeyRecord]?, isUser: Bool) { if !logging { return } } - + */ static func log(keyViewOpen keyID: String) { if !logging { return @@ -136,6 +136,7 @@ class Logger { sendCheck() } + /* static func log(importPrivateKeyPopupOpen mail: PersistentMail?) { if !logging { return @@ -147,7 +148,8 @@ class Logger { return } } - + */ + /* TODO static func log(importPrivateKey mail: PersistentMail?, success: Bool) { if !logging { return @@ -156,7 +158,7 @@ class Logger { sendCheck() } - + */ static func log(importPrivateKey type: LogData.TransferType, known: Bool, success: Bool) { if !logging { return @@ -196,13 +198,14 @@ class Logger { return } } - + /* static func log(createDraft to: [Mail_Address?], cc: [Mail_Address?], bcc: [Mail_Address?], subject: String, bodyLength: Int, isEncrypted: Bool, isSigned: Bool, myKeyID: String) { if !logging { return } } - + */ + /* TODO static func log(sent from: Mail_Address, to: [Mail_Address], cc: [Mail_Address], bcc: [Mail_Address], subject: String, bodyLength: Int, isEncrypted: Bool, decryptedBodyLength: Int, decryptedWithOldPrivateKey: Bool = false, isSigned: Bool, isCorrectlySigned: Bool = true, signingKeyID: String, myKeyID: String, secureAddresses: [Mail_Address] = [], encryptedForKeyIDs: [String] = [], inviteMailContent: String?, invitationMail: Bool) { if !logging { @@ -293,7 +296,7 @@ class Logger { LogData.importKey(keyType: .publicKey, transferType: importChannel, known: knownBefore, successful: true) sendCheck() } - + */ static func log(backgroundFetch newMails: UInt32, duration: Double) { if !logging { return @@ -430,11 +433,12 @@ public class LogData { static func newSimpleEvent(event: SimpleEvents) { LogInUserDefaults.handler.incrementEventCounter(eventName: event.name) } - static func addMail(mail: PersistentMail, received: Bool) { - let enc = mail.encState - let sig = mail.sigState + static func addMail(mail: MailRecord, received: Bool) { + let enc = mail.encryptionState + let sig = mail.signatureState addMail(enc: enc, sig: sig, received: received) } + static func addMail(enc: EncryptionState, sig: SignatureState, received: Bool) { let key = LogData.makeMailKey(enc: enc, sig: sig, received: received) @@ -679,6 +683,7 @@ public class Maildata: Encodable { private func collectPublicKeyInfos() { + /* TODO let handler = DataHandler.handler let numOfNoKeyAddr = handler.findMailAddress(withKey: false).count let numOfKeyAddr = handler.findMailAddress(withKey: true) @@ -690,5 +695,6 @@ public class Maildata: Encodable { } AddresseswithoutKeys = numOfNoKeyAddr addressesWithKeys = numOfKeysPerAddr + */ } } diff --git a/enzevalos_iphone/Mail.swift b/enzevalos_iphone/Mail.swift index c05a94856d2a66eb9754a7b69e3dd65364e5fe08..306e18593d74aa2cf01acabfb35c0602c34550a4 100644 --- a/enzevalos_iphone/Mail.swift +++ b/enzevalos_iphone/Mail.swift @@ -30,7 +30,7 @@ public protocol Mail: Comparable { var subject: String? { get } var body: String? { get } var uid: UInt64 { get } - var predecessor: PersistentMail? { get } + var predecessor: MailRecord? { get } } public func == <T: Mail> (lhs: T, rhs: T) -> Bool { diff --git a/enzevalos_iphone/MailAddress.swift b/enzevalos_iphone/MailAddress.swift index 8eab2691699d4a1fa76808e1c70cbc2338338055..37d5b8e6283036ab83f406c05c35abcfc8ddab5e 100644 --- a/enzevalos_iphone/MailAddress.swift +++ b/enzevalos_iphone/MailAddress.swift @@ -95,8 +95,17 @@ public protocol MailAddress { var hasKey: Bool { get } var isUser: Bool {get } - var primaryKey: PersistentKey? { get } - var publicKeys: Set<PersistentKey> { get } - var contact: EnzevalosContact? { get } + var primaryKey: PublicKeyRecord? { get } + var publicKeys: Set<PublicKeyRecord> { get } + var contact: Contact? { get } } + +extension MailAddress { + var mcoAddress: MCOAddress { + get { + var name = self.contact?.name ?? mailAddress + return MCOAddress.init(displayName: name, mailbox: mailAddress) + } + } +} diff --git a/enzevalos_iphone/MailHandler.swift b/enzevalos_iphone/MailHandler.swift index d900c05cf08d968cc93a4bad00771865eea86b0b..5522d22cfd540cea4feb7715fc2c7317bed3f724 100644 --- a/enzevalos_iphone/MailHandler.swift +++ b/enzevalos_iphone/MailHandler.swift @@ -49,6 +49,8 @@ fileprivate func > <T : Comparable>(lhs: T?, rhs: T?) -> Bool { class MailHandler { private static let MAXMAILS = 25 private static let extraHeaders = Autocrypt.EXTRAHEADERS + [TravelHandler.backupHeader] + + private let dataProvider = PersitentDataProvider() var delegate: MailHandlerDelegator? static var INBOX: String { @@ -172,22 +174,11 @@ class MailHandler { func storeIMAP(mail: OutgoingMail, folder: String, callback: ((MailServerConnectionError?) -> Void)?) { // 1. Test if folder exists // TODO: Does this really work? Should we test if folder exits on server and not locally? -> Ask Jakob - if !DataHandler.handler.existsFolder(with: folder) { - if let op = IMAPSession?.createFolderOperation(folder) { - op.start({[unowned self] error in - guard error == nil else { - let connerror = MailServerConnectionError.findErrorCode(error: error!) - self.errorhandling(error: connerror, originalCall: {self.storeIMAP(mail: mail, folder: folder, callback: callback)}, completionCallback: callback) - self.IMAPSes = nil - return - } - // Create folder on local - _ = DataHandler.handler.findFolder(with: folder) - self.storeIMAP(mail: mail, folder: folder, callback: callback) - }) - } - } - else { + + + // NEW TODO: How does we store and connect a mail?! + let existFolderController = dataProvider.generateFetchedFolderResultsController(folderpath: folder) + if let folders = existFolderController.fetchedObjects, let folderRecord = folders.first { // 2. Store Mail in test // We can always store encrypted data on the imap server because the user has a key pair and it is users imap account. let op = self.IMAPSession?.appendMessageOperation(withFolder: folder, messageData: mail.pgpData, flags: MCOMessageFlag.mdnSent) @@ -203,6 +194,28 @@ class MailHandler { } }) } + else { + if let op = IMAPSession?.createFolderOperation(folder) { + op.start({[unowned self] error in + guard error == nil else { + let connerror = MailServerConnectionError.findErrorCode(error: error!) + self.errorhandling(error: connerror, originalCall: {self.storeIMAP(mail: mail, folder: folder, callback: callback)}, completionCallback: callback) + self.IMAPSes = nil + return + } + // Create folder on local + let folderProperty = FolderProperties(delimiter: nil, icon: nil, uidValidity: nil, lastUpdate: nil, maxUID: nil, minUID: nil, path: folder) + dataProvider.importData(from: [folderProperty], completionHandler: { error in + guard error == nil else { + // TODO: Error handling + print("Error while creating a folder: \(error)") + return + } + self.storeIMAP(mail: mail, folder: folder, callback: callback) + }) + }) + } + } } func send(_ toEntrys: [String], ccEntrys: [String], bccEntrys: [String], subject: String, message: String, sendEncryptedIfPossible: Bool = true, callback: ((MailServerConnectionError?) -> Void)?, loggingMail: Bool = false, htmlContent: String? = nil, warningReact: Bool = false, inviteMail: Bool = false, textparts: Int = 0, uiState: SendViewMailSecurityState) { @@ -226,7 +239,7 @@ class MailHandler { return } } - DataHandler.handler.addOutgoingMail(mail: mail) + // TODO : DataHandler.handler.addOutgoingMail(mail: mail) } func createDraft(_ toEntrys: [String], ccEntrys: [String], bccEntrys: [String], subject: String, message: String, callback: @escaping (MailServerConnectionError?) -> Void) { @@ -238,7 +251,8 @@ class MailHandler { func startIMAPIdleIfSupported() throws{ if let supported = IMAPIdleSupported { - if supported && IMAPIdleSession == nil, let session = MailHandler.createIMAPSession(), let op = session.idleOperation(withFolder: MailHandler.INBOX, lastKnownUID: UInt32(DataHandler.handler.findFolder(with: MailHandler.INBOX).maxID)){ + let id = UInt32(0) // TODO FIX!!!! UInt32(DataHandler.handler.findFolder(with: MailHandler.INBOX).maxID) + if supported && IMAPIdleSession == nil, let session = MailHandler.createIMAPSession(), let op = session.idleOperation(withFolder: MailHandler.INBOX, lastKnownUID: id){ IMAPIdleSession = session op.start({[unowned self] error in guard error == nil else { @@ -250,21 +264,24 @@ class MailHandler { return } self.IMAPIdleSession = nil - let folder = DataHandler.handler.findFolder(with: MailHandler.INBOX) - self.updateFolder(folder: folder, completionCallback: { error in - guard error == nil else { - self.errorhandling(error: error, originalCall: {do { - try self.startIMAPIdleIfSupported() - } catch{}}, completionCallback: nil) - return - } - do { - try self.startIMAPIdleIfSupported() - } catch{} }) + if let folder = dataProvider.generateFetchedFolderResultsController(folderpath: MailHandler.INBOX).fetchedObjects?.first { + self.updateFolder(folder: folder, completionCallback: { error in + guard error == nil else { + self.errorhandling(error: error, originalCall: {do { + try self.startIMAPIdleIfSupported() + } catch{}}, completionCallback: nil) + return + } + do { + try self.startIMAPIdleIfSupported() + } catch{} }) + } else { + // TODO create folder?! + } }) - + /* //IDLE for Travel-Keymanagement folder - let op2 = IMAPIdleSession!.idleOperation(withFolder: TravelHandler.keyManagementFolder, lastKnownUID: UInt32(DataHandler.handler.findFolder(with: TravelHandler.keyManagementFolder).maxID)) + let op2 = IMAPIdleSession!.idleOperation(withFolder: TravelHandler.keyManagementFolder, lastKnownUID: id) op2?.start({[unowned self] error in guard error == nil else { let connerror = MailServerConnectionError.findErrorCode(error: error!) @@ -287,6 +304,7 @@ class MailHandler { try self.startIMAPIdleIfSupported() } catch{} }) }) + */ } } else { try checkIdleSupport() @@ -328,41 +346,45 @@ class MailHandler { guard IMAPSession != nil else { return } - let f = DataHandler.handler.findFolder(with: folderName) - let folderstatus = IMAPSession?.folderStatusOperation(folderName) - folderstatus?.start {[unowned self] (error, status) -> Void in - guard error == nil else { - let conerror = MailServerConnectionError.findErrorCode(error: error!) - self.errorhandling(error: conerror, originalCall: {self.changeFlag(uid: uid, flags: flags, kind: kind, folderName: folderName)}, completionCallback: nil) - return - } - if let status = status { - let uidValidity = status.uidValidity - if uidValidity == f.uidvalidity { - let op = self.IMAPSession?.storeFlagsOperation(withFolder: folderName, uids: MCOIndexSet.init(index: uid), kind: kind, flags: flags) - op?.start{[unowned self] error -> Void in - guard error == nil else { - let conerror = MailServerConnectionError.findErrorCode(error: error!) - self.errorhandling(error: conerror, originalCall: {self.changeFlag(uid: uid, flags: flags, kind: kind, folderName: folderName)}, completionCallback: nil) - return - } - if flags.contains(MCOMessageFlag.deleted) && kind == MCOIMAPStoreFlagsRequestKind.add { - let operation = self.IMAPSession?.expungeOperation(folderName) - operation?.start({[unowned self] err in - guard err == nil else { - let conerror = MailServerConnectionError.findErrorCode(error: error!) - self.errorhandling(error: conerror, originalCall: {self.changeFlag(uid: uid, flags: flags, kind: kind, folderName: folderName)}, completionCallback: nil) - return - } - DataHandler.handler.deleteMail(with: uid) - }) + if let f = dataProvider.generateFetchedFolderResultsController(folderpath: folderName).fetchedObjects?.first { + let folderstatus = IMAPSession?.folderStatusOperation(folderName) + folderstatus?.start {[unowned self] (error, status) -> Void in + guard error == nil else { + let conerror = MailServerConnectionError.findErrorCode(error: error!) + self.errorhandling(error: conerror, originalCall: {self.changeFlag(uid: uid, flags: flags, kind: kind, folderName: folderName)}, completionCallback: nil) + return + } + if let status = status { + let uidValidity = status.uidValidity + let folderUID = UInt32(truncating: f.uidValidity ?? 0) // TODO IS THIS TRUE???? + if uidValidity == folderUID { + let op = self.IMAPSession?.storeFlagsOperation(withFolder: folderName, uids: MCOIndexSet.init(index: uid), kind: kind, flags: flags) + op?.start{[unowned self] error -> Void in + guard error == nil else { + let conerror = MailServerConnectionError.findErrorCode(error: error!) + self.errorhandling(error: conerror, originalCall: {self.changeFlag(uid: uid, flags: flags, kind: kind, folderName: folderName)}, completionCallback: nil) + return + } + if flags.contains(MCOMessageFlag.deleted) && kind == MCOIMAPStoreFlagsRequestKind.add { + let operation = self.IMAPSession?.expungeOperation(folderName) + operation?.start({[unowned self] err in + guard err == nil else { + let conerror = MailServerConnectionError.findErrorCode(error: error!) + self.errorhandling(error: conerror, originalCall: {self.changeFlag(uid: uid, flags: flags, kind: kind, folderName: folderName)}, completionCallback: nil) + return + } + // TODO: DELETE MAIL DataHandler.handler.deleteMail(with: uid) + }) + } } } } } } + // TODO WHAT IF Folder does not exists? + } - + /* Where to we need this function? func loadMailsForRecord(_ record: KeyRecord, folderPath: String, completionCallback: @escaping ((_ error: MailServerConnectionError?) -> ())) { guard IMAPSession != nil else { completionCallback(MailServerConnectionError.NoData) @@ -411,24 +433,28 @@ class MailHandler { } } + */ func loadMailsForInbox(completionCallback: @escaping ((_ error: MailServerConnectionError?) -> ())) { guard IMAPSession != nil else { completionCallback(MailServerConnectionError.NoData) return } - let folder = DataHandler.handler.findFolder(with: MailHandler.INBOX) - let folderstatus = IMAPSession?.folderStatusOperation(folder.path) - folderstatus?.start {[unowned self] (error, status) -> Void in - guard error == nil else { - let connerror = MailServerConnectionError.findErrorCode(error: error!) - self.errorhandling(error: connerror, originalCall: {self.loadMailsForInbox(completionCallback: completionCallback)}, completionCallback: completionCallback) - return - } - if let status = status { - let uidValidity = status.uidValidity - folder.uidvalidity = uidValidity - self.olderMails(folder: folder, completionCallback: completionCallback) + if let folder = dataProvider.generateFetchedFolderResultsController(folderpath: MailHandler.INBOX).fetchedObjects?.first { + let folderstatus = IMAPSession?.folderStatusOperation(folder.path) + folderstatus?.start {[unowned self] (error, status) -> Void in + guard error == nil else { + let connerror = MailServerConnectionError.findErrorCode(error: error!) + self.errorhandling(error: connerror, originalCall: {self.loadMailsForInbox(completionCallback: completionCallback)}, completionCallback: completionCallback) + return + } + if let status = status { + let uidValidity = status.uidValidity + folder.uidValidity = NSDecimalNumber(value: uidValidity) + self.olderMails(folder: folder, completionCallback: completionCallback) + } } + } else { + // TODO: Generate INBOX } } @@ -437,43 +463,46 @@ class MailHandler { completionCallback(0, completionHandler) return } - let folder = DataHandler.handler.findFolder(with: MailHandler.INBOX) - let folderstatus = IMAPSession?.folderStatusOperation(folder.path) - // Work only in background thread.... - var backgroundTaskID: Int? - DispatchQueue.global(qos: .background).async { - backgroundTaskID = UIApplication.shared.beginBackgroundTask (withName: "Finish Network Tasks"){ - UIApplication.shared.endBackgroundTask(convertToUIBackgroundTaskIdentifier(backgroundTaskID!)) - backgroundTaskID = convertFromUIBackgroundTaskIdentifier(UIBackgroundTaskIdentifier.invalid) - }.rawValue - folderstatus?.start{(error, status) -> Void in - guard error == nil else { + if let folder = dataProvider.generateFetchedFolderResultsController(folderpath: MailHandler.INBOX).fetchedObjects?.first { + let folderstatus = IMAPSession?.folderStatusOperation(folder.path) + // Work only in background thread.... + var backgroundTaskID: Int? + DispatchQueue.global(qos: .background).async { + backgroundTaskID = UIApplication.shared.beginBackgroundTask (withName: "Finish Network Tasks"){ UIApplication.shared.endBackgroundTask(convertToUIBackgroundTaskIdentifier(backgroundTaskID!)) backgroundTaskID = convertFromUIBackgroundTaskIdentifier(UIBackgroundTaskIdentifier.invalid) - completionCallback(0, completionHandler) - return - } - if let status = status { - let uidValidity = status.uidValidity - let uid = status.uidNext - var newMails: UInt32 = 0 - var diff = uid.subtractingReportingOverflow(UInt32(folder.maxID)) - diff = diff.partialValue.subtractingReportingOverflow(1) - if diff.overflow { - newMails = 0 - } - else { - newMails = diff.partialValue - } - if (uidValidity != folder.uidvalidity || folder.maxID < uid - 1) { - UIApplication.shared.endBackgroundTask(convertToUIBackgroundTaskIdentifier(backgroundTaskID!)) - backgroundTaskID = convertFromUIBackgroundTaskIdentifier(UIBackgroundTaskIdentifier.invalid) - completionCallback(newMails, completionHandler) - } - else { + }.rawValue + folderstatus?.start{(error, status) -> Void in + guard error == nil else { UIApplication.shared.endBackgroundTask(convertToUIBackgroundTaskIdentifier(backgroundTaskID!)) backgroundTaskID = convertFromUIBackgroundTaskIdentifier(UIBackgroundTaskIdentifier.invalid) completionCallback(0, completionHandler) + return + } + if let status = status { + let uidValidity = status.uidValidity + let uid = status.uidNext + var newMails: UInt32 = 0 + var max = UInt32(truncating: folder.maxUID ?? 0) // TODO CHECK WHAT SHOULD BE MAX? + var folderUidValidity = UInt32(folder.uidValidity ?? 0) // TODO CHECK! + var diff = uid.subtractingReportingOverflow(max) + diff = diff.partialValue.subtractingReportingOverflow(1) + if diff.overflow { + newMails = 0 + } + else { + newMails = diff.partialValue + } + if (uidValidity != folderUidValidity || max < uid - 1) { + UIApplication.shared.endBackgroundTask(convertToUIBackgroundTaskIdentifier(backgroundTaskID!)) + backgroundTaskID = convertFromUIBackgroundTaskIdentifier(UIBackgroundTaskIdentifier.invalid) + completionCallback(newMails, completionHandler) + } + else { + UIApplication.shared.endBackgroundTask(convertToUIBackgroundTaskIdentifier(backgroundTaskID!)) + backgroundTaskID = convertFromUIBackgroundTaskIdentifier(UIBackgroundTaskIdentifier.invalid) + completionCallback(0, completionHandler) + } } } } @@ -538,6 +567,7 @@ class MailHandler { } } + /* public func getRepeals(for keyID: String) -> [Repeal] { let mails = DataHandler.handler.allMailsInFolder(key: keyID, contact: nil, folder: DataHandler.handler.findFolder(with: TravelHandler.keyManagementFolder), isSecure: true) var repeals: [Repeal] = [] @@ -865,8 +895,9 @@ class MailHandler { return nil } + */ - func move(mails: [PersistentMail], from: String, to: String, folderCreated: Bool = false) { + func move(mails: [MailRecord], from: String, to: String, folderCreated: Bool = false) { guard IMAPSession != nil else { return } @@ -947,7 +978,7 @@ class MailHandler { } - private func initFolder(folder: Folder, completionCallback: @escaping ((MailServerConnectionError?) -> ())) { + private func initFolder(folder: FolderRecord, completionCallback: @escaping ((MailServerConnectionError?) -> ())) { let folderPath = folder.path let requestKind = MCOIMAPMessagesRequestKind(rawValue: MCOIMAPMessagesRequestKind.headers.rawValue) let uids = MCOIndexSet(range: MCORangeMake(1, UINT64_MAX)) @@ -972,7 +1003,7 @@ class MailHandler { } } - private func initInbox(inbox: Folder, completionCallback: @escaping ((MailServerConnectionError?) -> ())) { + private func initInbox(inbox: FolderRecord, completionCallback: @escaping ((MailServerConnectionError?) -> ())) { if let date = Calendar.current.date(byAdding: .month, value: -1, to: Date()) { loadMailsSinceDate(folder: inbox, since: date, maxLoad: 100, completionCallback: completionCallback) } else { @@ -981,7 +1012,7 @@ class MailHandler { } - func updateFolder(folder: Folder, completionCallback: @escaping ((MailServerConnectionError?) -> ())) { guard IMAPSession != nil else { + func updateFolder(folder: FolderRecord, completionCallback: @escaping ((MailServerConnectionError?) -> ())) { guard IMAPSession != nil else { completionCallback(MailServerConnectionError.NoData) return } @@ -997,7 +1028,7 @@ class MailHandler { } } - private func calculateIndicies(indicies: MCOIndexSet, folder: Folder, multipleMails: Bool) -> MCOIndexSet { + private func calculateIndicies(indicies: MCOIndexSet, folder: FolderRecord, multipleMails: Bool) -> MCOIndexSet { var factor = 1 if multipleMails { factor = 3 @@ -1052,7 +1083,7 @@ class MailHandler { return requestIds } - private func loadMailsByNum(folder: Folder, completionCallback: @escaping ((MailServerConnectionError?) -> ()), multipleMails: Bool) { + private func loadMailsByNum(folder: FolderRecord, completionCallback: @escaping ((MailServerConnectionError?) -> ()), multipleMails: Bool) { guard let session = IMAPSession else { completionCallback(MailServerConnectionError.NoData) return @@ -1075,7 +1106,7 @@ class MailHandler { } - private func olderMails(folder: Folder, completionCallback: @escaping ((MailServerConnectionError?) -> ())) { + private func olderMails(folder: FolderRecord, completionCallback: @escaping ((MailServerConnectionError?) -> ())) { guard IMAPSession != nil else { completionCallback(MailServerConnectionError.NoData) return @@ -1086,7 +1117,7 @@ class MailHandler { initFolder(folder: folder, completionCallback: completionCallback) } } - private func loadMailsSinceDate(folder: Folder, since: Date, maxLoad: Int = MailHandler.MAXMAILS, completionCallback: @escaping ((MailServerConnectionError?) -> ())) { + private func loadMailsSinceDate(folder: FolderRecord, since: Date, maxLoad: Int = MailHandler.MAXMAILS, completionCallback: @escaping ((MailServerConnectionError?) -> ())) { guard IMAPSession != nil else { completionCallback(MailServerConnectionError.NoData) return diff --git a/enzevalos_iphone/MailHandlerDelegator.swift b/enzevalos_iphone/MailHandlerDelegator.swift index 43113ce9c4a3a39b6aa88aef7a41dc6b2bf5e2c1..b7996193c13212d66a81d5d5166c5f01ca6a5a00 100644 --- a/enzevalos_iphone/MailHandlerDelegator.swift +++ b/enzevalos_iphone/MailHandlerDelegator.swift @@ -21,6 +21,6 @@ import Foundation protocol MailHandlerDelegator { - func addNewMail(_ mail: PersistentMail) + func addNewMail(_ mail: MailRecord) func getMailCompleted() } diff --git a/enzevalos_iphone/Mail_Address+CoreDataClass.swift b/enzevalos_iphone/Mail_Address+CoreDataClass.swift deleted file mode 100644 index 17d570ce529664a7efaf0378616525bf1c436ade..0000000000000000000000000000000000000000 --- a/enzevalos_iphone/Mail_Address+CoreDataClass.swift +++ /dev/null @@ -1,92 +0,0 @@ -// -// Mail_Address+CoreDataClass.swift -// enzevalos_iphone -// -// Created by Oliver Wiese on 05/01/17. -// Copyright © 2018 fu-berlin. -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. -// This file was automatically generated and should not be edited. -// - -import Foundation -import CoreData -import Contacts - -@objc(Mail_Address) -open class Mail_Address: NSManagedObject, MailAddress { - /** - What key should be used to send encrypted messages or to verify messages? - */ - public var primaryKey: PersistentKey? { - get { - if hasKey { - for key in publicKeys { - if key.currentlyActiveKey.keyID == primaryActiveKeyID { - return key - } - } - } - return nil - } - } - - - open var mailAddress: String { - return address.lowercased() - } - - /** - In the address book a mail address has a label (e.g. work, private, ...). - */ - open var label: CNLabeledValue<NSString> { - if let cnc = self.contact?.cnContact { - for adr in cnc.emailAddresses { - if adr.value as String == address { - return adr - } - } - } - return CNLabeledValue.init(label: CNLabelOther, value: address as NSString) - } - - open var hasKey: Bool { - if publicKeys.count > 0 { - return true - } - return false - } - - /** - Is this a mail address of the user? - */ - public var isUser: Bool { - get { - if let userAddr = UserManager.loadUserValue(Attribute.userAddr) as? String { - return self.address.lowercased() == userAddr.lowercased() - } - return false - } - } - - /** - Just create a MCOAddress. Mailcore (our IMAP/SMTP library) needs MCOAddresses to send mails etc. - */ - public func transform () -> MCOAddress { - var name = address - if let contact = contact { - name = contact.name - } - return MCOAddress.init(displayName: name, mailbox: address) - } -} diff --git a/enzevalos_iphone/Mail_Address+CoreDataProperties.swift b/enzevalos_iphone/Mail_Address+CoreDataProperties.swift deleted file mode 100644 index ce3c0a68898508d082a4c27f6673fbb812c42946..0000000000000000000000000000000000000000 --- a/enzevalos_iphone/Mail_Address+CoreDataProperties.swift +++ /dev/null @@ -1,232 +0,0 @@ -// -// Mail_Address+CoreDataProperties.swift -// enzevalos_iphone -// -// Created by Oliver Wiese on 05/01/17. -// Copyright © 2018 fu-berlin. -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. -// This file was automatically generated and should not be edited. -// - -import Foundation -import SwiftUI -import CoreData - -extension Mail_Address { - - @nonobjc open override class func fetchRequest() -> NSFetchRequest<NSFetchRequestResult> { - return NSFetchRequest(entityName: "Mail_Address"); - } - - @NSManaged public var address: String - @NSManaged public var contact: EnzevalosContact? - @NSManaged public var bcc: NSSet? - @NSManaged public var cc: NSSet? - @NSManaged public var from: NSSet? - @NSManaged public var to: NSSet? - /** - Just for logging. - */ - @NSManaged public var pseudonym: String - /** - What key should be used to send encrypted messages or to verify messages? - */ - @NSManaged public var primaryKeyID: String? - @NSManaged private var keys: NSSet? - /** - Did we invited the mail address owner to use encryption? - */ - @NSManaged public var invitations: Int16 - - var primaryActiveKeyID: String? { - get { - if let primaryKeyID = primaryKeyID { - return DataHandler.handler.findKey(keyID: primaryKeyID)?.currentlyActiveKey.keyID - } - return nil - } - set(newKeyID) { - //TODO: we should check if newKeyID is related to a key in keys. - if let newKeyID = newKeyID, let key = DataHandler.handler.findKey(keyID: newKeyID) { - //update the active member of the regarding Keygroup - key.currentlyActiveKey = key - primaryKeyID = key.rootKey.keyID - } - } - } - - open var publicKeys: Set<PersistentKey> { - get { - if let pks = keys { - if let set = pks as? Set<PersistentKey> { - let array = Array(set) - var publicKeys: [PersistentKey] = [] - for entry in array { - publicKeys.append(contentsOf: entry.relatedKeys) - } - return Set(publicKeys) - } - } - return Set<PersistentKey>() - } - } -} - - -// MARK: Generated accessors for bcc -extension Mail_Address { - - @objc(addBccObject:) - @NSManaged public func addToBcc(_ value: PersistentMail) - - @objc(removeBccObject:) - @NSManaged public func removeFromBcc(_ value: PersistentMail) - - @objc(addBcc:) - @NSManaged public func addToBcc(_ values: NSSet) - - @objc(removeBcc:) - @NSManaged public func removeFromBcc(_ values: NSSet) - -} - -// MARK: Generated accessors for cc -extension Mail_Address { - - @objc(addCcObject:) - @NSManaged public func addToCc(_ value: PersistentMail) - - @objc(removeCcObject:) - @NSManaged public func removeFromCc(_ value: PersistentMail) - - @objc(addCc:) - @NSManaged public func addToCc(_ values: NSSet) - - @objc(removeCc:) - @NSManaged public func removeFromCc(_ values: NSSet) - -} - -// MARK: Generated accessors for to -extension Mail_Address { - - @objc(addToObject:) - @NSManaged public func addToTo(_ value: PersistentMail) - - @objc(removeToObject:) - @NSManaged public func removeFromTo(_ value: PersistentMail) - - @objc(addTo:) - @NSManaged public func addToTo(_ values: NSSet) - - @objc(removeTo:) - @NSManaged public func removeFromTo(_ values: NSSet) - -} - -// MARK: Generated accessors for key -extension Mail_Address { - - public func addToKeys(key value: PersistentKey) { - addToKeys(value.rootKey) - } - - @objc(addKeysObject:) - @NSManaged private func addToKeys(_ value: PersistentKey) - - @objc(removeKeysObject:) - @NSManaged private func removeFromKeys(_ value: PersistentKey) - - @objc(addKeys:) - @NSManaged private func addToKeys(_ values: NSSet) - - @objc(removeKeys:) - @NSManaged private func removeFromKeys(_ values: NSSet) - -} - -extension Mail_Address: DisplayContact { - var name: String { - if let contact = self.contact { - return contact.name - } - return self.addr - } - - var addr: String { - return self.address - } - - var myImage: Image { - if let contact = self.contact { - return Image(uiImage: contact.getImageOrDefault()) - } - let color = UIColor(hue: CGFloat(addr.hashValue) / CGFloat(UINT32_MAX), saturation: 1, brightness: 0.75, alpha: 1) - return PseudoContact.makeImg(addr, color: color) - } - - var isInContactBook: Bool { - if let con = self.contact { - return con.cnContact != nil - } - return false - } - - var otherAddresses: [String] { - if let con = contact { - return con.getMailAddresses().map({$0.mailAddress}) - } - return [] - } - - var keyIDs: [String] { - let pks = self.publicKeys.map({$0.keyID}) - return pks - } - - var previousMails: Int { - if let from = from { - return from.count - } - return 0 - } - - var previousResponses: Int { - var responses = 0 - if let to = self.to { - responses += to.count - } - if let cc = self.cc { - responses += cc.count - } - if let bcc = self.bcc { - responses += bcc.count - } - return responses - } - - var hasSimilarContacts: Bool { - return false - } - - var similarContacts: [String] { - return [] - } - - var keyRecord: KeyRecord? { - return DataHandler.handler.getKeyRecord(addr: addr, keyID: self.primaryKeyID, saveRecord: false) - } - - -} diff --git a/enzevalos_iphone/New Group/Mailbot.swift b/enzevalos_iphone/New Group/Mailbot.swift index 65dc25032bbd72fe13606b7d40ee4de5b5f40ada..5e996b033bdd05662f0832575e5b27dd62337676 100644 --- a/enzevalos_iphone/New Group/Mailbot.swift +++ b/enzevalos_iphone/New Group/Mailbot.swift @@ -72,6 +72,7 @@ class Mailbot { let senderAdr = SUPPORT_MAIL_ADR let sender = MCOAddress.init(displayName: "Letterbox-Team", mailbox: senderAdr) var keyID: String? + /* TODO if let addr = DataHandler.handler.findMailAddress(adr: senderAdr) { if let pk = addr.primaryKey { keyID = pk.keyID @@ -80,5 +81,6 @@ class Mailbot { let cryptoObject = CryptoObject(chiphertext: nil, plaintext: body, decryptedData: body.data(using: .utf8), sigState: SignatureState.ValidSignature, encState: EncryptionState.ValidedEncryptedWithCurrentKey, signKey: keyID, encType: CryptoScheme.PGP, signedAdrs: [senderAdr]) _ = DataHandler.handler.createMail(0, sender: sender, receivers: [], cc: [], time: Date(), received: false, subject: subject, body: body, flags: MCOMessageFlag.init(rawValue: 0), record: nil, autocrypt: nil, decryptedData: cryptoObject, folderPath: UserManager.backendInboxFolderPath, secretKey: nil, encryptedBody: cryptoObject.chiperString) + */ } } diff --git a/enzevalos_iphone/OutgoingMail.swift b/enzevalos_iphone/OutgoingMail.swift index 52904e4394bb752a37498454792a2f42634242e9..5e2ce83ced1d3a6c59d5c3aed5851bd11656fec4 100644 --- a/enzevalos_iphone/OutgoingMail.swift +++ b/enzevalos_iphone/OutgoingMail.swift @@ -36,9 +36,10 @@ class OutgoingMail { } } } - private var sk: SecretKey? { + private var sk: SecretKeyRecord? { get { - return DataHandler.handler.prefSecretKey() + //TODO return DataHandler.handler.prefSecretKey() + return nil } } private let subject: String @@ -103,7 +104,7 @@ class OutgoingMail { return nil } - private var mail: PersistentMail? + private var mail: MailRecord? init(toEntrys: [String], ccEntrys: [String], bccEntrys: [String], subject: String, textContent: String, htmlContent: String?, textparts: Int = 0, sendEncryptedIfPossible: Bool = true, attachments: [MCOAttachment] = []) { self.toEntrys = OutgoingMail.mapToMCOAddresses(addr: toEntrys) @@ -125,22 +126,24 @@ class OutgoingMail { } - init(mail: PersistentMail){ - toEntrys = OutgoingMail.mapToMCOAddresses(addr: mail.getReceivers()) - ccEntrys = OutgoingMail.mapToMCOAddresses(addr: mail.getCCs()) - bccEntrys = OutgoingMail.mapToMCOAddresses(addr: mail.getBCCs()) + init(mail: MailRecord){ + toEntrys = OutgoingMail.mapToMCOAddresses(addr: mail.tos) + ccEntrys = OutgoingMail.mapToMCOAddresses(addr: mail.ccs) + bccEntrys = OutgoingMail.mapToMCOAddresses(addr: mail.bccs) subject = mail.subject != nil ? mail.subject!: "" textContent = mail.body - htmlContent = mail.decryptedBody //TODO FIX HERE + //TODO htmlContent = mail.decryptedBody //TODO FIX HERE textparts = 0 //TODO FIX HERE - sendEncryptedIfPossible = mail.isEncrypted //TODO FIX HERE + //sendEncryptedIfPossible = mail.isEncrypted //TODO FIX HERE self.orderReceivers() self.mail = mail - self.loggingMail = mail.isCorrectlySigned //TODO FIX HERE - self.attachedSignature = mail.attachedSignature + //self.loggingMail = mail.isCorrectlySigned //TODO FIX HERE + //TODO ??? self.attachedSignature = mail.attachedSignature } - func store() -> PersistentMail? { + func store() -> MailRecord? { + //TPODO Generate a mail record + /* let me = MCOAddress.init(displayName: username, mailbox: useraddr) let mail = DataHandler.handler.createMail(0, sender: me, receivers: toEntrys, cc: ccEntrys, time: Date(), received: false, subject: subject, body: textContent, flags: MCOMessageFlag.seen, record: nil, autocrypt: nil, decryptedData: nil, folderPath: DataHandler.handler.outgoingFolder, secretKey: nil, encryptedBody: nil) mail?.decryptedBody = htmlContent @@ -149,6 +152,8 @@ class OutgoingMail { mail?.attachedSignature = self.attachedSignature self.mail = mail return mail + */ + return nil } func addTextAttachment(text: String) { @@ -172,7 +177,7 @@ class OutgoingMail { func send(informUser: Bool = false) { self.informUser = informUser if let mail = mail { - DataHandler.handler.delete(mail: mail) + // TODO Remove mail DataHandler.handler.delete(mail: mail) } AppDelegate.getAppDelegate().mailHandler.sendSMTP(mail: self, callback: sendCallback) } @@ -186,7 +191,7 @@ class OutgoingMail { } } else { - DataHandler.handler.startToSendMore() + // TODO DataHandler.handler.startToSendMore() } } @@ -199,29 +204,29 @@ class OutgoingMail { if loggingMail { return false } - let fromLogging: Mail_Address = DataHandler.handler.getMailAddress(useraddr, temporary: false) as! Mail_Address - let toLogging: [Mail_Address] = [] - let ccLogging: [Mail_Address] = [] - let bccLogging: [Mail_Address] = [] + // TODO let fromLogging: MailAddress = DataHandler.handler.getMailAddress(useraddr, temporary: false) as! Mail_Address + let toLogging: [MailAddress] = [] + let ccLogging: [MailAddress] = [] + let bccLogging: [MailAddress] = [] let secureAddrsInString = pgpAddresses.map { $0.mailbox } - var secureAddresses: [Mail_Address] = [] + var secureAddresses: [MailAddress] = [] for addr in toLogging { for sec in secureAddrsInString { - if addr.address == sec { + if addr.mailAddress == sec { secureAddresses.append(addr) } } } for addr in ccLogging { for sec in secureAddrsInString { - if addr.address == sec { + if addr.mailAddress == sec { secureAddresses.append(addr) } } } for addr in bccLogging { for sec in secureAddrsInString { - if addr.address == sec { + if addr.mailAddress == sec { secureAddresses.append(addr) } } @@ -235,22 +240,22 @@ class OutgoingMail { let isSig = co.signatureState == .ValidSignature || co.signatureState == .InvalidSignature || co.signatureState == .NoPublicKey let isCorSig = co.signatureState == .ValidSignature if isDraft { - Logger.log(createDraft: toLogging, cc: ccLogging, bcc: bccLogging, subject: subject, bodyLength: textContent?.count ?? 0, isEncrypted: isEnc, isSigned: isSig, myKeyID: keyID ?? "") + //TODO Logger.log(createDraft: toLogging, cc: ccLogging, bcc: bccLogging, subject: subject, bodyLength: textContent?.count ?? 0, isEncrypted: isEnc, isSigned: isSig, myKeyID: keyID ?? "") } else { - Logger.log(sent: fromLogging, to: toLogging, cc: ccLogging, bcc: bccLogging, subject: subject, bodyLength: co.chiperString?.count ?? 0, isEncrypted: isEnc, decryptedBodyLength: ("\n" + (co.plaintext ?? "")).count, decryptedWithOldPrivateKey: false, isSigned: isSig, isCorrectlySigned: isCorSig, signingKeyID: co.signKey ?? "", myKeyID: sk?.keyID ?? "", secureAddresses: secureAddresses, encryptedForKeyIDs: OutgoingMail.addKeys(adrs: pgpAddresses), inviteMailContent: inviteMailContent, invitationMail: inviteMail) + //TODO Logger.log(sent: fromLogging, to: toLogging, cc: ccLogging, bcc: bccLogging, subject: subject, bodyLength: co.chiperString?.count ?? 0, isEncrypted: isEnc, decryptedBodyLength: ("\n" + (co.plaintext ?? "")).count, decryptedWithOldPrivateKey: false, isSigned: isSig, isCorrectlySigned: isCorSig, signingKeyID: co.signKey ?? "", myKeyID: sk?.keyID ?? "", secureAddresses: secureAddresses, encryptedForKeyIDs: OutgoingMail.addKeys(adrs: pgpAddresses), inviteMailContent: inviteMailContent, invitationMail: inviteMail) } } //TODO: double logging? crpyto mail and plain mail? else { if isDraft { - Logger.log(createDraft: toLogging, cc: ccLogging, bcc: bccLogging, subject: subject, bodyLength: textContent?.count ?? 0, isEncrypted: false, isSigned: false, myKeyID: "") + //TODO Logger.log(createDraft: toLogging, cc: ccLogging, bcc: bccLogging, subject: subject, bodyLength: textContent?.count ?? 0, isEncrypted: false, isSigned: false, myKeyID: "") } else { var textContentCount = textContent?.count ?? 0 if textContentCount != 0 { textContentCount += 1 //for \n } - Logger.log(sent: fromLogging, to: toLogging, cc: ccLogging, bcc: bccLogging, subject: subject, bodyLength: textContentCount, isEncrypted: false, decryptedBodyLength: textContentCount , decryptedWithOldPrivateKey: false, isSigned: false, isCorrectlySigned: false, signingKeyID: "", myKeyID: "", secureAddresses: [], encryptedForKeyIDs: [], inviteMailContent: inviteMailContent, invitationMail: inviteMail) + // TODO Logger.log(sent: fromLogging, to: toLogging, cc: ccLogging, bcc: bccLogging, subject: subject, bodyLength: textContentCount, isEncrypted: false, decryptedBodyLength: textContentCount , decryptedWithOldPrivateKey: false, isSigned: false, isCorrectlySigned: false, signingKeyID: "", myKeyID: "", secureAddresses: [], encryptedForKeyIDs: [], inviteMailContent: inviteMailContent, invitationMail: inviteMail) } } return true @@ -286,8 +291,7 @@ class OutgoingMail { var missingOwnPublic = false var pgpKeyIds: [String] = [] var skKeyID = "" - if let sk = sk { - let skID = sk.keyID + if let sk = sk, let skID = sk.fingerprint { pgpKeyIds.append(skID) skKeyID = skID } @@ -298,15 +302,16 @@ class OutgoingMail { } // We add our public if one uses pgp but may not our public key for id in pgpKeyIds { + /* TODO if let key = DataHandler.handler.findKey(keyID: id) { if !key.sentOwnPublicKey { missingOwnPublic = true key.sentOwnPublicKey = true } } + */ } - if missingOwnPublic, let sk = sk { - let id = sk.keyID + if missingOwnPublic, let sk = sk, let id = sk.fingerprint { if let myPK = pgp.exportKey(id: id, isSecretkey: false, autocrypt: false), let data = myPK.data(using: .utf8) { addAttachment(filename: "\(id).asc", mimeType: "application/pgp-keys", charset: nil, data: data) } @@ -326,6 +331,7 @@ class OutgoingMail { } private func orderReceiver(receiver: MCOAddress) { + /* TODO if let adr = DataHandler.handler.findMailAddress(adr: receiver.mailbox) { let recommandation = Autocrypt.recommandateEncryption(receiver: adr) if recommandation.recommandEnc && self.sendEncryptedIfPossible, let primaryKey = adr.primaryKey, !primaryKey.currentlyActiveKey.repealed { @@ -336,7 +342,7 @@ class OutgoingMail { } } else { plainAddresses.append(receiver) - } + } */ } @@ -377,16 +383,18 @@ class OutgoingMail { }) } - private static func mapToMCOAddresses(addr: [Mail_Address]) -> [MCOAddress]{ - return addr.map{$0.transform()} + private static func mapToMCOAddresses(addr: [MailAddress]) -> [MCOAddress]{ + return addr.map{$0.mcoAddress} } private static func addKeys(adrs: [MCOAddress]) -> [String] { var ids = [String]() for a in adrs { + /* TODO FInd if let adr = DataHandler.handler.findMailAddress(adr: a.mailbox), let key = adr.primaryKey?.keyID { ids.append(key) } + */ } return ids } diff --git a/enzevalos_iphone/PersistentKey+CoreDataClass.swift b/enzevalos_iphone/PersistentKey+CoreDataClass.swift deleted file mode 100644 index d908198e6c8c7b0b6923b2600754b745f1ec2459..0000000000000000000000000000000000000000 --- a/enzevalos_iphone/PersistentKey+CoreDataClass.swift +++ /dev/null @@ -1,84 +0,0 @@ -// -// PersistentKey+CoreDataClass.swift -// -// -// Created by Oliver Wiese on 27.09.17. -// -// - -import Foundation -import CoreData - -/** - Is a stored public key. - - It stores the keydata, some additional information and relations to key records etc. - - A key can be part of a key chain, such that one key introduced another key (yet not implemented) - */ -@objc(PersistentKey) -public class PersistentKey: NSManagedObject { - - var counterSignedMails: Int { - if let signedMails = self.signedMails { - return signedMails.count - } - return 0 - } - - var lastReceivedMail: PersistentMail? { - var lastMail: PersistentMail? - for m in signedMails ?? [] { - if let mail = m as? PersistentMail { - if lastMail == nil { - lastMail = mail - }else if let l = lastMail, l.date < mail.date { - lastMail = mail - } - } - } - return lastMail - } - - func verify() { - failedCallForUse = false - repealed = false - misstrust = false - self.verifiedDate = Date.init() - } - - func isVerified() -> Bool { - return self.verifiedDate != nil - } - - /** - Is the key expired (according to the crypto scheme)? - */ - func isExpired() -> Bool { - let pgp = SwiftPGP() - if let key = pgp.loadKey(id: self.keyID) { - if let expire = key.expirationDate { - return expire < Date.init() - } - return false - } - return true - } - - public var fingerprint: String? { - get { - let pgp = SwiftPGP() - if let k = pgp.loadKey(id: self.keyID) { - if let pk = k.publicKey { - return pk.fingerprint.description() - } - else if let sk = k.secretKey { - return sk.fingerprint.description() - } - return k.keyID.longIdentifier - } - return nil - } - } - -} diff --git a/enzevalos_iphone/PersistentKey+CoreDataProperties.swift b/enzevalos_iphone/PersistentKey+CoreDataProperties.swift deleted file mode 100644 index dc7f0cf71d5f8f7b7cf958236836b44145282a1d..0000000000000000000000000000000000000000 --- a/enzevalos_iphone/PersistentKey+CoreDataProperties.swift +++ /dev/null @@ -1,320 +0,0 @@ -// -// PersistentKey+CoreDataProperties.swift -// -// -// Created by Oliver Wiese on 27.09.17. -// -// - -import Foundation -import CoreData - - -extension PersistentKey { - - @nonobjc public class func fetchRequest() -> NSFetchRequest<PersistentKey> { - return NSFetchRequest<PersistentKey>(entityName: "PersistentKey") - } - - @NSManaged public var keyID: String - @NSManaged public var verifiedDate: Date? - /** - When did we received the last signed mail? - */ - @NSManaged public var lastSeen: Date? - /** - When did we received the last mail with autocrypt header? - */ - @NSManaged public var lastSeenAutocrypt: Date? - /** - When did we imported the key? - */ - @NSManaged public var discoveryDate: Date? - @NSManaged private var mailaddress: NSSet? - /** - What is the mail which contains this key (only the first)? - */ - @NSManaged public var firstMail: PersistentMail? - /** - A pseudonym was used for logging. - */ - @NSManaged public var pseudonym: String - /** - Did we send our own public key to the owner of this public key? - This means does the owner knows our public key? - */ - @NSManaged public var sentOwnPublicKey: Bool - @NSManaged public var signedMails: NSSet? - @NSManaged private var record: KeyRecord? - @NSManaged private var activeKey: PersistentKey? - /** - This is only for the travler scenario. You can ignore it. - */ - @NSManaged public var activeRepeal: PersistentMail? - /** - Currently not used. - */ - @NSManaged private var parentKey: PersistentKey? - /** - Currently not used. - */ - @NSManaged private var childKeys: NSSet? - /** - This is only for the travler scenario. You can ignore it. - */ - @NSManaged public var repealedByMails: NSSet? - /** - This is only for the travler scenario. You can ignore it. - */ - @NSManaged private var isRepealed: Bool - /** - This is only for the travler scenario. You can ignore it. - */ - @NSManaged private var gotFailedCallForUse: Bool - /** - This is only for the travler scenario. You can ignore it. - */ - @NSManaged private var isMisstrusted: Bool - - var mailaddresses: NSSet? { - get { - return rootKey.mailaddress - } - set(newSet) { - rootKey.mailaddress = newSet - } - } - - var keyRecord: KeyRecord? { - get { - return rootKey.record - } - set(newRecord) { - rootKey.record = newRecord - } - } - - var parent: PersistentKey? { - get { - return parentKey - } - } - - var hasParent: Bool { - return parentKey != nil - } - - /** - Currently not used. - */ - var rootKey: PersistentKey { - get { - var key = self - while key.hasParent { - key = key.parentKey! - } - return key - } - } - - var childs: [PersistentKey] { - if let keys = childKeys { - return Array(keys) as? [PersistentKey] ?? [] - } - return [] - } - - var currentlyActiveKey: PersistentKey { - get { - if let active = rootKey.activeKey { - return active - } - return rootKey - } - set(newKey) { - if relatedKeys.contains(newKey) { - rootKey.activeKey = newKey - } - } - } - - var relatedKeys: [PersistentKey] { - var keys = rootKey.getNodesBelow() - keys.append(rootKey) - return keys - } - /** - This is only for the travler scenario. You can ignore it. - */ - public var repealed: Bool { - get { - return rootKey.isRepealed - } - set(newRepealState) { - rootKey.isRepealed = newRepealState - } - } - /** - This is only for the travler scenario. You can ignore it. - */ - public var failedCallForUse: Bool { - get { - return rootKey.gotFailedCallForUse - } - set(newState) { - rootKey.gotFailedCallForUse = newState - } - } - /** - This is only for the travler scenario. You can ignore it. - */ - public var misstrust: Bool { - get { - return rootKey.isMisstrusted - } - set(trust) { - rootKey.isMisstrusted = trust - } - } - /** - This is the autocrypt prefer enc state. - */ - public var prefer_encryption: AutocryptState{ - set { - let name = "preferEncryption" - self.willChangeValue(forKey: name) - self.setPrimitiveValue(newValue.asInt(), forKey: name) - self.didChangeValue(forKey: name) - } - get { - - let name = "preferEncryption" - self.willAccessValue(forKey: name) - if let i = self.primitiveValue(forKey: name) { - let value = i as! Int - self.didAccessValue(forKey: name) - return AutocryptState.find(i: value) - } - return AutocryptState.NOAUTOCRYPT - } - } - - public var encryptionType: CryptoScheme{ - set{ - let name = "encryptionType" - self.willChangeValue(forKey: name) - self.setPrimitiveValue(newValue.asInt(), forKey: name) - self.didChangeValue(forKey: name) - } - get { - - let name = "encryptionType" - self.willAccessValue(forKey: name) - let i = self.primitiveValue(forKey: name) as! Int - self.didAccessValue(forKey: name) - return CryptoScheme.find(i: i) - } - } - - private func getNodesBelow() -> [PersistentKey] { - let myChilds = childs - var result: [PersistentKey] = myChilds - for child in myChilds { - result.append(contentsOf: child.getNodesBelow()) - } - return result - } - - public func addChild(child: PersistentKey) { - if !child.hasParent && !relatedKeys.contains(child) { - if let addresses = child.mailaddress as? Set<Mail_Address> { - for address in addresses { - addToMailaddresses(address) - } - } - if let childRecord = child.record { - //TODO: merge KeyRecords here - for mail in childRecord.mails { - childRecord.removeFromPersistentMails(mail) - record?.addToPersistentMails(mail) - } - //delete gratuitous keyrecord - child.record = nil - } - if child.currentlyActiveKey.lastSeen ?? Date.init() > currentlyActiveKey.lastSeen ?? Date.init() { - currentlyActiveKey = child.currentlyActiveKey - } - child.verifiedDate = verifiedDate - addChildKeys(child) - //TODO: do we have to set childs parent here too? - } - } - -} - -// MARK: Generated accessors for mailaddress -extension PersistentKey { - - public func addToMailaddresses(_ value: Mail_Address) { - rootKey.addToMailaddress(value) - } - - @objc(addMailaddressObject:) - @NSManaged private func addToMailaddress(_ value: Mail_Address) - - @objc(removeMailaddressObject:) - @NSManaged private func removeFromMailaddress(_ value: Mail_Address) - - @objc(addMailaddress:) - @NSManaged private func addToMailaddress(_ values: NSSet) - - @objc(removeMailaddress:) - @NSManaged private func removeFromMailaddress(_ values: NSSet) - -} - -// MARK: Generated accessors for mailaddress -extension PersistentKey { - @objc(addSignedMailsObject:) - @NSManaged public func addSignedMails(_ value: PersistentMail) - - @objc(removeSignedMailsObject:) - @NSManaged public func removeSignedMails(_ value: PersistentMail) - - @objc(addSignedMails:) - @NSManaged public func addSignedMails(_ values: NSSet) - - @objc(removeSignedMails:) - @NSManaged public func removeSignedMails(_ values: NSSet) - -} - -extension PersistentKey { - @objc(addChildKeysObject:) - @NSManaged private func addChildKeys(_ value: PersistentKey) - - @objc(removeChildKeysObject:) - @NSManaged private func removeChildKeys(_ value: PersistentKey) - - @objc(addChildKeys:) - @NSManaged private func addChildKeys(_ values: NSSet) - - @objc(removeChildKeys:) - @NSManaged private func removeChildKeys(_ values: NSSet) - -} - -extension PersistentKey { - @objc(addRepealedByMailsObject:) - @NSManaged public func addRepealedByMails(_ value: PersistentMail) - - @objc(removeRepealedByMailsObject:) - @NSManaged public func removeRepealedByMails(_ value: PersistentMail) - - @objc(addRepealedByMails:) - @NSManaged public func addRepealedByMails(_ values: NSSet) - - @objc(removeRepealedByMails:) - @NSManaged public func removeRepealedByMails(_ values: NSSet) - -} diff --git a/enzevalos_iphone/PersistentMail +CoreDataClass.swift b/enzevalos_iphone/PersistentMail +CoreDataClass.swift deleted file mode 100644 index 170ee700e10ca964d6bc7e9bd3ed7c5cfda89e54..0000000000000000000000000000000000000000 --- a/enzevalos_iphone/PersistentMail +CoreDataClass.swift +++ /dev/null @@ -1,233 +0,0 @@ -// -// PersistentMail+CoreDataClass.swift -// enzevalos_iphone -// -// Created by Oliver Wiese on 27/12/16. -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. -// This file was automatically generated and should not be edited. -// - - -import Foundation -import CoreData -/** -A PersistentMail stores all information about one mail: - - Sender, receivers - - subject, date - - body - - encryption state - - signature state - - attached files, keys - -*/ -@objc(PersistentMail) -open class PersistentMail: NSManagedObject, Mail { - public var predecessor: PersistentMail? = nil - - var showMessage: Bool = false - - var isSecure: Bool { - return isEncrypted && isSigned && isCorrectlySigned && !unableToDecrypt && !trouble && keyID != nil - } - var encState: EncryptionState { - get{ - if unableToDecrypt { - return EncryptionState.UnableToDecrypt - } - if !isEncrypted { - return EncryptionState.NoEncryption - } - else if self.decryptedWithOldPrivateKey { - return EncryptionState.ValidEncryptedWithOldKey - } - else { - return EncryptionState.ValidedEncryptedWithCurrentKey - } - } - } - - var sigState: SignatureState { - get{ - if isSigned && isCorrectlySigned { - return SignatureState.ValidSignature - } - else if isSigned && keyID == nil { - return SignatureState.NoPublicKey - } - else if isSigned { - return SignatureState.InvalidSignature - } - else { - return SignatureState.NoSignature - } - - } - } - - /** - This the signed first mail of the signed key? - */ - var isNewPubKey: Bool { - guard let signedKey = self.signedKey else { - return false - } - - if signedKey.counterSignedMails < 2 && self.from.publicKeys.count > 1 && signedKey.fingerprint != self.from.primaryKey?.fingerprint { - return true - } - return false - } - - /** - Just a flag if the user read this mail. - */ - var isRead: Bool { - get { - let value = flag.contains(MCOMessageFlag.seen) - return value - } - set { - if !newValue { - flag.remove(MCOMessageFlag.seen) - } else { - flag.insert(MCOMessageFlag.seen) - } - DataHandler.handler.save(during: "set read flag") - } - } - - /** - Just a flag if the user answered the mail. - */ - var isAnwered: Bool { - get { - let value = flag.contains(MCOMessageFlag.answered) - return value - } - set { - if !newValue { - flag.remove(MCOMessageFlag.answered) - } else { - flag.insert(MCOMessageFlag.answered) - } - DataHandler.handler.save(during: "set answer flag") - } - } - - var timeString: String { - var returnString = "" - let dateFormatter = DateFormatter() - dateFormatter.locale = Locale.current - let mailTime = self.date - let interval = Date().timeIntervalSince(mailTime as Date) - switch interval { - case -55..<55: - returnString = NSLocalizedString("Now", comment: "New email") - case 55..<120: - returnString = NSLocalizedString("OneMinuteAgo", comment: "Email came one minute ago") - case 120..<24 * 60 * 60: - dateFormatter.timeStyle = .short - returnString = dateFormatter.string(from: mailTime as Date) - case 86400..<172800: //24 * 60 * 60..<48 * 60 * 60: - returnString = NSLocalizedString("Yesterday", comment: "Email came yesterday") - case 172800..<259200: //48 * 60 * 60..<72 * 60 * 60: - returnString = NSLocalizedString("TwoDaysAgo", comment: "Email came two days ago") - default: - dateFormatter.dateStyle = .short - returnString = dateFormatter.string(from: mailTime as Date) - } - return returnString - } - - /** - Just a short part of the body. Can be used for a preview. - In case of trouble there is no preview. - */ - var shortBodyString: String? { - guard !trouble else { - return nil - } - - var message: String? = "" - if isEncrypted && !unableToDecrypt { - message = decryptedBody - } else { - message = body - } - - if message != nil { - message = message!.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) - if message!.count > 50 { - message = String(message![..<message!.index(message!.startIndex, offsetBy: 50)]) - } - let messageArray = message!.components(separatedBy: "\n") - return messageArray.joined(separator: " ") - } else { - return nil - } - } - - var decryptedWithOldPrivateKey: Bool = false - - func getReceivers() -> [Mail_Address] { - var receivers = [Mail_Address] () - for obj in to { - receivers.append(obj as! Mail_Address) - } - return receivers - } - - func getCCs() -> [Mail_Address] { - var receivers = [Mail_Address] () - for obj in cc! { - receivers.append(obj as! Mail_Address) - } - return receivers - } - - func getBCCs() -> [Mail_Address] { - var receivers = [Mail_Address] () - for obj in bcc! { - receivers.append(obj as! Mail_Address) - } - return receivers - } - - func getSubjectWithFlagsString() -> String { - let subj: String - var returnString: String = "" - - if self.subject == nil || (self.subject?.isEmpty)! { - subj = NSLocalizedString("SubjectNo", comment: "This email has no subject") - } else { - subj = subject! - } - if self.trouble { - returnString.append("❗️ ") - } - if !self.isRead { - returnString.append("🔵 ") - } - if MCOMessageFlag.answered.isSubset(of: flag) { - returnString.append("↩️ ") - } - if MCOMessageFlag.forwarded.isSubset(of: flag) { - returnString.append("➡️ ") - } - if MCOMessageFlag.flagged.isSubset(of: flag) { - returnString.append("⭐️ ") - } - return "\(returnString)\(subj)" - } -} diff --git a/enzevalos_iphone/PersistentMail +CoreDataProperties.swift b/enzevalos_iphone/PersistentMail +CoreDataProperties.swift deleted file mode 100644 index ff76cbf634242d0b149b86537095f310e27236b9..0000000000000000000000000000000000000000 --- a/enzevalos_iphone/PersistentMail +CoreDataProperties.swift +++ /dev/null @@ -1,491 +0,0 @@ -// -// PersistentMail+CoreDataProperties.swift -// enzevalos_iphone -// -// Created by Oliver Wiese on 04/01/17. -// Copyright © 2018 fu-berlin. -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. -// - -import Foundation -import CoreData - -extension PersistentMail { - - @nonobjc public class func fetchRequest() -> NSFetchRequest<PersistentMail> { - return NSFetchRequest(entityName: "PersistentMail"); - } - - @NSManaged public var body: String? - /** - Deprecated - */ - @NSManaged public var visibleBody: String? - @NSManaged public var decryptedBody: String? - @NSManaged public var encryptedBody: String? - @NSManaged public var date: Date - /** - secret key which is attacted to the mail (to import) - */ - @NSManaged public var secretKey: String? - /** - The corresponding key record - */ - @NSManaged public var record: KeyRecord? - - public var hasAttachment: Bool { - get { - if let at = attachments, at.count > 0 { - return true - } - return false - } - } - - /** - Some mail flags, e.g. read flag, answered flag (according to RFC) - */ - public var flag: MCOMessageFlag { - set { - if newValue != flag { - AppDelegate.getAppDelegate().mailHandler.setFlag(self.uid, flags: newValue, folder: folder.name) - self.willChangeValue(forKey: "flag") - self.setPrimitiveValue(newValue.rawValue, forKey: "flag") - self.didChangeValue(forKey: "flag") - - } - - } - get { - self.willAccessValue(forKey: "flag") - var value = MCOMessageFlag().rawValue - if let flagInt = self.primitiveValue(forKey: "flag") { - value = flagInt as! Int - } - let text = MCOMessageFlag(rawValue: value) - self.didAccessValue(forKey: "flag") - return text - } - - } - /** - 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 - */ - @NSManaged public var isSigned: Bool - /** - We could verify the signature (with a given public key) - */ - @NSManaged public var isCorrectlySigned: Bool - /** - This mail is encrypted but we could not decrypt the message (e.g. the secret key is missing) - */ - @NSManaged public var unableToDecrypt: Bool - /** - Subject of a mail (according to RFC) - */ - @NSManaged public var subject: String? - /** - Which folder is used to store the mail? - */ - @NSManaged public var folder: Folder - /** - Not used. - */ - @NSManaged public var firstKey: PersistentKey? - /** - What key is the signature key of this mail? - */ - @NSManaged public var signedKey: PersistentKey? - /** - Did we received the mail? - */ - @NSManaged public var received: Bool - /** - Only used in traveler scenario. - */ - @NSManaged public var deleteWhileTravel: Bool - /** - Only used in traveler scenario. - */ - @NSManaged public var storeEncrypted: Bool - /** - Only used in traveler scenario. - */ - @NSManaged public var repealsKey: PersistentKey? - - /** - This can be used for threading. This is defined in a RFC. - */ - @NSManaged public var gmailMessageID: NSNumber? - /** - This can be used for threading. This is defined in a RFC. - */ - @NSManaged public var gmailThreadID: NSNumber? - /** - Please read up this mail in the RFC! - */ - @NSManaged public var messageID: String? - /** - Currently not used. - */ - @NSManaged public var notLoadedMessages: String? - /** - Only for traveler scenario. - */ - @NSManaged public var decryptedKey: PersistentKey? - /** - Related secrect Key for mail. - */ - @NSManaged public var relatedSecrectKey: SecretKey? - /** - Sender mail client. - */ - @NSManaged public var xMailer: String? - - /** - Key id of the signature key. - TODO rename to signedKeyID - */ - public var keyID: String? { - set { - self.willChangeValue(forKey: "keyID") - self.setPrimitiveValue(newValue, forKey: "keyID") - self.didChangeValue(forKey: "keyID") - } - get { - var signKeyID: String? - if let k = self.signedKey { - signKeyID = k.keyID - } - self.willAccessValue(forKey: "keyID") - if let text = self.primitiveValue(forKey: "keyID") { - signKeyID = text as? String - } - else { - if let id = signKeyID { - self.setPrimitiveValue(id, forKey: "keyID") - } - } - self.didAccessValue(forKey: "keyID") - return signKeyID - } - } - - - /** - Does this mail has some (crypto) errors, e.g. manipulated encryption or signature? - */ - public var trouble: Bool { - set { - self.willChangeValue(forKey: "trouble") - self.setPrimitiveValue(newValue, forKey: "trouble") - self.didChangeValue(forKey: "trouble") - } - get { - self.willAccessValue(forKey: "trouble") - let text = self.primitiveValue(forKey: "trouble") as? Bool ?? true - self.didAccessValue(forKey: "trouble") - return text - } - - } - /** - Please read the RFC! - */ - public var uid: UInt64 { - set { - self.willChangeValue(forKey: "uid") - self.setPrimitiveValue(NSDecimalNumber.init(value: newValue as UInt64), forKey: "uid") - self.didChangeValue(forKey: "uid") - } - get { - self.willAccessValue(forKey: "uid") - let text = (self.primitiveValue(forKey: "uid") as? NSDecimalNumber)?.uint64Value - self.didAccessValue(forKey: "uid") - if let res = text { - return res - } - return 0 - } - } - /** - Please read the RFC! - */ - public var uidvalidity: UInt32? { - set { - if let num = newValue { - self.willChangeValue(forKey: "uidvalidity") - self.setPrimitiveValue(NSDecimalNumber.init(value: num as UInt32), forKey: "uidvalidity") - self.didChangeValue(forKey: "uidvalidity") - } - } - get { - self.willAccessValue(forKey: "uidvalidity") - let text = (self.primitiveValue(forKey: "uidvalidity") as? NSDecimalNumber)?.uint32Value - self.didAccessValue(forKey: "uidvalidity") - return text - } - } - public var from: MailAddress { - set { - if newValue is Mail_Address { - let adr = newValue as! Mail_Address - self.willChangeValue(forKey: "from") - self.setValue(adr, forKey: "from") - self.didChangeValue(forKey: "from") - } - } - get { - self.willAccessValue(forKey: "from") - let text = (self.primitiveValue(forKey: "from") as? Mail_Address) - self.didAccessValue(forKey: "from") - if let text = text { - return text - } - return Mail_Address() - } - } - public var containsSecretKey: Bool { - get { - return secretKey != nil - } - } - - private func extractPassword(body: String) -> String? { - var pw: String? = nil - var keyword: String? = nil - if body.contains("PW:") { - keyword = "PW:" - } - else if body.contains("pw:") { - keyword = "pw:" - } - else if body.contains("password:") { - keyword = "password:" - } - if let key = keyword { - if let range = (body.range(of: key)?.upperBound) { - pw = String(body[range...]) - if let split = pw?.components(separatedBy: CharacterSet.whitespacesAndNewlines) { - if split.count > 0 && split[0].count > 0 { - pw = split[0] - } - else if split.count > 1 { - pw = split[1] - } - } - } - } - return pw - - } - - /** - Enter a password and if possible import the secret keys. - */ - public func processSecretKey(pw: String?) throws -> Bool { - var sk = "" - if let key = secretKey { - sk = key.replacingOccurrences(of: "\r\n", with: "\n") - sk = sk.replacingOccurrences(of: "\n", with: "\r\n") - let pgp = SwiftPGP() - let keyIDs = try pgp.importKeys(key: sk, pw: pw, isSecretKey: true, autocrypt: false) - let sks = DataHandler.handler.newSecretKeys(keyIds: keyIDs, addPKs: true) - return sks.count > 0 - } - return false - } - - @NSManaged public var bcc: NSSet? - @NSManaged public var cc: NSSet? - @NSManaged public var to: NSSet - @NSManaged public var attachments: NSSet? - /** - Can be used for threading. Please read the RFC. - */ - @NSManaged public var referenceMails: NSSet? - -} - -// MARK: Generated accessors for bcc -extension PersistentMail { - - @objc(addBccObject:) - @NSManaged public func addToBcc(_ value: Mail_Address) - - @objc(removeBccObject:) - @NSManaged public func removeFromBcc(_ value: Mail_Address) - - @objc(addBcc:) - @NSManaged public func addToBcc(_ values: NSSet) - - @objc(removeBcc:) - @NSManaged public func removeFromBcc(_ values: NSSet) - -} - -// MARK: Generated accessors for cc -extension PersistentMail { - - @objc(addCcObject:) - @NSManaged public func addToCc(_ value: Mail_Address) - - @objc(removeCcObject:) - @NSManaged public func removeFromCc(_ value: Mail_Address) - - @objc(addCc:) - @NSManaged public func addToCc(_ values: NSSet) - - @objc(removeCc:) - @NSManaged public func removeFromCc(_ values: NSSet) - -} - -// MARK: Generated accessors for to -extension PersistentMail { - - @objc(addToObject:) - @NSManaged public func addToTo(_ value: Mail_Address) - - @objc(removeToObject:) - @NSManaged public func removeFromTo(_ value: Mail_Address) - - @objc(addTo:) - @NSManaged public func addToTo(_ values: NSSet) - - @objc(removeTo:) - @NSManaged public func removeFromTo(_ values: NSSet) - -} - -// MARK: Generated accessors for attachments -extension PersistentMail { - - @objc(addAttachmentsObject:) - @NSManaged public func addToAttachments(_ value: Attachment) - - @objc(removeAttachmentsObject:) - @NSManaged public func removeFromAttachments(_ value: Attachment) - - @objc(addAttachments:) - @NSManaged public func addToAttachments(_ values: NSSet) - - @objc(removeAttachments:) - @NSManaged public func removeFromAttachments(_ values: NSSet) - -} - -// MARK: Generated accessors for attachments -extension PersistentMail { - - @objc(addReferenceMailsObject:) - @NSManaged public func addToReferenceMails(_ value: PersistentMail) - - @objc(removeReferenceMailsObject:) - @NSManaged public func removeFromReferenceMails(_ value: PersistentMail) - - @objc(addReferenceMails:) - @NSManaged public func addToReferenceMails(_ values: NSSet) - - @objc(removeReferenceMails:) - @NSManaged public func removeFromReferenceMails(_ values: NSSet) - -} - - -extension PersistentMail: DisplayMail { - typealias C = Mail_Address - - var sender: C { - return self.from as! PersistentMail.C - } - - var tos: [C] { - return self.getReceivers() - } - - var ccs: [C] { - return self.getCCs()// TODO - } - - var bccs: [C] { - return self.getBCCs() - } - - var routingStops: [Landmark] { - return [] // TODO - } - - var signedState: SignatureState { - return self.sigState - } - - var persistentMail: PersistentMail? { - return self - } - - var displayAttachments: [DisplayAttachment] { - var attachments = [DisplayAttachment]() - if let coreDataAttachment = self.attachments { - for att in coreDataAttachment { - if let att = att as? Attachment { - attachments.append(att) - } - } - } - return attachments - } - - var folderType: FolderType { - return .Other // TODO FIX - } - - func markAsRead(isRead: Bool) { - self.isRead = isRead - } - - var transportEnc: Bool { - get { - return true - } - } -} - -extension Attachment: DisplayAttachment { - var myName: String { - return name ?? "No name" - } - - var myData: Data { - return data ?? Data() - } - - -} - diff --git a/enzevalos_iphone/ReadVENDelegate.swift b/enzevalos_iphone/ReadVENDelegate.swift index 66e6f8676c918495ae293edb0acf1980b70daa23..adeb105755ce4f6b1fb219ec86a21738f7304d13 100644 --- a/enzevalos_iphone/ReadVENDelegate.swift +++ b/enzevalos_iphone/ReadVENDelegate.swift @@ -81,11 +81,12 @@ extension ReadVENDelegate: VENTokenFieldDelegate { } func tokenField(_ tokenField: VENTokenField, colorSchemeForTokenAt index: UInt) -> UIColor { + /* TODO if let adr = DataHandler.handler.findMailAddress(adr: tokenField.mailTokens[Int(index)] as! String){ if adr.hasKey { return UIColor.init(red: 0, green: 122.0 / 255.0, blue: 1, alpha: 1) } - } + } */ return UIColor.orange } diff --git a/enzevalos_iphone/ReadViewController.swift b/enzevalos_iphone/ReadViewController.swift index df4d1a4363d2b0703c13de1b8004c5a09bafa4ac..d0918448353c26df56985bd86b3bc20f514665a6 100644 --- a/enzevalos_iphone/ReadViewController.swift +++ b/enzevalos_iphone/ReadViewController.swift @@ -50,7 +50,7 @@ class ReadViewController: UITableViewController { var VENDelegate: ReadVENDelegate? var textDelegate: ReadTextDelegate? - var mail: PersistentMail? = nil + var mail: MailRecord? = nil var isDraft = false var isInSentFolder = false @@ -62,28 +62,30 @@ class ReadViewController: UITableViewController { var infoState = LogData.WarningType.none - + /* var deletedWhileTravel: Bool { guard let mail = mail else { return false } return mail.isSecure && mail.deleteWhileTravel && TravelHandler.instance().mode != .atHome } - + */ + + override func viewDidLoad() { super.viewDidLoad() self.tableView.rowHeight = UITableView.automaticDimension self.tableView.estimatedRowHeight = 44.0 - if let folder = mail?.folder { - if folder.path.hasPrefix(UserManager.backendDraftFolderPath) { + if let folder = mail?.inFolder, let path = folder.path { + if path.hasPrefix(UserManager.backendDraftFolderPath) { isDraft = true - } else if folder.path.hasPrefix(UserManager.backendSentFolderPath) { + } else if path.hasPrefix(UserManager.backendSentFolderPath) { isInSentFolder = true - } else if folder.path.hasPrefix(UserManager.backendArchiveFolderPath) { + } else if path.hasPrefix(UserManager.backendArchiveFolderPath) { isInArchiveFolder = true - } else if folder.path.hasPrefix(UserManager.backendTrashFolderPath) { + } else if path.hasPrefix(UserManager.backendTrashFolderPath) { isTrash = true } } @@ -97,20 +99,20 @@ class ReadViewController: UITableViewController { if isDraft || isInArchiveFolder || isTrash { archiveButton.isEnabled = false } - + /* TODO if Logger.logging, let mail = self.mail { var message = "none" if showInfoSection(mail: mail) { - if mail.trouble { + if mail.signedState == .InvalidSignature { message = "corrupted" - } else if mail.isEncrypted && mail.unableToDecrypt { + } else if mail.encryptionState == .UnableToDecrypt { message = "couldNotDecrypt" - } else if mail.from.hasKey && !mail.isSecure { + } else if mail.fromAddress?.usedPublicKeys?.count ?? 0 > 0 && !mail.signedState == .none { message = "encryptedBefore" } } Logger.log(readViewOpen: mail, message: message, draft: isDraft) - } + } */ VENDelegate = ReadVENDelegate(tappedWhenSelectedFunc: { [weak self] in self?.showContact($0) }, tableView: tableView) @@ -134,22 +136,23 @@ class ReadViewController: UITableViewController { reactButton.setTitle(NSLocalizedString("reactButton", comment: "Title of the reaction Button"), for: .normal) setUItoMail() - - if let mail = mail, mail.folder.uidvalidity != mail.uidvalidity || !mail.received { + /* TODO + if let mail = mail, mail.inFolder?.uidValidity != mail.uidvalidity || !mail.received { deleteButton.isEnabled = false } + */ textDelegate = ReadTextDelegate() textDelegate?.callback = { [weak self] (address: String) in self?.newMailCallback(Address: address) } messageBody.delegate = textDelegate - self.keyDiscoveryDate = mail?.from.contact?.firstSecureMailReceived + // TODO self.keyDiscoveryDate = mail?.from.contact?.firstSecureMailReceived } deinit { print("===============|| ReadViewController deinitialized ||===============") - +/* TODO FIX LOGGER if Logger.logging, let mail = self.mail { var message = "none" if mail.trouble && mail.showMessage || !mail.trouble && !mail.isSecure && mail.from.contact!.hasKey && mail.date > self.keyDiscoveryDate ?? Date() || !mail.trouble && mail.isEncrypted && mail.unableToDecrypt, !StudySettings.hideWarning { @@ -162,7 +165,7 @@ class ReadViewController: UITableViewController { } } Logger.log(readViewClose: message, draft: isDraft) - } + } */ } override func viewWillDisappear(_ animated: Bool){ @@ -174,9 +177,7 @@ class ReadViewController: UITableViewController { if let mail = mail { if mail.trouble { self.navigationController?.navigationBar.barTintColor = ThemeManager.troubleMessageColor() - if !mail.showMessage { - answerButton.isEnabled = false - } + answerButton.isEnabled = false } else if mail.isSecure { self.navigationController?.navigationBar.barTintColor = ThemeManager.encryptedMessageColor() } else { @@ -194,30 +195,35 @@ class ReadViewController: UITableViewController { } func showContact(_ email: String) { - let records = DataHandler.handler.getContactByAddress(email).records - for r in records { - for address in r.addresses { - if address.mailAddress == email && address.hasKey == r.hasKey { - performSegue(withIdentifier: "showContact", sender: ["record": r, "email": email]) - return + // TODO DAS THIS WORK? + if let records = PersitentDataProvider.dataProvider.generateFetchedAddressResultsController(address: email).fetchedObjects?.first?.usedPublicKeys?.allObjects as? [PublicKeyRecord] { + for r in records { + if let addresses = r.usedAddress?.allObjects as? [AddressRecord] { + for address in addresses { + if let addr = address.email, addr == email && address.hasPublicKey { + performSegue(withIdentifier: "showContact", sender: ["record": r, "email": email]) + return + } + } + for address in addresses { + if let addr = address.email, addr == email { + performSegue(withIdentifier: "showContact", sender: ["record": r, "email": email]) + return + } + } } - } - for address in r.addresses { - if address.mailAddress == email { - performSegue(withIdentifier: "showContact", sender: ["record": r, "email": email]) - return } - } + } } /// Bool indicating whether a info section is shown with the exception of trouble mails where the message is not shown (because we need only 2 sections in that case) - func showInfoSection(mail: PersistentMail) -> Bool { - return (mail.trouble && mail.showMessage) || (!mail.trouble && !mail.isSecure && mail.from.hasKey && mail.date > keyDiscoveryDate ?? Date() && !isDraft && !isInSentFolder) || (!mail.trouble && mail.isEncrypted && mail.unableToDecrypt) || mail.isNewPubKey && !StudySettings.hideWarning || deletedWhileTravel + func showInfoSection(mail: MailRecord) -> Bool { + return true // (mail.trouble && mail.showMessage) || (!mail.trouble && !mail.isSecure && mail.from.hasKey && mail.date > keyDiscoveryDate ?? Date() && !isDraft && !isInSentFolder) || (!mail.trouble && mail.isEncrypted && mail.unableToDecrypt) || mail.isNewPubKey && !StudySettings.hideWarning || deletedWhileTravel } - func showInfoButton(mail: PersistentMail) -> Bool { - return (mail.trouble && !mail.showMessage || mail.from.hasKey && !mail.isSecure && mail.date > keyDiscoveryDate ?? Date() && !mail.showMessage && !isDraft && !isInSentFolder) && !StudySettings.hideWarning && !mail.unableToDecrypt || deletedWhileTravel || mail.unableToDecrypt && mail.isEncrypted && TravelHandler.instance().mode != .atHome + func showInfoButton(mail: MailRecord) -> Bool { + return true //(mail.trouble && !mail.showMessage || mail.from.hasKey && !mail.isSecure && mail.date > keyDiscoveryDate ?? Date() && !mail.showMessage && !isDraft && !isInSentFolder) && !StudySettings.hideWarning && !mail.unableToDecrypt || deletedWhileTravel || mail.unableToDecrypt && mail.isEncrypted && TravelHandler.instance().mode != .atHome } // set top seperator height @@ -239,7 +245,7 @@ class ReadViewController: UITableViewController { } override func numberOfSections(in tableView: UITableView) -> Int { - if let mail = mail, showInfoSection(mail: mail) && !deletedWhileTravel { + if let mail = mail, showInfoSection(mail: mail) { return 3 } return 2 @@ -275,25 +281,18 @@ class ReadViewController: UITableViewController { } else if indexPath.row == 1 { if mail.trouble { // Show info reaction cell with one button return infoButtonCell - } else if deletedWhileTravel { - reactButton.setTitle(NSLocalizedString("LoadBackup", comment: "load the backup, if the traveler is at home again"), for: .normal) - return infoReactButtonCell - } else if mail.unableToDecrypt && mail.isEncrypted && TravelHandler.instance().mode != .atHome { - reactButton.setTitle(NSLocalizedString("LoadBackup", comment: "load the backup, if the traveler is at home again"), for: .normal) - return infoReactButtonCell - } else if mail.from.hasKey && !mail.isSecure && mail.date > (keyDiscoveryDate ?? Date()) && !isDraft { // Show info reaction cell with two buttons + } else if mail.fromAddress?.hasPublicKey ?? false && !mail.isSecure && mail.date ?? Date() > (keyDiscoveryDate ?? Date()) && !isDraft { // Show info reaction cell with two buttons return infoReactButtonCell } } } - return messageCell } @IBAction func showEmailButton(_ sender: UIButton) { - Logger.log(showBroken: self.mail) + // TODO FIX Logger.log(showBroken: self.mail) - mail?.showMessage = true + // mail?.showMessage = true self.tableView.beginUpdates() let path = IndexPath(row: 1, section: 1) @@ -309,29 +308,28 @@ class ReadViewController: UITableViewController { } @IBAction func reactButton(_ sender: Any) { - if deletedWhileTravel || (mail?.unableToDecrypt ?? false) && (mail?.isEncrypted ?? false) && TravelHandler.instance().mode != .atHome { + /* if (mail?.unableToDecrypt ?? false) && (mail?.isEncrypted ?? false) && TravelHandler.instance().mode != .atHome { UIView.animate(withDuration: 0.3, animations: { self.navigationController?.navigationBar.barTintColor = ThemeManager.defaultColor }) navigationController?.pushViewController(TravelHandler.instance().loadBackupUI(), animated: true) - } else { + } else { */ performSegue(withIdentifier: "answerTo", sender: "reactButton") - } - Logger.log(reactTo: mail) - Logger.log(reactWarning: infoState, reaction: .clickButton) + // TODO Logger.log(reactTo: mail) + // TODO Logger.log(reactWarning: infoState, reaction: .clickButton) } @IBAction func markUnreadButton(_ sender: AnyObject) { - mail?.isRead = false + // TODO mail?.isRead = false navigationController?.popViewController(animated: true) } @IBAction func deleteButton(_ sender: AnyObject) { if let mail = mail { if isTrash { - Logger.log(delete: mail, toTrash: false) - AppDelegate.getAppDelegate().mailHandler.setFlag(mail.uid, flags: MCOMessageFlag.deleted, folder: mail.folder.path) + // TODO Logger.log(delete: mail, toTrash: false) + // TODO AppDelegate.getAppDelegate().mailHandler.setFlag(mail.uid, flags: MCOMessageFlag.deleted, folder: mail.folder.path) } else { - Logger.log(delete: mail, toTrash: true) - AppDelegate.getAppDelegate().mailHandler.move(mails: [mail], from: mail.folder.path, to: UserManager.backendTrashFolderPath) + // TODO Logger.log(delete: mail, toTrash: true) + AppDelegate.getAppDelegate().mailHandler.move(mails: [mail], from: mail.inFolder?.path ?? MailHandler.INBOX, to: UserManager.backendTrashFolderPath) } } navigationController?.popViewController(animated: true) @@ -339,8 +337,8 @@ class ReadViewController: UITableViewController { @IBAction func archiveButton(_ sender: AnyObject) { if let mail = mail { - Logger.log(archive: mail) - AppDelegate.getAppDelegate().mailHandler.move(mails: [mail], from: mail.folder.path, to: UserManager.backendArchiveFolderPath) + // TODO Logger.log(archive: mail) + // TODO AppDelegate.getAppDelegate().mailHandler.move(mails: [mail], from: mail.folder.path, to: UserManager.backendArchiveFolderPath) } navigationController?.popViewController(animated: true) } @@ -361,19 +359,19 @@ class ReadViewController: UITableViewController { state = .Secure alert.addAction(UIAlertAction(title: NSLocalizedString("ReadMailOnOtherDevice", comment: "email is not readable on other devices"), style: .default, handler: { (action: UIAlertAction!) -> Void in let duration = Date().timeIntervalSince(opening) - Logger.log(close: icon, mail: m, action: .exportKey, duration: duration) + // TODO Logger.log(close: icon, mail: m, action: .exportKey, duration: duration) self.performSegue(withIdentifier: "exportKeyFromReadView", sender: nil) })) - } else if m.isCorrectlySigned { + } else if m.signedState == .ValidSignature { alert = UIAlertController(title: NSLocalizedString("Postcard", comment: "postcard label"), message: NSLocalizedString("ReceiveInsecureInfoVerified", comment: "Postcard infotext"), preferredStyle: .alert) icon = .signedOnly state = .OnlySigned - } else if m.isEncrypted && !m.unableToDecrypt { + } else if m.encryptionState == .ValidEncryptedWithOldKey || m.encryptionState == .ValidedEncryptedWithCurrentKey { //TODO: maybe add travel hook here icon = .encryptedOnly alert = UIAlertController(title: NSLocalizedString("Postcard", comment: "postcard label"), message: NSLocalizedString("ReceiveInsecureInfoEncrypted", comment: "Postcard infotext"), preferredStyle: .alert) state = .OnlyEncrypted - } else if m.isEncrypted && m.unableToDecrypt { + } else if m.encryptionState == .UnableToDecrypt { //TODO: add travel hook here icon = .unableToDecrypt alert = UIAlertController(title: NSLocalizedString("Postcard", comment: "postcard label"), message: NSLocalizedString("ReceiveInsecureInfoDecryptionFailed", comment: "Postcard infotext"), preferredStyle: .alert) @@ -383,10 +381,10 @@ class ReadViewController: UITableViewController { alert = UIAlertController(title: NSLocalizedString("Postcard", comment: "postcard label"), message: NSLocalizedString("ReceiveInsecureInfo", comment: "Postcard infotext"), preferredStyle: .alert) state = .Insecure } - Logger.log(open: state.generalInfo, mail: m) + // TODO Logger.log(open: state.generalInfo, mail: m) alert.addAction(UIAlertAction(title: NSLocalizedString("MoreInformation", comment: "More Information label"), style: .default, handler: { (action: UIAlertAction!) -> Void in let duration = Date().timeIntervalSince(opening) - Logger.log(close: icon, mail: m, action: .moreInfo, duration: duration) + // TODO Logger.log(close: icon, mail: m, action: .moreInfo, duration: duration) _ = MoreInformationViewController.pushInfoView(navigationController: self.navigationController, state: state) })) @@ -396,7 +394,7 @@ class ReadViewController: UITableViewController { })) alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: { (action: UIAlertAction!) -> Void in let duration = Date().timeIntervalSince(opening) - Logger.log(close: icon, mail: m, action: .close, duration: duration) + // TODO Logger.log(close: icon, mail: m, action: .close, duration: duration) })) DispatchQueue.main.async(execute: { self.present(alert, animated: true, completion: nil) @@ -406,7 +404,7 @@ class ReadViewController: UITableViewController { func setUItoMail() { if let mail = mail { - if mail.containsSecretKey { + if mail.attachedSecretKey?.count ?? 0 > 0 { importSecretKeyDialog(first: true) } @@ -416,39 +414,38 @@ class ReadViewController: UITableViewController { if let viewControllers = self.navigationController?.viewControllers { for viewController in viewControllers { if viewController.isKind(of: ReadViewController.self) { - mail.isRead = true + // TODO mail.isRead = true } } } } - if let name = mail.from.contact?.nameOptional { - senderTokenField.delegate?.tokenField!(senderTokenField, didEnterText: name, mail: mail.from.mailAddress) - } else { - senderTokenField.delegate?.tokenField!(senderTokenField, didEnterText: mail.from.mailAddress, mail: mail.from.mailAddress) + if let name = mail.fromAddress?.name, let addr = mail.fromAddress?.email { + senderTokenField.delegate?.tokenField!(senderTokenField, didEnterText: name, mail: addr) + } else if let addr = mail.fromAddress?.email { + senderTokenField.delegate?.tokenField!(senderTokenField, didEnterText: addr, mail: addr) } - - for receiver in mail.getReceivers() { - if let displayname = receiver.contact?.nameOptional { - toTokenField.delegate?.tokenField!(toTokenField, didEnterText: displayname, mail: receiver.address) - } else { - toTokenField.delegate?.tokenField!(toTokenField, didEnterText: receiver.address, mail: receiver.address) + for receiver in mail.tos { + if let name = mail.fromAddress?.name, let addr = mail.fromAddress?.email { + toTokenField.delegate?.tokenField!(toTokenField, didEnterText: name, mail: addr) + } else if let addr = mail.fromAddress?.email { + toTokenField.delegate?.tokenField!(toTokenField, didEnterText: addr, mail: addr) } } - for receiver in mail.getCCs() { - if let displayname = receiver.contact?.nameOptional { - toTokenField.delegate?.tokenField!(toTokenField, didEnterText: displayname, mail: receiver.address) - } else { - toTokenField.delegate?.tokenField!(toTokenField, didEnterText: receiver.address, mail: receiver.address) + for receiver in mail.ccs { + if let name = mail.fromAddress?.name, let addr = mail.fromAddress?.email { + toTokenField.delegate?.tokenField!(toTokenField, didEnterText: name, mail: addr) + } else if let addr = mail.fromAddress?.email { + toTokenField.delegate?.tokenField!(toTokenField, didEnterText: addr, mail: addr) } } - for receiver in mail.getBCCs() { - if let displayname = receiver.contact?.nameOptional { - toTokenField.delegate?.tokenField!(toTokenField, didEnterText: displayname, mail: receiver.address) - } else { - toTokenField.delegate?.tokenField!(toTokenField, didEnterText: receiver.address, mail: receiver.address) + for receiver in mail.bccs { + if let name = mail.fromAddress?.name, let addr = mail.fromAddress?.email { + toTokenField.delegate?.tokenField!(toTokenField, didEnterText: name, mail: addr) + } else if let addr = mail.fromAddress?.email { + toTokenField.delegate?.tokenField!(toTokenField, didEnterText: addr, mail: addr) } } @@ -460,7 +457,7 @@ class ReadViewController: UITableViewController { toTokenField.collapse() } - receivedTime.text = mail.timeString + receivedTime.text = mail.date?.dateToString ?? Date().dateToString if let subj = mail.subject { if subj.trimmingCharacters(in: CharacterSet.whitespaces).count > 0 { @@ -470,19 +467,15 @@ class ReadViewController: UITableViewController { } } - if mail.isEncrypted && !mail.unableToDecrypt { - messageBody.text = mail.decryptedBody - } else { - messageBody.text = mail.body - } + messageBody.text = mail.body messageBody.text = messageBody.text?.trimmingCharacters(in: NSCharacterSet.whitespacesAndNewlines).appending("\n") // NavigationBar Icon var icon: UIImage if mail.trouble { icon = StudySettings.securityIndicator.imageOfCorruptedIndicator() - } else if deletedWhileTravel { - icon = IconsStyleKit.imageOfLetter + //} else if deletedWhileTravel { + // icon = IconsStyleKit.imageOfLetter } else if mail.isSecure { icon = StudySettings.securityIndicator.imageOfSecureIndicator(open: true) } else { @@ -508,7 +501,7 @@ class ReadViewController: UITableViewController { infoCell.setNeedsLayout() infoCell.layoutIfNeeded() infoCell.translatesAutoresizingMaskIntoConstraints = true - } else if mail.isEncrypted && mail.unableToDecrypt { + } else if mail.encryptionState == .UnableToDecrypt { if TravelHandler.instance().mode != .atHome { infoState = .unableToDecryptTravel infoSymbol.text = "?" @@ -526,14 +519,14 @@ class ReadViewController: UITableViewController { infoText.text = NSLocalizedString("couldNotDecryptText", comment: "Message could not be decrypted") } - } else if (mail.isNewPubKey) && !deletedWhileTravel { + } else if false { // TODO (mail.isNewPubKey) { //&& !deletedWhileTravel { infoState = .newKey infoSymbol.text = "!" infoSymbol.textColor = ThemeManager.orange infoHeadline.text = NSLocalizedString("newKeyHeadline", comment: "Message contained a new public key") infoHeadline.textColor = UIColor.gray infoText.text = NSLocalizedString("newKeyText", comment: "Message contained a new public key") - } else if mail.from.hasKey && !mail.isSecure { + } else if mail.fromAddress?.hasPublicKey ?? false && !mail.isSecure { //TODO: add travel hook here infoState = .notConfidential infoSymbol.text = "?" @@ -541,13 +534,14 @@ class ReadViewController: UITableViewController { infoHeadline.text = NSLocalizedString("encryptedBeforeHeadline", comment: "The sender has encrypted before") infoHeadline.textColor = UIColor.gray infoText.text = NSLocalizedString("encryptedBeforeText", comment: "The sender has encrypted before") - } else if deletedWhileTravel { + /*} else if deletedWhileTravel { infoState = .deletedWhileTravel infoSymbol.text = "!" infoSymbol.textColor = ThemeManager.green infoHeadline.text = NSLocalizedString("unreadableWhileTravelHeadline", comment: "The mail is not readable while traveling") infoHeadline.textColor = UIColor.gray infoText.text = NSLocalizedString("unreadableWhileTravelText", comment: "The mail is not readable while traveling") + */ } if infoState != .none { Logger.log(warning: infoState) @@ -561,12 +555,12 @@ class ReadViewController: UITableViewController { if let controller = navigationController?.topViewController as? SendViewController, let mail = mail { controller.sendViewDelegate = self if isDraft { - let prefillMail = EphemeralMail.init(to: mail.to, cc: mail.cc ?? NSSet.init(), bcc: mail.bcc ?? NSSet.init(), subject: mail.subject, body: mail.body, uid: mail.uid, predecessor: mail.predecessor) - controller.prefilledMail = prefillMail + // TODO FIX let prefillMail = EphemeralMail.init(to: mail.to, cc: mail.cc ?? NSSet.init(), bcc: mail.bcc ?? NSSet.init(), subject: mail.subject, body: mail.body, uid: mail.uid, predecessor: mail.predecessor) + // controller.prefilledMail = prefillMail return } let askForConfirmation = (sender as? String ?? "noReaction") == "reactButton" - +/* var answerTo = [mail.from] var answerCC = [Mail_Address]() var body = NSLocalizedString("mail from", comment: "describing who send the mail") + " " @@ -621,6 +615,7 @@ class ReadViewController: UITableViewController { let answerMail = EphemeralMail(to: NSSet.init(array: answerTo), cc: NSSet.init(array: answerCC), bcc: [], date: mail.date, subject: subject, body: body, uid: mail.uid, predecessor: mail) controller.prefilledMail = answerMail + */ } } else if segue.identifier == "answerTo" { // New Mail from data detector action let navigationController = segue.destination as? UINavigationController @@ -636,7 +631,7 @@ class ReadViewController: UITableViewController { } else if segue.identifier == "showContact" { let destinationVC = segue.destination as! ContactViewController if let sender = sender as? [String: AnyObject?] { - destinationVC.keyRecord = (sender["record"] as! KeyRecord) + // TODO destinationVC.keyRecord = (sender["record"] as! KeyRecord) destinationVC.highlightEmail = (sender["email"] as! String) } } @@ -654,7 +649,8 @@ class ReadViewController: UITableViewController { } func importSecretKey(alertAction: UIAlertAction!) { - Logger.log(importPrivateKeyPopupClose: mail, doImport: true) + // TODO Logger.log(importPrivateKeyPopupClose: mail, doImport: true) + /* TODO if (alertAction) != nil { if let pw = secretKeyPasswordField?.text { do { @@ -666,17 +662,18 @@ class ReadViewController: UITableViewController { } } } + */ } private func importSecretKeyDialog(first: Bool) { - Logger.log(importPrivateKeyPopupOpen: mail) - var message = String(format: NSLocalizedString("Read.Import.Secret.Body.PW", comment: "NewSecretKeyMessage"), mail?.secretKey ?? "") + // TODO Logger.log(importPrivateKeyPopupOpen: mail) + var message = String(format: NSLocalizedString("Read.Import.Secret.Body.PW", comment: "NewSecretKeyMessage"), "")// TODO mail?.secretKey ?? "") if !first { message = NSLocalizedString("Read.Import.Secret.Body.Wrong", comment: "NewSecretKeyMessage") } let alert = UIAlertController(title: NSLocalizedString("Read.Import.Secret.Title", comment: "NewSecretKeyTitle"), message: message, preferredStyle: UIAlertController.Style.alert) alert.addAction(UIAlertAction(title: NSLocalizedString("Read.Import.Secret.No", comment: "NoSecretKeyImport"), style: UIAlertAction.Style.destructive, handler: { (_: UIAlertAction) -> Void in - Logger.log(importPrivateKeyPopupClose: self.mail, doImport: false) + // TODO Logger.log(importPrivateKeyPopupClose: self.mail, doImport: false) })) alert.addAction(UIAlertAction(title: NSLocalizedString("Read.Import.Secret.Ok", comment: "Import secret Key"), style: UIAlertAction.Style.default, handler: importSecretKey)) @@ -698,7 +695,7 @@ extension ReadViewController: SendViewDelegate { reactButton.isEnabled = false if isDraft { if let mail = mail { - AppDelegate.getAppDelegate().mailHandler.setFlag(mail.uid, flags: MCOMessageFlag.deleted, folder: mail.folder.path) + // TODO AppDelegate.getAppDelegate().mailHandler.setFlag(mail.uid, flags: MCOMessageFlag.deleted, folder: mail.folder.path) } self.navigationController?.viewControllers.removeLast() } diff --git a/enzevalos_iphone/Record.swift b/enzevalos_iphone/Record.swift index 5175776c0bf6e1f08d98f846c1466ff0084c3af2..cf01697fea26152b34b7c571326f55ce558efec1 100644 --- a/enzevalos_iphone/Record.swift +++ b/enzevalos_iphone/Record.swift @@ -28,8 +28,8 @@ public protocol Record: Comparable { var name: String { get } var hasKey: Bool { get } var isVerified: Bool { get } - var ezContact: EnzevalosContact { get } - var mails: [PersistentMail] { get } + var ezContact: AddressRecord { get } + var mails: [MailRecord] { get } var cnContact: CNContact? { get } var color: UIColor { get } var image: UIImage { get } diff --git a/enzevalos_iphone/SecretKey+CoreDataClass.swift b/enzevalos_iphone/SecretKey+CoreDataClass.swift deleted file mode 100644 index f420d7f57e7899ef09aa018af97fa81720236258..0000000000000000000000000000000000000000 --- a/enzevalos_iphone/SecretKey+CoreDataClass.swift +++ /dev/null @@ -1,16 +0,0 @@ -// -// SecretKey+CoreDataClass.swift -// enzevalos_iphone -// -// Created by Oliver Wiese on 02.10.19. -// Copyright © 2019 fu-berlin. All rights reserved. -// -// - -import Foundation -import CoreData - -@objc(SecretKey) -public class SecretKey: NSManagedObject { - -} diff --git a/enzevalos_iphone/SecretKey+CoreDataProperties.swift b/enzevalos_iphone/SecretKey+CoreDataProperties.swift deleted file mode 100644 index 9c3470fad3931cbd50fc232aec613e3d2ec1e7c4..0000000000000000000000000000000000000000 --- a/enzevalos_iphone/SecretKey+CoreDataProperties.swift +++ /dev/null @@ -1,69 +0,0 @@ -// -// SecretKey+CoreDataProperties.swift -// enzevalos_iphone -// -// Created by Oliver Wiese on 02.10.19. -// Copyright © 2019 fu-berlin. All rights reserved. -// -// - -import Foundation -import CoreData - -/** - - */ -extension SecretKey { - - @nonobjc public class func fetchRequest() -> NSFetchRequest<SecretKey> { - return NSFetchRequest<SecretKey>(entityName: "SecretKey") - } - - /** - Did we exported the secretkey? - */ - @NSManaged public var exported: Bool - /** - When did we import the secretkey? - */ - @NSManaged public var importedDate: NSDate? - @NSManaged public var keyID: String - /** - Used in the travler scenario. Just ignore it. - */ - @NSManaged public var obsolete: Bool - /** - Not used yet. Should store how we imported the key (generated on device, imported from mail via autorcrypt, via iTunes, ...) - */ - @NSManaged public var origin: Int16 - /** - Just added in case of multiple accounts. - */ - @NSManaged public var account: Account? - /** - 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? - -} - -// MARK: Generated accessors for decryptedMails -extension SecretKey { - - @objc(addDecryptedMailsObject:) - @NSManaged public func addToDecryptedMails(_ value: PersistentMail) - - @objc(removeDecryptedMailsObject:) - @NSManaged public func removeFromDecryptedMails(_ value: PersistentMail) - - @objc(addDecryptedMails:) - @NSManaged public func addToDecryptedMails(_ values: NSSet) - - @objc(removeDecryptedMails:) - @NSManaged public func removeFromDecryptedMails(_ values: NSSet) - -} diff --git a/enzevalos_iphone/SecretKeyTableViewController.swift b/enzevalos_iphone/SecretKeyTableViewController.swift index 89b89433503ad179a0c15fc1c89867da83e4d091..d4a9541084a8bb19160a3a1a356595fff93f61ae 100644 --- a/enzevalos_iphone/SecretKeyTableViewController.swift +++ b/enzevalos_iphone/SecretKeyTableViewController.swift @@ -15,7 +15,7 @@ class SecretKeyTableViewController: UITableViewController { private var prefKeyID: String? { get { - return DataHandler.handler.prefSecretKey()?.keyID + return nil //TODO DataHandler.handler.prefSecretKey()?.keyID } } var currentPrefKeyRow = IndexPath() @@ -31,7 +31,7 @@ class SecretKeyTableViewController: UITableViewController { } override func viewDidLoad() { - keys = DataHandler.handler.findSecretKeys() + keys = [SecretKeyRecord]()//DataHandler.handler.findSecretKeys() keys.append(contentsOf: ItunesKeyHandling.iTunesKeyHandler.extractSecretKeys(withKnownKeys: false)) self.title = NSLocalizedString("SecretKeyTable.title", comment: "Title of secret key table") let feedbackButton = UIBarButtonItem(title: FeedbackButtonHelper.Name, style: .plain, target: self, action:#selector(feedback)) @@ -102,7 +102,7 @@ class SecretKeyTableViewController: UITableViewController { private func changePrefKey(tableView: UITableView, indexPath: IndexPath) { if let newPrefKey = keys[indexPath.row].save() { - DataHandler.handler.changePrefKey(newPrefKey: newPrefKey) + //TODO DataHandler.handler.changePrefKey(newPrefKey: newPrefKey) } var reloadCells = [IndexPath]() if let oldPrefCell = tableView.cellForRow(at: currentPrefKeyRow) as? KeyCell { diff --git a/enzevalos_iphone/SwiftUI/Data/DisplayProtocols.swift b/enzevalos_iphone/SwiftUI/Data/DisplayProtocols.swift index c9a84587639791ed82b1f5929490f0255c100621..9e87a13fa2eb99d1cdc0fc0149f133cee3528150 100644 --- a/enzevalos_iphone/SwiftUI/Data/DisplayProtocols.swift +++ b/enzevalos_iphone/SwiftUI/Data/DisplayProtocols.swift @@ -73,13 +73,14 @@ protocol DisplayContact { var hasSimilarContacts: Bool { get } var similarContacts: [String] { get } - var keyRecord: KeyRecord? { get } + // TODO var keyRecord: KeyRecord? { get } } extension DisplayContact { func findAddress(temp: Bool) -> MailAddress { - return DataHandler.handler.getMailAddress(addr, temporary: temp) + // TODO return DataHandler.handler.getMailAddress(addr, temporary: temp) + return PersitentDataProvider.dataProvider.fetchedAddressResultController.fetchedObjects?.first as! AddressRecord } } @@ -87,6 +88,7 @@ protocol DisplayMail { associatedtype C: DisplayContact var subject: String? { get } + var subjectWithFlag: String? { get } var sender: C { get } var tos: [C] { get } var ccs: [C] { get } @@ -106,7 +108,7 @@ protocol DisplayMail { var encState: EncryptionState { get } var transportEnc: Bool { get } - var persistentMail: PersistentMail? { get } + var persistentMail: MailRecord? { get } func markAsRead(isRead: Bool) } @@ -328,6 +330,19 @@ extension DisplayMail { } + var trouble: Bool { //TODO: What are troubles? Have we more cases? Can we remove this attribute? + get { + return signedState == .InvalidSignature || encState == .UnableToDecrypt + + } + } + //TODO: What is a secure mail? Have we more cases? Can we remove this attribute? + var isSecure: Bool { + get { + return signedState == .ValidSignature && (encState == .ValidEncryptedWithOldKey || encState == .ValidedEncryptedWithCurrentKey) + } + } + } diff --git a/enzevalos_iphone/SwiftUI/Data/SimulatorData.swift b/enzevalos_iphone/SwiftUI/Data/SimulatorData.swift index 62623526fa051e99915faed257063d1bbd3d9aa9..dfdd1c9705f59a493f40cd0ede0501d675567aba 100644 --- a/enzevalos_iphone/SwiftUI/Data/SimulatorData.swift +++ b/enzevalos_iphone/SwiftUI/Data/SimulatorData.swift @@ -128,10 +128,6 @@ struct PseudoContact: DisplayContact { return Image(uiImage: snapshot!) } - - var keyRecord: KeyRecord? { - return nil - } } @@ -154,6 +150,7 @@ struct PseuoMail: DisplayMail { var date = Date() var subject: String? = "Hello World" + var subjectWithFlag: String? = "Hello World" var body: String? = """ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent laoreet justo tellus, vitae molestie erat pharetra a. Curabitur porta finibus quam, eget posuere elit luctus vel. In sapien orci, eleifend pharetra nunc id, hendrerit gravida orci. In fringilla tellus mauris, hendrerit cursus enim lacinia vitae. Fusce vel nisl id sem blandit cursus vel quis odio. Aenean accumsan arcu eu quam iaculis, eu malesuada sapien dignissim. Aenean consequat elit nec metus auctor tempor. Aliquam erat volutpat. Proin non mi felis. @@ -187,7 +184,7 @@ struct PseuoMail: DisplayMail { var encState: EncryptionState - var persistentMail: PersistentMail? { + var persistentMail: MailRecord? { return nil } diff --git a/enzevalos_iphone/SwiftUI/Inbox/InboxCoordinator.swift b/enzevalos_iphone/SwiftUI/Inbox/InboxCoordinator.swift index fa50af6a326ac48f4451ba95aa261e539dc6a543..8054fa0c6e7c48dba317e595746cf83a17249660 100644 --- a/enzevalos_iphone/SwiftUI/Inbox/InboxCoordinator.swift +++ b/enzevalos_iphone/SwiftUI/Inbox/InboxCoordinator.swift @@ -9,7 +9,7 @@ import Foundation import SwiftUI -class InboxCoordinator { +class InboxCoordinator <M: MailRecord, C: DisplayContact> { let root: UINavigationController private let mainStoryboardName = "Main" @@ -27,10 +27,11 @@ class InboxCoordinator { } func pushInbox(){ + /* TODO Fix try? AppDelegate.getAppDelegate().mailHandler.startIMAPIdleIfSupported() - AppDelegate.getAppDelegate().mailHandler.updateFolder(folder: Folder.inbox, completionCallback: {_ in + AppDelegate.getAppDelegate().mailHandler.updateFolder(folder: MailHandler.INBOX, completionCallback: {_ in }) - + */ root.isToolbarHidden = true if let vc = inbox { @@ -41,11 +42,13 @@ class InboxCoordinator { } } else { + /* TODO: SwiftUI and DB? KeyRecord.findFirstMails() let context = DataHandler.handler.managedObjectContext let vc = UIHostingController(rootView: Inbox(coord: self).environment(\.managedObjectContext, context)) inbox = vc root.pushViewController(vc, animated: true) + */ } } @@ -55,7 +58,7 @@ class InboxCoordinator { root.pushViewController(controller, animated: true) } - func pushReadView(mail: PersistentMail) { + func pushReadView(mail: M) { if AppDelegate.getAppDelegate().newReadView, let readCoord = AppDelegate.getAppDelegate().readViewCoordinator { readCoord.pushReadView(mail: mail) } else { @@ -68,7 +71,8 @@ class InboxCoordinator { } } - func pushRecordView(record: KeyRecord){ + // TODO FIX!!! Was ist ein Record? Key oder address? + func pushRecordView(record: C){ let vc = mainStoryboard.instantiateViewController(withIdentifier: ViewID.KeyRecordView.rawValue) if let vc = vc as? ContactViewController { vc.keyRecord = record @@ -86,7 +90,8 @@ class InboxCoordinator { root.pushViewController(vc, animated: true) } - func pushMailListView(record: KeyRecord) { + // TODO FIX!!! Was ist ein Record? Key oder address? + func pushMailListView(record: C) { let vc = mainStoryboard.instantiateViewController(identifier: ViewID.MailListView.rawValue) if let vc = vc as? ListViewController { vc.contact = record diff --git a/enzevalos_iphone/SwiftUI/Inbox/KeyRecordRow.swift b/enzevalos_iphone/SwiftUI/Inbox/KeyRecordRow.swift index 52234c358db8b9f94586567d99ff8f8d19a54aa7..83c836e099b1efd675632f6ea92ac2cd53d16090 100644 --- a/enzevalos_iphone/SwiftUI/Inbox/KeyRecordRow.swift +++ b/enzevalos_iphone/SwiftUI/Inbox/KeyRecordRow.swift @@ -8,18 +8,18 @@ import SwiftUI -struct KeyRecordRow: View { - private static let coord = AppDelegate.getAppDelegate().inboxCoordinator +struct KeyRecordRow <M: DisplayMail, C: DisplayContact>: View { + private let coord = AppDelegate.getAppDelegate().inboxCoordinator - let keyrecord: KeyRecord - var first: PersistentMail? - var second: PersistentMail? + let keyrecord: C + var first: M? + var second: M? let name: String - init(keyrecord: KeyRecord) { + init(keyrecord: C) { self.keyrecord = keyrecord - first = keyrecord.firstMail - second = keyrecord.secondMail + //TODO first = keyrecord.firstMail + //TODO second = keyrecord.secondMail name = keyrecord.name } @@ -70,14 +70,15 @@ struct KeyRecordRow: View { } private var icon: some View{ - self.keyrecord.image.img + self.keyrecord.myImage .resizable() .frame(width: 60, height: 60) .shadow(radius: 5) .onTapGesture { + /* TODO if let coord = KeyRecordRow.coord { coord.pushRecordView(record: self.keyrecord) - } + }*/ } } @@ -86,17 +87,19 @@ struct KeyRecordRow: View { .frame(maxWidth: 300, alignment: .leading) .lineLimit(1) .onTapGesture { + /* TODO if let coord = KeyRecordRow.coord { coord.pushRecordView(record: self.keyrecord) - } + } */ } } private var moreMails: some View { Button(action: { + /* TODO if let coord = KeyRecordRow.coord { coord.pushMailListView(record: self.keyrecord) - } + }*/ }, label: { Text(NSLocalizedString("MailView.MoreMails", comment: "More mails")) .foregroundColor(.gray) diff --git a/enzevalos_iphone/SwiftUI/Read/ReadViewCoordinator.swift b/enzevalos_iphone/SwiftUI/Read/ReadViewCoordinator.swift index ca25281f05fab071989cb72d0abc8a7623ce7fbc..339f3cf2e8aa77bd1bab9478dd000ce68a55ea4d 100644 --- a/enzevalos_iphone/SwiftUI/Read/ReadViewCoordinator.swift +++ b/enzevalos_iphone/SwiftUI/Read/ReadViewCoordinator.swift @@ -23,13 +23,13 @@ import SwiftUI * Does Views disappear? */ -class ReadViewCoordinator { +class ReadViewCoordinator <M: DisplayMail, C: DisplayContact> { let root: UINavigationController private let mainStoryboardName = "Main" private let mainStoryboard: UIStoryboard private var readView: UIViewController? - private var mail: PersistentMail? + private var mail: M? func makeAction(action: ButtonAction) { guard let mail = mail else { @@ -58,12 +58,12 @@ class ReadViewCoordinator { mainStoryboard = UIStoryboard(name: self.mainStoryboardName, bundle: nil) } - func pushReadView(mail: PersistentMail){ + func pushReadView(mail: M){ self.mail = mail root.isToolbarHidden = true try? AppDelegate.getAppDelegate().mailHandler.startIMAPIdleIfSupported() - AppDelegate.getAppDelegate().mailHandler.updateFolder(folder: Folder.inbox, completionCallback: {_ in - }) + /* TODO update folder AppDelegate.getAppDelegate().mailHandler.updateFolder(folder: Folder.inbox, completionCallback: {_ in + }) */ let icon = mail.titleIcon let view = UIImageView(image: icon) let vc = UIHostingController(rootView: ReadMainView(mail: mail)) @@ -72,15 +72,15 @@ class ReadViewCoordinator { root.pushViewController(vc, animated: true) } - func delete(mail: PersistentMail){ - Logger.log(delete: mail, toTrash: true) - AppDelegate.getAppDelegate().mailHandler.move(mails: [mail], from: mail.folder.path, to: UserManager.backendTrashFolderPath) + func delete(mail: M){ + // TODO: Logger.log(delete: mail, toTrash: true) + // TODO AppDelegate.getAppDelegate().mailHandler.move(mails: [mail], from: mail.folder.path, to: UserManager.backendTrashFolderPath) AppDelegate.getAppDelegate().presentInboxViewController() } - func archive(mail: PersistentMail){ - Logger.log(archive: mail) - AppDelegate.getAppDelegate().mailHandler.move(mails: [mail], from: mail.folder.path, to: UserManager.backendArchiveFolderPath) + func archive(mail: M){ + //TODO Logger.log(archive: mail) + // AppDelegate.getAppDelegate().mailHandler.move(mails: [mail], from: mail.folder.path, to: UserManager.backendArchiveFolderPath) } func pushComposeView(to: [MailAddress], cc: [MailAddress], bcc: [MailAddress], subject: String?, body: String?, responseType: ResponseType?) { @@ -97,7 +97,7 @@ class ReadViewCoordinator { root.pushViewController(vc, animated: true) } - func pushContactView(contact: KeyRecord) { + func pushContactView(contact: C) { let vc = mainStoryboard.instantiateViewController(withIdentifier: ViewID.KeyRecordView.rawValue) if let vc = vc as? ContactViewController { vc.keyRecord = contact @@ -131,9 +131,7 @@ class ReadViewCoordinator { } func askSenderToResendForPK <M: DisplayMail> (mail: M) { - guard let sender = mail.sender.keyRecord else { - return - } + let sender = mail.sender let to = [sender.findAddress(temp: false)] var body = NSLocalizedString("ReadView.PrefilledMail.AskForResend.Body", comment: "") body += preparePreviousMailBody(mail: mail) @@ -142,9 +140,7 @@ class ReadViewCoordinator { } func askSenderToSendPK <M: DisplayMail>(mail: M) { - guard let sender = mail.sender.keyRecord else { - return - } + let sender = mail.sender let to = [sender.findAddress(temp: false)] let body = NSLocalizedString("ReadView.PrefilledMail.AskForPK.Body", comment: "") let subject = NSLocalizedString("ReadView.PrefilledMail.AskForPK.Subject", comment: "") @@ -189,9 +185,9 @@ class ReadViewCoordinator { private func findPersisentContact (persons: [DisplayContact]) -> [MailAddress] { var result = [MailAddress] () for p in persons { - if let contact = p.keyRecord { - result.append(contact.findAddress(temp: true)) - } + //TOTO if let contact = p.addr { + //result.append(contact.findAddress(temp: true)) + //} // TODO: Add data handler? } return result diff --git a/enzevalos_iphone/SwiftUI/Read/Tabbed Views/SenderViewChildren/SmallContactListView.swift b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/SenderViewChildren/SmallContactListView.swift index e8e87fad180e94112b752768339ee9caa15a2cbd..016a1b64ad58a5001c2c585769159c23818c601a 100644 --- a/enzevalos_iphone/SwiftUI/Read/Tabbed Views/SenderViewChildren/SmallContactListView.swift +++ b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/SenderViewChildren/SmallContactListView.swift @@ -56,10 +56,11 @@ struct SmallContactListView <C: DisplayContact>: View { } private func goToContact(contact: DisplayContact) { - guard let con = contact.keyRecord else { + /* TODOguard let con = contact.keyRecord else { return - } - AppDelegate.getAppDelegate().readViewCoordinator?.pushContactView(contact: con) + } */ + return + // AppDelegate.getAppDelegate().readViewCoordinator?.pushContactView(contact: con) } } diff --git a/enzevalos_iphone/SwiftUI/SupportingViews/MailView.swift b/enzevalos_iphone/SwiftUI/SupportingViews/MailView.swift index 8cac9ab0789bb6de69cee356bfdca3a4419d0943..3fe0d949a1bdd4f7b740665c4215d5025a7fcd0f 100644 --- a/enzevalos_iphone/SwiftUI/SupportingViews/MailView.swift +++ b/enzevalos_iphone/SwiftUI/SupportingViews/MailView.swift @@ -10,12 +10,12 @@ import SwiftUI -struct MailView: View { - private static let coord = AppDelegate.getAppDelegate().inboxCoordinator +struct MailView <M: DisplayMail>: View { + private let coord = AppDelegate.getAppDelegate().inboxCoordinator - var mail: PersistentMail + var mail: M - init(mail: PersistentMail){ + init(mail: M){ self.mail = mail } @@ -26,19 +26,19 @@ struct MailView: View { .frame(minWidth: 10, maxWidth: 200, alignment: .leading) .lineLimit(1) Spacer() - Text(mail.timeString) + Text(mail.date.dateToString) .font(.footnote) } } .onTapGesture { - if let coord = MailView.coord { - coord.pushReadView(mail: self.mail) + if let coord = coord, let m = self.mail as? AppDelegate.M { + coord.pushReadView(mail: m) } } } var subject: some View { - var text = Text(mail.getSubjectWithFlagsString() ) + var text = Text(mail.subjectWithFlag ?? "") if !mail.isRead { text = text.bold() } diff --git a/enzevalos_iphone/TableViewDataDelegate.swift b/enzevalos_iphone/TableViewDataDelegate.swift index 43a005e0c0051f95b71b62718a2dacd71a3ded5d..1744ad4ef9e281ec855b01548f48750c70471711 100644 --- a/enzevalos_iphone/TableViewDataDelegate.swift +++ b/enzevalos_iphone/TableViewDataDelegate.swift @@ -44,7 +44,7 @@ class TableViewDataDelegate: NSObject, UITableViewDelegate, UITableViewDataSourc if let img = pictures[indexPath.row] { cell.img.image = img } - + /* TODO if !DataHandler.handler.hasKey(adr: cell.address.text!) { cell.name.textColor! = UIColor.orange cell.address.textColor! = UIColor.orange @@ -52,7 +52,7 @@ class TableViewDataDelegate: NSObject, UITableViewDelegate, UITableViewDataSourc else { cell.name.textColor! = UIColor.black cell.address.textColor! = UIColor.black - } + } */ return cell } diff --git a/enzevalos_iphone/TempKey.swift b/enzevalos_iphone/TempKey.swift index f829a039be232ec6adf86ae37ec027b17a3a7b60..f1bb6b0d3afd562b9a3f77bb9d366617ecfdfbe0 100644 --- a/enzevalos_iphone/TempKey.swift +++ b/enzevalos_iphone/TempKey.swift @@ -20,7 +20,7 @@ protocol DisplayKey { get } - func save() -> SecretKey? + func save() -> SecretKeyRecord? } class TempKey: DisplayKey { @@ -96,47 +96,47 @@ class TempKey: DisplayKey { } func isNew() -> Bool { - return DataHandler.handler.findKey(keyID: keyID) == nil && DataHandler.handler.findSecretKey(keyID: keyID) == nil + return true + //TODO return DataHandler.handler.findKey(keyID: keyID) == nil && DataHandler.handler.findSecretKey(keyID: keyID) == nil } - func save() -> SecretKey? { + func save() -> SecretKeyRecord? { let keyIDs = SwiftPGP.init().store(tempKeys: [self]) - let sk = DataHandler.handler.newSecretKeys(keyIds: keyIDs, addPKs: true) - return sk.first + // TODO let sk = DataHandler.handler.newSecretKeys(keyIds: keyIDs, addPKs: true) + return nil///sk.first } - func savePK(type: LogData.TransferType) -> PersistentKey? { + func savePK(type: LogData.TransferType) -> PublicKeyRecord? { let keyIDs = SwiftPGP.init().store(tempKeys: [self]) - var pk: PersistentKey? = nil + var pk: PublicKeyRecord? = nil for key in keyIDs { - pk = DataHandler.handler.newPublicKey(keyID: key, cryptoType: .PGP , adr: mailAddresses.first ?? "", autocrypt: false, firstMail: nil, newGenerated: false, saveKey: true, transferType: type) + //TODO pk = DataHandler.handler.newPublicKey(keyID: key, cryptoType: .PGP , adr: mailAddresses.first ?? "", autocrypt: false, firstMail: nil, newGenerated: false, saveKey: true, transferType: type) } return pk } } -extension SecretKey: DisplayKey { +extension SecretKeyRecord: DisplayKey { var importDate: Date { if let date = self.importedDate { return date as Date } - let date = Date.init() - self.importedDate = date as NSDate - return date + self.importedDate = Date() + return importedDate ?? Date() } var pgpKey: Key? { let pgp = SwiftPGP() - let id = keyID + let id = fingerprint ?? "" return pgp.loadKey(id: id) } - func save() -> SecretKey? { + func save() -> SecretKeyRecord? { return self } } -extension PersistentKey: DisplayKey { +extension PublicKeyRecord: DisplayKey { var importDate: Date { if let date = self.discoveryDate { return date @@ -150,10 +150,10 @@ extension PersistentKey: DisplayKey { var pgpKey: Key? { let pgp = SwiftPGP() - return pgp.loadKey(id: keyID) + return pgp.loadKey(id: fingerprint ?? "") } - func save() -> SecretKey? { + func save() -> SecretKeyRecord? { return nil } } diff --git a/enzevalos_iphone/TravelHandler.swift b/enzevalos_iphone/TravelHandler.swift index 667218d883bc9bb79583cd67a4944d4a195270ba..42f13298992038f193d4b65c4d80d7fc66807809 100644 --- a/enzevalos_iphone/TravelHandler.swift +++ b/enzevalos_iphone/TravelHandler.swift @@ -196,8 +196,8 @@ public class TravelHandler { let mailHandler = AppDelegate.getAppDelegate().mailHandler if mode == .atHome { self.backupAddress = UserManager.loadUserValue(.userAddr) as? String - let home = DataHandler.handler.findMailAddress(adr: self.backupAddress!)! - backupKeyID = home.primaryActiveKeyID + //TODO let home = DataHandler.handler.findMailAddress(adr: self.backupAddress!)! + // backupKeyID = home.primaryActiveKeyID canSecurelyBackup = true } let backupAddress = self.backupAddress! @@ -206,11 +206,11 @@ public class TravelHandler { //get keys for contacts for c in contacts { // discard contacts, who do not have a key (should be checked in the ui prior calling this function too) - if let adr = DataHandler.handler.findMailAddress(adr: c), adr.hasKey, let primaryKey = adr.primaryKey { + /* TODO if let adr = DataHandler.handler.findMailAddress(adr: c), adr.hasKey, let primaryKey = adr.primaryKey { contactsWithKey.append(c) keyIDs[c] = primaryKey.keyID keys[c] = encodeKeys(relatedTo: primaryKey) - } + }*/ } let traveler = Traveler(contacts: contactsWithKey, keys: keys, backupAddress: backupAddress, backupKey: backupKey, canSecurelyBackup: canSecurelyBackup) let password = try traveler.getToRemember() @@ -220,38 +220,40 @@ public class TravelHandler { } mode = .borderCrossing if TravelHandler.deleteCommunication { - DataHandler.handler.deleteDecryptedMailCopies() + //TODO DataHandler.handler.deleteDecryptedMailCopies() } - DataHandler.handler.deleteSecretKeys() + //TODO DataHandler.handler.deleteSecretKeys() let data = traveler.getToStore() travelerStored = data return password } - private func encodeKeys(relatedTo key: PersistentKey) -> String { + private func encodeKeys(relatedTo key: PublicKeyRecord) -> String { var keys: [String] = [] let pgp = SwiftPGP() + /* for relatedKey in key.relatedKeys { if let exportedKey = pgp.exportKey(id: relatedKey.keyID, isSecretkey: false, autocrypt: false) { keys.append(exportedKey) } - } + }*/ if let data = try? JSONEncoder().encode(keys) { return String(data: data, encoding: .utf8) ?? "" } return "" } - private func compareKeys(keysFromTraveler: String, storedPrimaryKey: PersistentKey) -> Bool { + private func compareKeys(keysFromTraveler: String, storedPrimaryKey: PublicKeyRecord) -> Bool { if let data = keysFromTraveler.data(using: .utf8), let checkedKeys = try? JSONDecoder().decode([String].self, from: data) { var storedKeys: [String] = [] let pgp = SwiftPGP() + /* for relatedKey in storedPrimaryKey.relatedKeys { if let exportedKey = pgp.exportKey(id: relatedKey.keyID, isSecretkey: false, autocrypt: false) { storedKeys.append(exportedKey) } - } + }*/ for storedKey in storedKeys { if !checkedKeys.contains(storedKey) { return false @@ -270,6 +272,7 @@ public class TravelHandler { * failed to load data? */ func followUp(with password: String) throws { + /* guard mode == .borderCrossing else { throw TravelHandlerError.invalidMode } @@ -283,21 +286,23 @@ public class TravelHandler { var keyIDs: [String: String] = [:] let pgp = SwiftPGP() for c in traveler.contacts { - if let adr = DataHandler.handler.findMailAddress(adr: c), adr.hasKey, let primaryKey = adr.primaryKey, let travelerKey = travelerKeys[c], compareKeys(keysFromTraveler: travelerKey, storedPrimaryKey: primaryKey){ + /* TODO if let adr = DataHandler.handler.findMailAddress(adr: c), adr.hasKey, let primaryKey = adr.primaryKey, let travelerKey = travelerKeys[c], compareKeys(keysFromTraveler: travelerKey, storedPrimaryKey: primaryKey){ keyIDs[c] = primaryKey.keyID } else { throw TravelError.corruptData - } + }*/ } if traveler.canSecurelyBackup && (backupAddress != traveler.backupAddress || pgp.exportKey(id: backupKeyID!, isSecretkey: false, autocrypt: false) != traveler.backupKey) { throw TravelError.corruptData } var oldFingerprint = "00000000000000000000000000000000000000000000000000000000000000" + if let fingerprint = DataHandler.handler.getMailAddress(UserManager.loadUserValue(Attribute.userAddr) as! String, temporary: true).primaryKey!.currentlyActiveKey.fingerprint { oldFingerprint = fingerprint } let keyID = DataHandler.handler.createNewSecretKey(adr: UserManager.loadUserValue(Attribute.userAddr) as! String).keyID - let pubKey = pgp.exportKey(id: keyID, isSecretkey: false, autocrypt: false)! + + let pubKey = pgp.exportKey(id: keyID, isSecretkey: false, autocrypt: false)! let sharedSecrets = try traveler.getToSend() for c in traveler.contacts { mailHandler.sendTravelCallForUse(to: c, sharedSecret: sharedSecrets[c]!, pubKey: pubKey, keyID: keyID, repealedKeyFingerprint: oldFingerprint, callback: {_ in }) //TODO: errorhandling! @@ -323,12 +328,14 @@ public class TravelHandler { canSecurelyBackup = false throw TravelHandlerError.corruptData } + */ } private func handleCorruption() { canSecurelyBackup = false let mailHandler = AppDelegate.getAppDelegate().mailHandler let pgp = SwiftPGP() + /* var oldFingerprint = "00000000000000000000000000000000000000000000000000000000000000" if let fingerprint = DataHandler.handler.getMailAddress(UserManager.loadUserValue(Attribute.userAddr) as! String, temporary: true).primaryKey!.currentlyActiveKey.fingerprint { oldFingerprint = fingerprint @@ -346,9 +353,11 @@ public class TravelHandler { } mode = .traveling _ = DataHandler.handler.newPublicKey(keyID: keyID, cryptoType: .PGP, adr: UserManager.loadUserValue(Attribute.userAddr) as! String, autocrypt: false, transferType: nil) + */ } public func loadBackup(with passcode: String) -> Bool { + /* let folder = DataHandler.handler.findFolder(with: TravelHandler.backupFolder) var regularBackup: [PersistentMail] = [] var travelBackup: [PersistentMail] = [] @@ -403,6 +412,7 @@ public class TravelHandler { } mode = .atHome return true + */ } public func getUI(current viewController: UIViewController) -> UIViewController { @@ -446,8 +456,8 @@ public class TravelHandler { let describeContactsController = IntroButtonViewController.storyboardInstance(description: NSLocalizedString("TravelIntroContactDescription", comment: ""), buttonText: NSLocalizedString("Continue", comment: ""))! controllers.append(describeContactsController) - let contacts = getSecureContacts() - let contactViewController = IntroContactTableViewController.storyboardInstance(contacts: contacts, titleText: NSLocalizedString("SelectContacts", comment: ""), titleDescription: NSLocalizedString("TravelSelectContacts", comment: ""))! + // let contacts = [String: [(EnzevalosContact, PersistentKey, [Mail_Address])]]() //getSecureContacts() + //let contactViewController = IntroContactTableViewController.storyboardInstance(contacts: contacts, titleText: NSLocalizedString("SelectContacts", comment: ""), titleDescription: NSLocalizedString("TravelSelectContacts", comment: ""))! let decisionController = IntroYesNoViewController.storyboardInstance(description: NSLocalizedString("TravelCloseLetters", comment: ""), titleText: NSLocalizedString("CloseLetters", comment: ""), titleDescription: NSLocalizedString("CloseLettersDescription", comment: ""))! if !canSecurelyBackup { decisionController.titleImage = TravelHandler.troublePlaneIcon @@ -470,13 +480,13 @@ public class TravelHandler { } description1.skipAction = {_ in pageViewController?.setViewControllers([describeContactsController], direction: .forward, animated: true, completion: nil)} - describeContactsController.buttonAction = {_ in describeContactsController.navigationController?.pushViewController(contactViewController, animated: true)} + // TODO describeContactsController.buttonAction = {_ in describeContactsController.navigationController?.pushViewController(contactViewController, animated: true)} - contactViewController.title = "Kontakte auswählen" - contactViewController.nextAction = { + // contactViewController.title = "Kontakte auswählen" + /* contactViewController.nextAction = { TravelHandler.selectedContacts = contactViewController.getSelectedContacts() contactViewController.navigationController?.pushViewController(decisionController, animated: true) - } + }*/ decisionController.yesAction = {_ in TravelHandler.deleteCommunication = true decisionController.navigationController?.pushViewController(describeSecretController, animated: true) @@ -582,7 +592,7 @@ public class TravelHandler { } backupCodeInput.update(description: "Der Code hat leider nicht funktioniert. Bist du dir sicher, dass du ihn richtig abgetippt hast? Lege deine Sicherung im Ordner "+UserManager.convertToFrontendFolderPath(from: TravelHandler.backupFolder)+" ab, falls es trotzdem nicht funktioniert.") } - + /* backupDescription.spinningAction = { AppDelegate.getAppDelegate().mailHandler.updateFolder(folder: DataHandler.handler.findFolder(with: TravelHandler.backupFolder), completionCallback: { error in if let _ = error { backupDescription.text = "Es konnten keine Sicherungen gefunden werden. Lege deine Sicherungen im Ordner "+UserManager.convertToFrontendFolderPath(from: TravelHandler.backupFolder)+" ab und probiere es erneut!" @@ -592,10 +602,11 @@ public class TravelHandler { } backupDescription.endSpinning() }) } + */ return backupDescription } - + /* private func getSecureContacts() -> [String: [(EnzevalosContact, PersistentKey, [Mail_Address])]] { let dataHandler = DataHandler.handler var contacts = dataHandler.getContacts() @@ -627,8 +638,9 @@ public class TravelHandler { } return result } + */ - private func getFirstChar(from contact: EnzevalosContact) -> String { + private func getFirstChar(from contact: Contact) -> String { if let char = contact.name.first, let unicode = char.unicodeScalars.first { let diffUpper = abs(Int(unicode.value) - Int(UnicodeScalar("A").value)) let diffLower = abs(Int(unicode.value) - Int(UnicodeScalar("a").value)) diff --git a/enzevalos_iphone/enzevalos_iphone.xcdatamodeld/.xccurrentversion b/enzevalos_iphone/enzevalos_iphone.xcdatamodeld/.xccurrentversion index fa8416cffd55eab648ab8a1e71b0f7d54706fc10..0c67376ebacb410fd873cac1d8d8dd431b262c02 100644 --- a/enzevalos_iphone/enzevalos_iphone.xcdatamodeld/.xccurrentversion +++ b/enzevalos_iphone/enzevalos_iphone.xcdatamodeld/.xccurrentversion @@ -1,8 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> -<dict> - <key>_XCCurrentVersionName</key> - <string>enzevalos_iphone 10.xcdatamodel</string> -</dict> +<dict/> </plist> diff --git a/enzevalos_iphone/persistentData/AddressRecord.swift b/enzevalos_iphone/persistentData/AddressRecord.swift index 59563398d50e56af531af5832e17f6fdbfb59c6e..0ad7026032bbe66ecc61a7e1c478e181935835e9 100644 --- a/enzevalos_iphone/persistentData/AddressRecord.swift +++ b/enzevalos_iphone/persistentData/AddressRecord.swift @@ -6,6 +6,11 @@ // Copyright © 2020 fu-berlin. All rights reserved. // +/* TODO: usedKeys -> associted? +*/ +import Contacts +import SwiftUI + extension AddressRecord { static var entityName = "AddressRecord" @@ -15,4 +20,145 @@ extension AddressRecord { self.displayname = name } } + + + public var name: String { + get { + if let contact = self.phoneBookID { + // TODO Look up cn contact name! + + } + if let displayname = self.displayname { + return displayname + } + return self.email ?? NSLocalizedString("noName", comment: "We have no name for this one") // TODO FIX! + } + } + + var mails: [MailRecord] { + get { + var mails = [MailRecord]() + mails.append(contentsOf: mailsFromSet(set: self.inToField)) + mails.append(contentsOf: mailsFromSet(set: self.inCCField)) + mails.append(contentsOf: mailsFromSet(set: self.inBCCField)) + mails.append(contentsOf: mailsFromSet(set: self.inFromField)) + return mails + } + } + private func mailsFromSet(set: NSSet?) -> [MailRecord] { + if let set = set, let mails = set.allObjects as? [MailRecord] { + return mails + } + return [] + } + + var hasPublicKey: Bool { + get { + if let keys = self.usedPublicKeys { + return keys.count > 0 + } + return false + } + } +} + +extension AddressRecord: MailAddress { + public var mailAddress: String { + get { + return email ?? "" + } + } + + public var label: CNLabeledValue<NSString> { + return CNLabeledValue.init(label: CNLabelWork, value: (email ?? "") as NSString) // TODO + } + + public var hasKey: Bool { + get { + return hasPublicKey + } + } + + public var isUser: Bool { + return false // TODO + } + + public var primaryKey: PublicKeyRecord? { + return self.publicKeys.first // TODO + } + + public var publicKeys: Set<PublicKeyRecord> { + if let set = usedPublicKeys, let keys = set as? Set<PublicKeyRecord> { + return keys + } + return Set<PublicKeyRecord> () + } + + public var contact: Contact? { + return nil // TODO + } + + +} + +extension AddressRecord: Contact { + public var cnContact: CNContact? { + // TODO FIX! + return nil + } + + public func getMailAddresses() -> [MailAddress] { + var addresses = [AddressRecord] () + addresses.append(self) + for key in self.publicKeys { + if let set = key.usedAddress as? Set<AddressRecord> { + addresses.append(contentsOf: set) + } + } + + return addresses + } +} + +extension AddressRecord: DisplayContact { + var addr: String { + return email ?? "" + } + + var myImage: Image { + return Image(uiImage: getImageOrDefault()) + } + + var isInContactBook: Bool { + return false // TODO + } + + var otherAddresses: [String] { + return getMailAddresses().map{$0.mailAddress} + } + + var keyIDs: [String] { + if let keys = usedPublicKeys?.allObjects as? [PublicKeyRecord] { + return keys.map{($0.fingerprint ?? "")}.filter{$0 != ""} + } + return [] + } + + var previousMails: Int { + return 0 //TODO + } + + var previousResponses: Int { + return 0 //TODO + } + + var hasSimilarContacts: Bool { + return false // TODO + } + + var similarContacts: [String] { + return [] + } + + } diff --git a/enzevalos_iphone/persistentData/DataModel.xcdatamodeld/DataModel.xcdatamodel/contents b/enzevalos_iphone/persistentData/DataModel.xcdatamodeld/DataModel.xcdatamodel/contents index f0db75e4b7a699f56636c8c7964d7428f7b96119..8248d51ba153eb870a0af7a81909b2c73508671d 100644 --- a/enzevalos_iphone/persistentData/DataModel.xcdatamodeld/DataModel.xcdatamodel/contents +++ b/enzevalos_iphone/persistentData/DataModel.xcdatamodeld/DataModel.xcdatamodel/contents @@ -7,10 +7,12 @@ <entity name="AddressRecord" representedClassName="AddressRecord" syncable="YES" codeGenerationType="class"> <attribute name="displayname" optional="YES" attributeType="String"/> <attribute name="email" attributeType="String"/> + <attribute name="phoneBookID" optional="YES" attributeType="String"/> <relationship name="inBCCField" toMany="YES" deletionRule="Nullify" destinationEntity="MailRecord" inverseName="bccAddresses" inverseEntity="MailRecord"/> <relationship name="inCCField" toMany="YES" deletionRule="Nullify" destinationEntity="MailRecord" inverseName="ccAddresses" inverseEntity="MailRecord"/> <relationship name="inFromField" toMany="YES" deletionRule="Nullify" destinationEntity="MailRecord" inverseName="fromAddress" inverseEntity="MailRecord"/> <relationship name="inToField" toMany="YES" deletionRule="Nullify" destinationEntity="MailRecord" inverseName="toAddresses" inverseEntity="MailRecord"/> + <relationship name="usedPublicKeys" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="PublicKeyRecord" inverseName="usedAddress" inverseEntity="PublicKeyRecord"/> <uniquenessConstraints> <uniquenessConstraint> <constraint value="email"/> @@ -70,27 +72,32 @@ </entity> <entity name="PublicKeyRecord" representedClassName="PublicKeyRecord" parentEntity="AbstractKeyRecord" syncable="YES" codeGenerationType="class"> <attribute name="discoveryDate" attributeType="Date" usesScalarValueType="NO"/> + <attribute name="expireDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/> <attribute name="lastSeenInAutocryptHeader" optional="YES" attributeType="Date" usesScalarValueType="NO"/> <attribute name="lastSeenSignedMail" optional="YES" attributeType="Date" usesScalarValueType="NO"/> <attribute name="origin" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/> <attribute name="preferEncryption" optional="YES" attributeType="Integer 16" usesScalarValueType="YES"/> + <attribute name="verificationDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/> + <relationship name="mySecretKeyRecord" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="SecretKeyRecord" inverseName="myPublicKeyRecord" inverseEntity="SecretKeyRecord"/> <relationship name="sendWithAutocryptHeader" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MailRecord" inverseName="attachedAutocryptPublicKey" inverseEntity="MailRecord"/> <relationship name="sendWithMail" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MailRecord" inverseName="attachedPublicKeys" inverseEntity="MailRecord"/> <relationship name="signedMails" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MailRecord" inverseName="signatureKey" inverseEntity="MailRecord"/> + <relationship name="usedAddress" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="AddressRecord" inverseName="usedPublicKeys" inverseEntity="AddressRecord"/> </entity> <entity name="SecretKeyRecord" representedClassName="SecretKeyRecord" parentEntity="AbstractKeyRecord" syncable="YES" codeGenerationType="class"> <attribute name="exported" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/> <attribute name="importedDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/> <relationship name="decryptedMails" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MailRecord" inverseName="decryptionKey" inverseEntity="MailRecord"/> + <relationship name="myPublicKeyRecord" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="PublicKeyRecord" inverseName="mySecretKeyRecord" inverseEntity="PublicKeyRecord"/> <relationship name="sendWithMail" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MailRecord" inverseName="attachedSecretKey" inverseEntity="MailRecord"/> </entity> <elements> <element name="AbstractKeyRecord" positionX="-27" positionY="54" width="128" height="28"/> - <element name="AddressRecord" positionX="-36" positionY="27" width="128" height="133"/> + <element name="AddressRecord" positionX="-36" positionY="27" width="128" height="163"/> <element name="AttachmentRecord" positionX="0" positionY="144" width="128" height="133"/> <element name="FolderRecord" positionX="27" positionY="135" width="128" height="193"/> <element name="MailRecord" positionX="-54" positionY="-9" width="128" height="28"/> - <element name="PublicKeyRecord" positionX="9" positionY="63" width="128" height="28"/> - <element name="SecretKeyRecord" positionX="-9" positionY="63" width="128" height="28"/> + <element name="PublicKeyRecord" positionX="9" positionY="63" width="128" height="223"/> + <element name="SecretKeyRecord" positionX="-9" positionY="63" width="128" height="118"/> </elements> </model> \ No newline at end of file diff --git a/enzevalos_iphone/persistentData/FolderRecord.swift b/enzevalos_iphone/persistentData/FolderRecord.swift index d49244ff700b5b75a2a7309c62b5fded8dc0b3cf..4a9dd1384fb74b7b1b6db842993b6440ac32135b 100644 --- a/enzevalos_iphone/persistentData/FolderRecord.swift +++ b/enzevalos_iphone/persistentData/FolderRecord.swift @@ -6,6 +6,8 @@ // Copyright © 2020 fu-berlin. All rights reserved. // +//TODO Add name? frontendName + extension FolderRecord { static let entityName = "FolderRecord" diff --git a/enzevalos_iphone/persistentData/MailRecord.swift b/enzevalos_iphone/persistentData/MailRecord.swift index 798e055c0d8ee2ba3bb04cf457c6c8c74385f145..39249a3b9e8ee6f9662ddc14cfe1cadd2c73d3f6 100644 --- a/enzevalos_iphone/persistentData/MailRecord.swift +++ b/enzevalos_iphone/persistentData/MailRecord.swift @@ -8,6 +8,16 @@ /** Managed object subclass extension for the mail entity. + + TODO: + Encrypted before? + uidvalidity + received + showMessage -> Set true after ack the warning and user action. Add? + Different types of content? Text vs HTML?! + + self.keyDiscoveryDate = mail?.from.contact?.firstSecureMailReceived + isNewPubKey -> First mail with a new public key */ extension MailRecord { static let entityName = "MailRecord" @@ -36,4 +46,158 @@ extension MailRecord { var encryptionState: EncryptionState { return EncryptionState.init(rawValue: encryptionStateInt) ?? .NoEncryption } + + var addresses: [AddressRecord] { + get { + var addrs = [AddressRecord]() + addrs.append(contentsOf: addressesFromSet(set: self.toAddresses)) + addrs.append(contentsOf: addressesFromSet(set: self.ccAddresses)) + addrs.append(contentsOf: addressesFromSet(set: self.bccAddresses)) + if let from = self.fromAddress { + addrs.append(from) + } + return addrs + } + } + + private func addressesFromSet(set: NSSet?) -> [AddressRecord] { + if let set = set, let addrs = set.allObjects as? [AddressRecord] { + return addrs + } + return [] + } + + // TODO: Change Flag! + var isRead: Bool { + get { + let mcoflag = MCOMessageFlag.init(rawValue: Int(flag)) + let value = mcoflag.contains(MCOMessageFlag.seen) + return value + } + } + + var messageFlag: MCOMessageFlag { + get { + return MCOMessageFlag.init(rawValue: Int(flag)) + } + } + + var subjectWithFlag: String { + let subj: String + var returnString: String = "" + if let subject = self.subject { + subj = subject + } else { + subj = NSLocalizedString("SubjectNo", comment: "This email has no subject") + } + if !self.isRead { + returnString.append("🔵 ") + } + if MCOMessageFlag.answered.isSubset(of: messageFlag) { + returnString.append("↩️ ") + } + if MCOMessageFlag.forwarded.isSubset(of: messageFlag) { + returnString.append("➡️ ") + } + if MCOMessageFlag.flagged.isSubset(of: messageFlag) { + returnString.append("⭐️ ") + } + return "\(returnString)\(subj)" + } + + /** + Just a short part of the body. Can be used for a preview. + In case of trouble there is no preview. + */ + var shortBodyString: String? { + guard self.signatureState == .InvalidSignature || self.encryptionState == .UnableToDecrypt else { + return nil + } + guard var body = body else { + return nil + } + + + body = body.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) + if body.count > 50 { + body = String(body[..<body.index(body.startIndex, offsetBy: 50)]) + } + let messageArray = body.components(separatedBy: "\n") + return messageArray.joined(separator: " ") + + } +} + +extension MailRecord: DisplayMail { + typealias C = AddressRecord + + var sender: C { + if let from = self.fromAddress { + return from + } + print("ERROR!") + return self.fromAddress! + } + + var tos: [C] { + if let array = toAddresses?.allObjects as? [AddressRecord]{ + return array + } + return [] + } + + var ccs: [C] { + if let array = ccAddresses?.allObjects as? [AddressRecord]{ + return array + } + return [] + } + + var bccs: [C] { + if let array = bccAddresses?.allObjects as? [AddressRecord]{ + return array + } + return [] + } + + var routingStops: [Landmark] { + return [] // TODO + } + + var signedState: SignatureState { + return SignatureState.init(rawValue: self.signatureStateInt) ?? .NoSignature + } + + var persistentMail: MailRecord? { + return self + } + + var displayAttachments: [DisplayAttachment] { + /*var attachments = [DisplayAttachment]() + if let coreDataAttachment = self.attachments { + for att in coreDataAttachment { + if let att = att as? Attachment { + attachments.append(att) + } + } + } + return attachments */ + return [] //TODO + } + + var folderType: FolderType { + return .Other // TODO FIX + } + + func markAsRead(isRead: Bool) { + // TODO! + } + + var transportEnc: Bool { + get { + return true + } + } + + } diff --git a/enzevalos_iphone/persistentData/PersistentDataProvider.swift b/enzevalos_iphone/persistentData/PersistentDataProvider.swift index c198ff5bd820c49695db2c931fa14e18545361ae..498ca2de77afc31240878b6b0180041059260f5b 100644 --- a/enzevalos_iphone/persistentData/PersistentDataProvider.swift +++ b/enzevalos_iphone/persistentData/PersistentDataProvider.swift @@ -18,8 +18,21 @@ import CoreData + Addresses per Key -> Contact View + all folders -> Folder Overview + find specific mail -> Detail view + + TODOs: + + SwiftUI and CoreData? + +Reload mails for record loadMailsForRecord(contact!, folderPath: UserManager.backendInboxFolderPath, completionCallback: doneLoading) + Update folder updateFolder(folder: Folder.inbox, completionCallback: {_ in + Delete a Mail + find public or secret keys + find address by name + find folder by name + */ class PersitentDataProvider { + static let dataProvider = PersitentDataProvider() // MARK: - Core Data private let entitiesNames = [AddressRecord.entityName, MailRecord.entityName, FolderRecord.entityName, PublicKeyRecord.entityName, SecretKeyRecord.entityName, AttachmentRecord.entityName] @@ -327,6 +340,40 @@ class PersitentDataProvider { } + func generateFetchedFolderResultsController(folderpath: String) -> NSFetchedResultsController<FolderRecord> { + let freq = NSFetchRequest<FolderRecord>(entityName: FolderRecord.entityName) + freq.sortDescriptors = [NSSortDescriptor(key: "folderpath", ascending: true)] + let predicate = NSPredicate(format: "folderpath == %@", folderpath) + freq.predicate = predicate + let controller = NSFetchedResultsController(fetchRequest: freq, + managedObjectContext: persistentContainer.viewContext, + sectionNameKeyPath: nil, cacheName: nil) + // Perform the fetch. + do { + try controller.performFetch() + } catch { + fatalError("Unresolved error \(error)") + } + return controller + } + + + func generateFetchedAddressResultsController(address: String) -> NSFetchedResultsController<AddressRecord> { + let freq = NSFetchRequest<AddressRecord>(entityName: AddressRecord.entityName) + freq.sortDescriptors = [NSSortDescriptor(key: "email", ascending: true)] + let predicate = NSPredicate(format: "email == %@", address) + freq.predicate = predicate + let controller = NSFetchedResultsController(fetchRequest: freq, + managedObjectContext: persistentContainer.viewContext, + sectionNameKeyPath: nil, cacheName: nil) + // Perform the fetch. + do { + try controller.performFetch() + } catch { + fatalError("Unresolved error \(error)") + } + return controller + } /** Handles remote store change notifications (.NSPersistentStoreRemoteChange). storeRemoteChange runs on the queue where the changes were made. diff --git a/enzevalos_iphone/persistentData/PublicKeyRecord.swift b/enzevalos_iphone/persistentData/PublicKeyRecord.swift index 8a714134fcb6b4789c9fd6069679d1cd6cd75715..a879d6fc332b745f5d12b85bd4185260dd47c15d 100644 --- a/enzevalos_iphone/persistentData/PublicKeyRecord.swift +++ b/enzevalos_iphone/persistentData/PublicKeyRecord.swift @@ -14,7 +14,9 @@ enum Origin: Int16 { case Generated = 4 case FileTransfer = 5 } - + /* + TODO: signed mails should be sorted! ACCORDING TO date + */ extension PublicKeyRecord { static let entityName = "PublicKeyRecord"