diff --git a/EnzevalosContact+CoreDataClass.swift b/EnzevalosContact+CoreDataClass.swift index 9e05c20d2914769ac8b9301f364511abefe78465..252c38502a334efac596473707b0c4764322b13d 100644 --- a/EnzevalosContact+CoreDataClass.swift +++ b/EnzevalosContact+CoreDataClass.swift @@ -30,14 +30,12 @@ fileprivate func < <T : Comparable>(lhs: T?, rhs: T?) -> Bool { open class EnzevalosContact: NSManagedObject, Contact, Comparable { open var name: String { - let name = nameOptional - - if displayname != nil { - return displayname! - } else if name == nil { - return NSLocalizedString("noName", comment: "We have no name for this one") + if let name = nameOptional { + return name + } else if let displayname = displayname { + return displayname } else { - return name! + return NSLocalizedString("noName", comment: "We have no name for this one") } } diff --git a/PersistentMail +CoreDataClass.swift b/PersistentMail +CoreDataClass.swift index fea73f0c92d4a507c599a8ecd469db5c897bad09..1836f6d32594459705ffc950cfe08f3b6226728d 100644 --- a/PersistentMail +CoreDataClass.swift +++ b/PersistentMail +CoreDataClass.swift @@ -13,6 +13,8 @@ import CoreData @objc(PersistentMail) open class PersistentMail: NSManagedObject, Mail { + public var predecessor: PersistentMail? = nil + var showMessage: Bool = false @@ -34,6 +36,21 @@ open class PersistentMail: NSManagedObject, Mail { _ = DataHandler.handler.save() } } + + 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() + } + } var timeString: String { var returnString = "" diff --git a/enzevalos_iphone.xcodeproj/project.xcworkspace/xcshareddata/enzevalos_iphone.xcscmblueprint b/enzevalos_iphone.xcodeproj/project.xcworkspace/xcshareddata/enzevalos_iphone.xcscmblueprint new file mode 100644 index 0000000000000000000000000000000000000000..9527f63c17356ca65d1fdd7d0e043c064c880b78 --- /dev/null +++ b/enzevalos_iphone.xcodeproj/project.xcworkspace/xcshareddata/enzevalos_iphone.xcscmblueprint @@ -0,0 +1,30 @@ +{ + "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "08634A2A40CAF434DAE2F242AB5514BB7A368848", + "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { + + }, + "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { + "08634A2A40CAF434DAE2F242AB5514BB7A368848" : 9223372036854775807, + "D2C7EA0F1A440C91BD6EBA17F1863FAC9BB7F993" : 9223372036854775807 + }, + "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "58AEEA4D-40DB-4A72-8DC0-F394C44FE99A", + "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { + "08634A2A40CAF434DAE2F242AB5514BB7A368848" : "enzevalos_iphone\/", + "D2C7EA0F1A440C91BD6EBA17F1863FAC9BB7F993" : "workspace\/" + }, + "DVTSourceControlWorkspaceBlueprintNameKey" : "enzevalos_iphone", + "DVTSourceControlWorkspaceBlueprintVersion" : 204, + "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "enzevalos_iphone.xcodeproj", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "git.imp.fu-berlin.de:enzevalos\/enzevalos_iphone.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "08634A2A40CAF434DAE2F242AB5514BB7A368848" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "git.imp.fu-berlin.de:enzevalos\/enzevalos_iphone_workspace.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "D2C7EA0F1A440C91BD6EBA17F1863FAC9BB7F993" + } + ] +} \ No newline at end of file diff --git a/enzevalos_iphone.xcodeproj/project.xcworkspace/xcuserdata/Olli.xcuserdatad/UserInterfaceState.xcuserstate b/enzevalos_iphone.xcodeproj/project.xcworkspace/xcuserdata/Olli.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..478d0f4fa9f5b7ac64cd9069b9ca722074950663 Binary files /dev/null and b/enzevalos_iphone.xcodeproj/project.xcworkspace/xcuserdata/Olli.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/enzevalos_iphone.xcodeproj/xcuserdata/Olli.xcuserdatad/xcschemes/xcschememanagement.plist b/enzevalos_iphone.xcodeproj/xcuserdata/Olli.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000000000000000000000000000000000000..cacd0960e96d738e4de48fcd06fe3c87a838337e --- /dev/null +++ b/enzevalos_iphone.xcodeproj/xcuserdata/Olli.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,24 @@ +<?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>SuppressBuildableAutocreation</key> + <dict> + <key>A13526741D955BDF00D3BFE1</key> + <dict> + <key>primary</key> + <true/> + </dict> + <key>A135268B1D955BE000D3BFE1</key> + <dict> + <key>primary</key> + <true/> + </dict> + <key>A13526961D955BE000D3BFE1</key> + <dict> + <key>primary</key> + <true/> + </dict> + </dict> +</dict> +</plist> diff --git a/enzevalos_iphone/AddressHandler.swift b/enzevalos_iphone/AddressHandler.swift index b74f47f98d00fb78627bc2657e762b1ac51db6fe..d55c423b265d781776068d23e5f02722a8cf6bb5 100644 --- a/enzevalos_iphone/AddressHandler.swift +++ b/enzevalos_iphone/AddressHandler.swift @@ -11,51 +11,51 @@ import Contacts import UIKit.UIImage class AddressHandler { - + static var addresses: [String] = [] - + static var freqAlgorithm: ([String]) -> [(UIImage, String, String, UIImage?, UIColor)] = { - (inserted : [String]) -> [(UIImage, String, String, UIImage?, UIColor)] in - var cons : [(UIImage,String,String,UIImage?,UIColor)] = [] - do{ - - try AppDelegate.getAppDelegate().contactStore.enumerateContacts(with: CNContactFetchRequest(keysToFetch: [CNContactFormatter.descriptorForRequiredKeys(for: CNContactFormatterStyle.fullName), CNContactEmailAddressesKey as CNKeyDescriptor, CNContactImageDataKey as CNKeyDescriptor, CNContactThumbnailImageDataKey as CNKeyDescriptor]), usingBlock: { - ( c : CNContact, stop) -> Void in + (inserted: [String]) -> [(UIImage, String, String, UIImage?, UIColor)] in + var cons: [(UIImage, String, String, UIImage?, UIColor)] = [] + do { + + try AppDelegate.getAppDelegate().contactStore.enumerateContacts(with: CNContactFetchRequest(keysToFetch: [CNContactFormatter.descriptorForRequiredKeys(for: CNContactFormatterStyle.fullName), CNContactEmailAddressesKey as CNKeyDescriptor, CNContactImageDataKey as CNKeyDescriptor, CNContactThumbnailImageDataKey as CNKeyDescriptor]), usingBlock: { + ( c: CNContact, stop) -> Void in // print(c) - for email in c.emailAddresses { - let addr = email.value as String - var type : UIImage? = nil - if c.emailAddresses.count > 1 { - if email.label == "_$!<Work>!$_"{ - type = UIImage(named: "work2_white")! - } - else if email.label == "_$!<Home>!$_"{ + for email in c.emailAddresses { + let addr = email.value as String + var type: UIImage? = nil + if c.emailAddresses.count > 1 { + if email.label == "_$!<Work>!$_" { + type = UIImage(named: "work2_white")! + } + else if email.label == "_$!<Home>!$_" { type = UIImage(named: "home2_white")! - } - else if email.label == "_$!<iCloud>!$_"{ - //TODO: appleIcon hinzufügen - } } - var color = c.getColor() - if c.thumbnailImageData != nil { - color = UIColor.gray //blackColor() + else if email.label == "_$!<iCloud>!$_" { + //TODO: appleIcon hinzufügen } - if addr == "" { - continue + } + var color = c.getColor() + if c.thumbnailImageData != nil { + color = UIColor.gray //blackColor() + } + if addr == "" { + continue + } + if !inserted.contains(addr.lowercased()) { + if let name = CNContactFormatter.string(from: c, style: .fullName) { + cons.append((c.getImageOrDefault(), name, addr, type, color)) } - if !inserted.contains(addr.lowercased()) { - if let name = CNContactFormatter.string(from: c, style: .fullName) { - cons.append((c.getImageOrDefault(), name, addr, type, color)) - } else { cons.append((c.getImageOrDefault(), "NO NAME", addr, type, color)) - } } } - }) - } - catch {} - var list: [(UIImage,String,String,UIImage?,UIColor)] = [] + } + }) + } + catch { } + var list: [(UIImage, String, String, UIImage?, UIColor)] = [] var entrys = CollectionDataDelegate.maxFrequent if cons.count < entrys { entrys = cons.count @@ -63,24 +63,24 @@ class AddressHandler { if entrys <= 0 { return [] } - for i in 0...entrys-1 { + for i in 0...entrys - 1 { //let index = abs(Int(arc4random())) % cons.count let index = i % cons.count list.append(cons[index]) cons.remove(at: index) } - + return list } - + static var freqAlgorithm2: ([String]) -> [(UIImage, String, String, UIImage?, UIColor)] = { - (inserted : [String]) -> [(UIImage, String, String, UIImage?, UIColor)] in - + (inserted: [String]) -> [(UIImage, String, String, UIImage?, UIColor)] in + // var cons = DataHandler.handler.contacts var cons = DataHandler.handler.receiverRecords - var list: [(UIImage,String,String,UIImage?,UIColor)] = [] + var list: [(UIImage, String, String, UIImage?, UIColor)] = [] var localInserted = inserted - + for con: KeyRecord in cons { if list.count >= CollectionDataDelegate.maxFrequent { break @@ -98,31 +98,28 @@ class AddressHandler { if !insertedEntry { if let cn = con.cnContact { var addrType: UIImage? = nil - + if address.label.label == "_$!<Work>!$_" { addrType = UIImage(named: "work2_white")! } if address.label.label == "_$!<Home>!$_" { addrType = UIImage(named: "home2_white")! } - + var color = cn.getColor() if cn.thumbnailImageData != nil { color = UIColor.gray //blackColor() } - + //TODO: Add Image in EnzevalosContact var entry = (cn.getImageOrDefault(), con.ezContact.displayname!, address.mailAddress, addrType, color) - + list.append(entry) localInserted.append(address.mailAddress) } } } - - - - + /*var entrys = CollectionDataDelegate.maxFrequent if cons.count < entrys { entrys = cons.count @@ -136,19 +133,19 @@ class AddressHandler { list.append(cons[index]) cons.remove(at: index) }*/ - + return list } - + static func proveAddress(_ s: NSString) -> Bool { - if addresses.contains((s as String).lowercased()){ + if addresses.contains((s as String).lowercased()) { return true } return EnzevalosEncryptionHandler.hasKey(DataHandler.handler.getContactByAddress((s as String).lowercased())) } - - static func inContacts(_ name: String) -> Bool{ - AppDelegate.getAppDelegate().requestForAccess({access in }) + + static func inContacts(_ name: String) -> Bool { + AppDelegate.getAppDelegate().requestForAccess({ access in }) let authorizationStatus = CNContactStore.authorizationStatus(for: CNEntityType.contacts) if authorizationStatus == CNAuthorizationStatus.authorized { do { @@ -156,8 +153,8 @@ class AddressHandler { for con in conList { print(con.givenName) print(con.familyName) - - if (con.givenName+con.familyName).replacingOccurrences(of: " ", with: "") == name.replacingOccurrences(of: " ", with: ""){ + + if (con.givenName + con.familyName).replacingOccurrences(of: " ", with: "") == name.replacingOccurrences(of: " ", with: "") { return true } } @@ -165,18 +162,15 @@ class AddressHandler { catch { print("exception") } - } - else { + } else { print("no Access!") } return false } - - - - - static func getContact(_ name: String) -> [CNContact]{ - AppDelegate.getAppDelegate().requestForAccess({access in}) + + + static func getContact(_ name: String) -> [CNContact] { + AppDelegate.getAppDelegate().requestForAccess({ access in }) let authorizationStatus = CNContactStore.authorizationStatus(for: CNEntityType.contacts) if authorizationStatus == CNAuthorizationStatus.authorized { do { @@ -187,16 +181,15 @@ class AddressHandler { print("exception") } print("contacts done") - } - else { + } else { print("no Access!") } return [] } - - - static func getContactByID(_ identifier: String) -> [CNContact]{ - AppDelegate.getAppDelegate().requestForAccess({access in}) + + + static func getContactByID(_ identifier: String) -> [CNContact] { + AppDelegate.getAppDelegate().requestForAccess({ access in }) let ids = [identifier] let authorizationStatus = CNContactStore.authorizationStatus(for: CNEntityType.contacts) if authorizationStatus == CNAuthorizationStatus.authorized { @@ -208,8 +201,7 @@ class AddressHandler { print("exception") } print("contacts done") - } - else { + } else { print("no Access!") } return [] @@ -219,23 +211,23 @@ class AddressHandler { static func frequentAddresses (_ inserted: [String]) -> [(UIImage, String, String, UIImage?, UIColor)] { return freqAlgorithm2(inserted) } - - static func findContact(_ econtact: EnzevalosContact)-> [CNContact]{ + + static func findContact(_ econtact: EnzevalosContact) -> [CNContact] { var result = [CNContact]() if let identifier = econtact.cnidentifier { // 1. Look up identifier string result = getContactByID(identifier) } - if result.count == 0{ - if let name = econtact.displayname{ + 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())){ + for res in query { + if (proveMatching(res, addresses: econtact.getMailAddresses())) { result.append(res) } } - + } } if result.count == 0 { @@ -244,45 +236,43 @@ class AddressHandler { } return result } - - - static func proveMatching(_ result: CNContact, addresses: [MailAddress])-> Bool{ + + static func proveMatching(_ result: CNContact, addresses: [MailAddress]) -> Bool { var match: Bool = false - for email in result.emailAddresses{ - for adr in addresses{ + for email in result.emailAddresses { + for adr in addresses { let adrRest = email.value as String if adrRest.lowercased() == adr.mailAddress.lowercased() { match = true break } } - if match{ + if match { break } } return match } - - + static func contactByEmail(_ mailaddreses: [MailAddress]) -> [CNContact] { var contacts: [CNContact] = [] let predicate = NSPredicate { (evaluatedObject, bindings) -> Bool in guard let evaluatedContact = evaluatedObject as? CNContact else { - return false + return false } var exists: Bool exists = false - for adr in mailaddreses{ - let contains = Set(evaluatedContact.emailAddresses.map{$0.identifier}).contains(adr.mailAddress) + for adr in mailaddreses { + let contains = Set(evaluatedContact.emailAddresses.map { $0.identifier }).contains(adr.mailAddress) exists = (exists || contains) } return exists } - do{ + do { try contacts = AppDelegate.getAppDelegate().contactStore.unifiedContacts(matching: predicate, keysToFetch: [CNContactFormatter.descriptorForRequiredKeys(for: CNContactFormatterStyle.fullName), CNContactEmailAddressesKey as CNKeyDescriptor, CNContactImageDataKey as CNKeyDescriptor, CNContactThumbnailImageDataKey as CNKeyDescriptor]) } - catch {} + catch { } return contacts } } diff --git a/enzevalos_iphone/AppDelegate.swift b/enzevalos_iphone/AppDelegate.swift index a1824bbd5e9dd8fd8b651077de88c461250769b7..8c1dd4e494b40de0e5f1596a25edb17ada39d6f9 100644 --- a/enzevalos_iphone/AppDelegate.swift +++ b/enzevalos_iphone/AppDelegate.swift @@ -50,6 +50,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { Onboarding.manualSet = true self.window?.rootViewController = Onboarding.detailOnboarding(self.credentialCheck) } else { + Onboarding.manualSet = false let contr = (Onboarding.onboarding(self.credentialCheck) as! OnboardingViewController) self.window?.rootViewController = contr contr.gotoLastPage() @@ -76,11 +77,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate { if UserDefaults.standard.bool(forKey: "reset") { if UserManager.loadUserValue(Attribute.userAddr) as! String == "ullimuelle@web.de" { let mailhandler = MailHandler.init() - mailhandler.moveMails(mails: DataHandler.handler.mails, from: "INBOX", to: "ARCHIVE") + mailhandler.moveMails(mails: DataHandler.handler.mails, from: "INBOX", to: "Archive") } - - - DataHandler.handler.reset() Onboarding.credentials = nil Onboarding.credentialFails = 0 diff --git a/enzevalos_iphone/ContactViewController.swift b/enzevalos_iphone/ContactViewController.swift index 11004f618527a4a2e89ace533e16984a5de43957..ac85087595cbb57dbda98de21d27f2b8a0c3674d 100644 --- a/enzevalos_iphone/ContactViewController.swift +++ b/enzevalos_iphone/ContactViewController.swift @@ -147,7 +147,7 @@ class ContactViewController: UIViewController { tableView.selectRow(at: myPath, animated: false, scrollPosition: .none) performSegue(withIdentifier: "otherRecord", sender: nil) } else if (sender as? UIButton)?.titleLabel?.text == NSLocalizedString("invite", comment: "invite contact") { - let mail = EphemeralMail(to: NSSet.init(array: keyRecord!.addresses), cc: NSSet.init(), bcc: NSSet.init(), date: Date(), subject: NSLocalizedString("inviteSubject", comment: ""), body: NSLocalizedString("inviteText", comment: ""), uid: 0) + let mail = EphemeralMail(to: NSSet.init(array: keyRecord!.addresses), cc: NSSet.init(), bcc: NSSet.init(), date: Date(), subject: NSLocalizedString("inviteSubject", comment: ""), body: NSLocalizedString("inviteText", comment: ""), uid: 0,predecessor: nil) performSegue(withIdentifier: "newMail", sender: mail) } } diff --git a/enzevalos_iphone/EphemeralMail.swift b/enzevalos_iphone/EphemeralMail.swift index 846994e7072b47d8ed88a777b9dd19be16cb0326..0a8c2554216dd07ef9b4ea22aae3a14a561b5927 100644 --- a/enzevalos_iphone/EphemeralMail.swift +++ b/enzevalos_iphone/EphemeralMail.swift @@ -9,7 +9,7 @@ import Foundation open class EphemeralMail: Mail { - + public var cc: NSSet? public var bcc: NSSet? public var to: NSSet @@ -17,8 +17,9 @@ open class EphemeralMail: Mail { public var subject: String? public var body: String? public var uid: UInt64 + public var predecessor: PersistentMail? - public init(to: NSSet, cc: NSSet, bcc: NSSet, date: Date, subject: String?, body: String?, uid: UInt64) { //TODO: is casting cc and bcc necessary? + public init(to: NSSet, cc: NSSet, bcc: NSSet, date: Date, subject: String?, body: String?, uid: UInt64, predecessor: PersistentMail?) { //TODO: is casting cc and bcc necessary? self.cc = cc self.bcc = bcc self.to = to @@ -26,5 +27,6 @@ open class EphemeralMail: Mail { self.date = date self.subject = subject self.uid = uid + self.predecessor = predecessor } } diff --git a/enzevalos_iphone/Mail.swift b/enzevalos_iphone/Mail.swift index cd8dfd7bc97dc023c36ea595a015593ce2186f48..90b33b051524c56d42acc48b122667205cd861cd 100644 --- a/enzevalos_iphone/Mail.swift +++ b/enzevalos_iphone/Mail.swift @@ -18,6 +18,7 @@ public protocol Mail: Comparable { var subject: String? { get } var body: String? { get } var uid: UInt64 { get } + var predecessor: PersistentMail?{get} } public func == <T: Mail> (lhs: T, rhs: T) -> Bool { diff --git a/enzevalos_iphone/MailHandler.swift b/enzevalos_iphone/MailHandler.swift index df66d56d3da3792c6355ba6a0f4924d5910f8e7a..066fdb2cb2b1062ff591d1622c1ee215af48d4bc 100644 --- a/enzevalos_iphone/MailHandler.swift +++ b/enzevalos_iphone/MailHandler.swift @@ -276,7 +276,7 @@ class MailHandler { imapsession.port = UInt32(UserManager.loadUserValue(Attribute.imapPort) as! Int) imapsession.username = UserManager.loadUserValue(Attribute.userAddr) as! String imapsession.password = UserManager.loadUserValue(Attribute.userPW) as! String - imapsession.authType = MCOAuthType(rawValue: UserManager.loadUserValue(Attribute.imapAuthType) as! Int) //MCOAuthType.SASLPlain + imapsession.authType = UserManager.loadImapAuthType()//MCOAuthType(rawValue: UserManager.loadUserValue(Attribute.imapAuthType) as! Int) //MCOAuthType.SASLPlain imapsession.connectionType = MCOConnectionType(rawValue: UserManager.loadUserValue(Attribute.imapConnectionType) as! Int)//MCOConnectionType.TLS self.IMAPSes = imapsession } @@ -285,15 +285,13 @@ class MailHandler { let session = MCOSMTPSession() session.hostname = UserManager.loadUserValue(Attribute.smtpHostname) as! String session.port = UInt32(UserManager.loadUserValue(Attribute.smtpPort) as! Int) - session.username = (UserManager.loadUserValue(Attribute.userAddr) as! String) + session.username = UserManager.loadUserValue(Attribute.userAddr) as! String session.password = UserManager.loadUserValue(Attribute.userPW) as! String - session.authType = MCOAuthType(rawValue: UserManager.loadUserValue(Attribute.smtpAuthType) as! Int) + session.authType = UserManager.loadSmtpAuthType()//MCOAuthType(rawValue: UserManager.loadUserValue(Attribute.smtpAuthType) as! Int) session.connectionType = MCOConnectionType(rawValue: UserManager.loadUserValue(Attribute.smtpConnectionType) as! Int) return session } - - func addFlag(_ uid: UInt64, flags: MCOMessageFlag, folder: String = "INBOX") { let op = self.IMAPSession.storeFlagsOperation(withFolder: folder, uids: MCOIndexSet.init(index: uid), kind: MCOIMAPStoreFlagsRequestKind.set, flags: flags) op?.start { error -> Void in @@ -315,7 +313,6 @@ class MailHandler { } } - func receiveAll(_ folder: String = "INBOX", newMailCallback: @escaping (() -> ()), completionCallback: @escaping ((_ error: Bool) -> ())) { var uids: MCOIndexSet uids = MCOIndexSet(range: MCORangeMake(1, UINT64_MAX)) // DataHandler.handler.maxUID @@ -549,7 +546,7 @@ class MailHandler { } func checkSMTP(_ completion: @escaping (Error?) -> Void) { - let useraddr = (UserManager.loadUserValue(Attribute.userAddr) as! String) + let useraddr = UserManager.loadUserValue(Attribute.userAddr) as! String let username = UserManager.loadUserValue(Attribute.userName) as! String let session = MCOSMTPSession() @@ -557,7 +554,7 @@ class MailHandler { session.port = UInt32(UserManager.loadUserValue(Attribute.smtpPort) as! Int) session.username = username session.password = UserManager.loadUserValue(Attribute.userPW) as! String - session.authType = MCOAuthType.init(rawValue: UserManager.loadUserValue(Attribute.smtpAuthType) as! Int)//MCOAuthType.SASLPlain + session.authType = UserManager.loadSmtpAuthType()//MCOAuthType.init(rawValue: UserManager.loadUserValue(Attribute.smtpAuthType) as! Int)//MCOAuthType.SASLPlain session.connectionType = MCOConnectionType.init(rawValue: UserManager.loadUserValue(Attribute.smtpConnectionType) as! Int)//MCOConnectionType.StartTLS session.checkAccountOperationWith(from: MCOAddress.init(mailbox: useraddr)).start(completion) @@ -567,8 +564,8 @@ class MailHandler { func checkIMAP(_ completion: @escaping (Error?) -> Void) { self.setupIMAPSession() - self.IMAPSession.checkAccountOperation().start(completion/* as! (Error?) -> Void*/) - self.IMAPSession.connectOperation().start(completion/* as! (Error?) -> Void*/) + self.IMAPSes?.checkAccountOperation().start(completion/* as! (Error?) -> Void*/) + //self.IMAPSession.connectOperation().start(completion/* as! (Error?) -> Void*/) } func moveMails(mails: [PersistentMail], from: String, to: String) { diff --git a/enzevalos_iphone/Onboarding.swift b/enzevalos_iphone/Onboarding.swift index 4fc3b0f4616df5c5a77af64cf50f46b2c61acbfc..e23b1d663ec6cec14b2c7e5101f859f2eab7ed8b 100644 --- a/enzevalos_iphone/Onboarding.swift +++ b/enzevalos_iphone/Onboarding.swift @@ -50,7 +50,7 @@ class Onboarding: NSObject { static var credentialFails = 0 - static var authenticationRows: [Int: String] = [MCOAuthType.saslLogin.rawValue: "Login", MCOAuthType.saslPlain.rawValue: NSLocalizedString("NormalPassword", comment: ""), MCOAuthType.SASLSRP.rawValue: "SRP", MCOAuthType.SASLCRAMMD5.rawValue: "CRAMMD5", MCOAuthType.SASLDIGESTMD5.rawValue: "DIGESTMD5", MCOAuthType.SASLNTLM.rawValue: "NTLM", MCOAuthType.SASLGSSAPI.rawValue: "GSSAPI", MCOAuthType.saslKerberosV4.rawValue: "KerberosV4"] + static var authenticationRows: [Int: String] = [MCOAuthType.saslLogin.rawValue: "Login", MCOAuthType.saslPlain.rawValue: NSLocalizedString("NormalPassword", comment: ""), MCOAuthType.SASLSRP.rawValue: "SRP", MCOAuthType.SASLCRAMMD5.rawValue: "CRAMMD5", MCOAuthType.SASLDIGESTMD5.rawValue: "DIGESTMD5", MCOAuthType.SASLNTLM.rawValue: "NTLM", MCOAuthType.SASLGSSAPI.rawValue: "GSSAPI", MCOAuthType.saslKerberosV4.rawValue: "KerberosV4", 0: "None"] static var transportRows: [Int: String] = [MCOConnectionType.clear.rawValue: NSLocalizedString("Plaintext", comment: ""), MCOConnectionType.startTLS.rawValue: "StartTLS", MCOConnectionType.TLS.rawValue: "TLS"] static func onboarding(_ callback: @escaping () -> ()) -> UIViewController { @@ -480,6 +480,7 @@ class Onboarding: NSObject { static func imapCompletion(_ error: Error?) { //FIXME: vorher NSError? Mit Error? immer noch gültig? imapCheckDone = true imapCheck = error == nil + print(error) if imapCheck { AppDelegate.getAppDelegate().mailHandler.checkSMTP(smtpCompletion) return @@ -502,9 +503,18 @@ class Onboarding: NSObject { if let mailAddress = mailaddress.text?.lowercased().trimmingCharacters(in: .whitespacesAndNewlines), !manualSet && mailAddress != "" { let guessedUserName = mailAddress.components(separatedBy: "@")[0] UserManager.storeUserValue(guessedUserName as AnyObject?, attribute: Attribute.userName) - /*if mailAddress.contains("@") { - let provider = mailAddress.components(separatedBy: "@")[1] - }*/ + if mailAddress.contains("@gmail") || mailAddress.contains("@googlemail") { + UserManager.storeUserValue(mailAddress as AnyObject?, attribute: Attribute.userName) + } + else if mailAddress.contains("@gmx") { + UserManager.storeUserValue(mailAddress as AnyObject?, attribute: Attribute.userName) + } + else if mailAddress.contains("@posteo") { + UserManager.storeUserValue(mailAddress as AnyObject?, attribute: Attribute.userName) + } + else if mailAddress.contains("@aol.com") || mailAddress.contains("@games.com") || mailAddress.contains("@love.com") { + UserManager.storeUserValue(mailAddress as AnyObject?, attribute: Attribute.userName) + } setServerValues(mailaddress: mailAddress) UserManager.storeUserValue(mailAddress as AnyObject?, attribute: Attribute.userAddr) @@ -550,7 +560,7 @@ class Onboarding: NSObject { UserManager.storeUserValue(password.text! as AnyObject?, attribute: Attribute.userPW) UserManager.storeUserValue(username.text! as AnyObject?, attribute: Attribute.userName) UserManager.storeUserValue(username.text! as AnyObject?, attribute: Attribute.accountname) - UserManager.storeUserValue(keyForValue(transportRows, value: imapTransDataDelegate.pickedValue)[0] as AnyObject?, attribute: Attribute.imapConnectionType) //TODO: fatal error: Index out of range when reset button was used + UserManager.storeUserValue(keyForValue(transportRows, value: imapTransDataDelegate.pickedValue)[0] as AnyObject?, attribute: Attribute.imapConnectionType) UserManager.storeUserValue(keyForValue(authenticationRows, value: imapAuthDataDelegate.pickedValue)[0] as AnyObject?, attribute: Attribute.imapAuthType) UserManager.storeUserValue(keyForValue(transportRows, value: smtpTransDataDelegate.pickedValue)[0] as AnyObject?, attribute: Attribute.smtpConnectionType) UserManager.storeUserValue(keyForValue(authenticationRows, value: smtpAuthDataDelegate.pickedValue)[0] as AnyObject?, attribute: Attribute.smtpAuthType) @@ -606,7 +616,7 @@ class Onboarding: NSObject { } else if let auth = imapService.info()["auth"] as? String, auth == "xoAuth2Outlook" { UserManager.storeUserValue(MCOAuthType.SASLCRAMMD5.rawValue as AnyObject?, attribute: Attribute.imapAuthType) } else { - UserManager.storeUserValue(MCOAuthType.saslPlain.rawValue as AnyObject?, attribute: Attribute.imapAuthType) + UserManager.storeUserValue(0 as AnyObject?, attribute: Attribute.imapAuthType) } let smtpService = smtp[0] @@ -642,7 +652,7 @@ class Onboarding: NSObject { } else if let auth = smtpService.info()["auth"] as? String, auth == "xoAuth2Outlook" { UserManager.storeUserValue(MCOAuthType.SASLCRAMMD5.rawValue as AnyObject?, attribute: Attribute.smtpAuthType) } else { - UserManager.storeUserValue(MCOAuthType.saslPlain.rawValue as AnyObject?, attribute: Attribute.smtpAuthType) + UserManager.storeUserValue(0 as AnyObject?, attribute: Attribute.smtpAuthType) } } } diff --git a/enzevalos_iphone/PGPEncryption.swift b/enzevalos_iphone/PGPEncryption.swift index 6f0ce32ce37f7af03c417daa1619e567778d4d39..862f8bcc11392262106201ee2e83bb86825b7ed4 100644 --- a/enzevalos_iphone/PGPEncryption.swift +++ b/enzevalos_iphone/PGPEncryption.swift @@ -53,7 +53,7 @@ class PGPEncryption : Encryption { //check whether this encryption is used in this text for encryption. the key is not known to be used. nil is returned, if there is no answer to be made at the moment. //key unused func isUsedForEncryption(_ text: String, key: KeyWrapper?) -> Bool?{ - return text.hasPrefix("-----BEGIN PGP MESSAGE-----") && (text.hasSuffix("-----END PGP MESSAGE-----\n") || text.hasSuffix("-----END PGP MESSAGE-----")) + return getCipher(text: text) != "" //text.hasPrefix("-----BEGIN PGP MESSAGE-----") && (text.hasSuffix("-----END PGP MESSAGE-----\n") || text.hasSuffix("-----END PGP MESSAGE-----")) } //check whether this encryption is used in this mail for signing. nil is returned, if there is no answer to be made at the moment. @@ -174,7 +174,8 @@ class PGPEncryption : Encryption { //decrypt the mails body. the decryted body will be saved in the mail object. func decrypt(_ mail: PersistentMail)-> String?{ if self.isUsed(mail) { - let bodyData = mail.body!.data(using: String.Encoding.utf8)! + //let bodyData = mail.body!.data(using: String.Encoding.utf8)! + let bodyData = getCipher(text: mail.body!).data(using: String.Encoding.utf8)! var data = try? keyManager.pgp.decryptData(bodyData, passphrase: nil) if data == nil { self.keyManager.useAllPrivateKeys() @@ -215,7 +216,8 @@ class PGPEncryption : Encryption { func decryptAndSignatureCheck(_ mail: PersistentMail) { if self.isUsed(mail) { - let bodyData = mail.body!.data(using: String.Encoding.utf8)! + //let bodyData = mail.body!.data(using: String.Encoding.utf8)! + let bodyData = getCipher(text: mail.body!).data(using: String.Encoding.utf8)! var data: Data? //has to be var because it is given as pointer to obj-c-code var error: NSErrorPointer = NSErrorPointer.none @@ -577,6 +579,20 @@ class PGPEncryption : Encryption { return nil } + //TODO: Add for signature only + func getCipher(text: String) -> String { + var range = text.range(of: "-----BEGIN PGP MESSAGE-----") + if let lower = range?.lowerBound { + range = text.range(of: "-----END PGP MESSAGE-----") + if let upper = range?.upperBound { + let retValue = text.substring(to: upper).substring(from: lower) + return retValue + } + } + return "" + } + + func autocryptHeader(_ adr: String) -> String? { if let keyId = self.getActualKeyID(adr){ let key = self.getKey(keyId) as! PGPKeyWrapper diff --git a/enzevalos_iphone/ReadViewController.swift b/enzevalos_iphone/ReadViewController.swift index 066be366601f6bb7bf710cccacd76f73b7f8cb64..2af286bbae8100ef2ef9ee960f56af0c135a0cdf 100644 --- a/enzevalos_iphone/ReadViewController.swift +++ b/enzevalos_iphone/ReadViewController.swift @@ -369,7 +369,11 @@ class ReadViewController: UITableViewController { var answerCC = [Mail_Address]() var body = NSLocalizedString("mail from", comment: "describing who send the mail") + " " body.append(mail!.from.mailAddress) - body.append(" " + NSLocalizedString("sent at", comment: "describing when the mail was send") + " " + mail!.timeString) + let time = DateFormatter.init() + time.dateStyle = .short + time.timeStyle = .short + time.locale = Locale.current + body.append(" " + NSLocalizedString("sent at", comment: "describing when the mail was send") + " " + time.string(from: mail!.date)) body.append("\n" + NSLocalizedString("To", comment: "describing adressee") + ": ") let myAddress = UserManager.loadUserValue(Attribute.userAddr) as! String if mail!.to.count > 0 { @@ -408,7 +412,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) + 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 } diff --git a/enzevalos_iphone/SendViewController.swift b/enzevalos_iphone/SendViewController.swift index 4d969a7538098e1a0a4782ec056f9c69d15cf6f6..bf1347548cee82282183bc262e7a0b44b4bf94e0 100644 --- a/enzevalos_iphone/SendViewController.swift +++ b/enzevalos_iphone/SendViewController.swift @@ -243,7 +243,7 @@ class SendViewController: UIViewController { } } - let mail = EphemeralMail(to: NSSet.init(array: to), cc: NSSet.init(array: cc), bcc: NSSet.init(), date: Date(), subject: NSLocalizedString("inviteSubject", comment: "Subject for the invitation mail"), body: NSLocalizedString("inviteText", comment: "Body for the invitation mail"), uid: 0) + let mail = EphemeralMail(to: NSSet.init(array: to), cc: NSSet.init(array: cc), bcc: NSSet.init(), date: Date(), subject: NSLocalizedString("inviteSubject", comment: "Subject for the invitation mail"), body: NSLocalizedString("inviteText", comment: "Body for the invitation mail"), uid: 0,predecessor: nil) controller.prefilledMail = mail @@ -257,11 +257,17 @@ class SendViewController: UIViewController { LogHandler.doLog(UIViewResolver.resolve(tokenField.tag), interaction: "changeText", point: CGPoint(x: 0, y: 0), comment: inText) } if inText != "" { - scrollview.isScrollEnabled = false - scrollview.contentOffset = CGPoint(x: 0, y: tokenField.frame.origin.y - self.topLayoutGuide.length) - tableviewBegin.constant = tokenField.frame.maxY - tokenField.frame.origin.y - tableviewHeight.constant = keyboardY - tableviewBegin.constant - (self.navigationController?.navigationBar.frame.maxY)! searchContacts(inText) + if tableDataDelegate.contacts != [] { + scrollview.isScrollEnabled = false + scrollview.contentOffset = CGPoint(x: 0, y: tokenField.frame.origin.y - self.topLayoutGuide.length) + tableviewBegin.constant = tokenField.frame.maxY - tokenField.frame.origin.y + tableviewHeight.constant = keyboardY - tableviewBegin.constant - (self.navigationController?.navigationBar.frame.maxY)! + } + else { + scrollview.isScrollEnabled = true + tableviewHeight.constant = 0 + } } else { scrollview.isScrollEnabled = true tableviewHeight.constant = 0 @@ -373,7 +379,9 @@ class SendViewController: UIViewController { } else { NSLog("Send successful!") if (self.prefilledMail != nil) { - AppDelegate.getAppDelegate().mailHandler.addFlag((self.prefilledMail?.uid)!, flags: MCOMessageFlag.answered) + if self.prefilledMail?.predecessor != nil { + self.prefilledMail?.predecessor?.isAnwered = true + } } self.sendCompleted() } diff --git a/enzevalos_iphone/UserData.swift b/enzevalos_iphone/UserData.swift index 68d0b1b98d24e36bee7d6e2ab138c6af6201f1b0..6a1939eda8182e6bb09e482953b122a35f2af969 100644 --- a/enzevalos_iphone/UserData.swift +++ b/enzevalos_iphone/UserData.swift @@ -56,12 +56,12 @@ enum Attribute: Int{ struct UserManager{ static func storeUserValue(_ value: AnyObject?, attribute: Attribute) { - UserDefaults.standard.setValue(value, forKey: "\(attribute.hashValue)") + UserDefaults.standard.set(value, forKey: "\(attribute.rawValue)") UserDefaults.standard.synchronize() } static func loadUserValue(_ attribute: Attribute) -> AnyObject?{ - let value = UserDefaults.standard.value(forKey: "\(attribute.hashValue)") + let value = UserDefaults.standard.value(forKey: "\(attribute.rawValue)") if((value) != nil){ return value as AnyObject? } @@ -72,6 +72,20 @@ struct UserManager{ } } + static func loadImapAuthType() -> MCOAuthType { + if let auth = UserManager.loadUserValue(Attribute.imapAuthType) as? Int, auth != 0 { + return MCOAuthType.init(rawValue: auth) + } + return [] + } + + static func loadSmtpAuthType() -> MCOAuthType { + if let auth = UserManager.loadUserValue(Attribute.smtpAuthType) as? Int, auth != 0 { + return MCOAuthType.init(rawValue: auth) + } + return [] + } + static func resetUserValues(){ for a in Attribute.allAttributes { storeUserValue(a.defaultValue, attribute: a) diff --git a/enzevalos_iphone/de.lproj/Localizable.strings b/enzevalos_iphone/de.lproj/Localizable.strings index e661cdb0a434146a5e193e7d2f49881b7a2f7aa0..31c2e84456d4236a86096ede84d2c196e279d474 100644 --- a/enzevalos_iphone/de.lproj/Localizable.strings +++ b/enzevalos_iphone/de.lproj/Localizable.strings @@ -27,7 +27,7 @@ "DiscoveryTime" = "Bekannt seit"; "Checkmarks" = "Du hast Nachrichten von den Adressen mit Haken bekommen"; "Drafts" = "Entwürfe"; -"Emailaddress" = "E-Mail-adresse"; +"Emailaddress" = "E-Mail-Adresse"; "EncryptionType" = "Verschlüsselungsart"; "EverythingCorrect" = "Alles richtig?"; "Forward" = "Weiterleiten"; @@ -40,7 +40,7 @@ "InsertMailAddress" = "Bitte gib deine E-Mail-Adresse ein"; "InsertMailAddressAndPassword" = "Bitte gib deine E-Mail-Adresse und dein Passwort ein"; "InsertPassword" = "Bitte gib\ndein Passwort ein"; -"InsertUSername" = "Bitte gib deinen Nutzernamen ein"; +"InsertUsername" = "Bitte gib deinen Nutzernamen ein"; "InterestedInSecureMail" = "Schön, dass du dich für sichere E-Mail interessierst!"; "Junk" = "Spam"; "KeyAddresses" = "Mailadressen im Schlüssel"; @@ -49,10 +49,9 @@ "KeyIsRevoked" = "Der Schlüssel ist zurückgezogen. Zurückgezogen wurde er am "; "KeyIsVerified" = "Der Schlüssel ist verifiziert. Verifiziert wurde er am "; "KeyNotFound" = "Schlüssel konnte nicht gefunden werden. Dies ist ein Fehler, bitte wende dich an die Entwickler!"; -"KeyIsVerified" = "Der Schlüssel ist verifiziert. Verifiziert wurde er am "; "Letter" = "Brief"; "LetterDamaged" = "Angerissener Brief"; -"LetterDescription" = "• Eine vertrauliche E-Mail\n• Sie stammt tatsächlich vom angegebenen Absender\n• Benötigt Beteiligung von Sender und Empfänger. Dafür besteht in der App die Möglichkeit Kontakte einzuladen."; +"LetterDescription" = "• Das ist eine sichere E-Mail\n• Sie stammt tatsächlich vom angegebenen Absender\n• Nur Empfänger und Sender können die Nachricht lesen.\n• Benötigt Beteiligung von Sender und Empfänger. Dafür können in der App Kontakte eingeladen werden."; "mail from" = "Nachricht von"; "Message" = "Nachricht"; "MoreInformation" = "Mehr Informationen"; @@ -67,7 +66,7 @@ "Postcard" = "Postkarte"; "PostcardDescription" = "• Eine E-Mail, wie du sie bisher kennst\n• Weder vertraulich, noch steht fest, ob sie gefälscht wurde\n• Von jedem lesbar und veränderbar"; "Re" = "AW"; -"ReadFollowingPages" = "Wir wollen sichere E-Mail einfach nutzbar zu machen.\nDafür lies dir bitte die kommenden drei Seiten durch."; +"ReadFollowingPages" = "Wir wollen sichere E-Mail einfach nutzbar machen.\nDafür lies dir bitte die kommenden drei Seiten durch."; "Receive" = "Empfangen"; "ReceiveError" = "Ein Fehler ist aufgetreten"; //mehr spezifizieren? "ReceiveDamagedInfo" = "Mit dieser Nachricht stimmt was nicht. Der Inhalt könnte kompromitiert oder manipuliert sein."; @@ -109,7 +108,7 @@ "notVerified" = "Kontakt ist noch nicht verifiziert"; "noEncryption" = "Kontakt nutzt noch keine Verschlüsselung"; "otherEncryption" = "Dies ist die unsichere Ablage dieses Kontakt"; -"hasKeyButNoMail" = "Kontakt nutzt verschlüsselung, hat dir aber noch keine sichere E-Mail gesendet"; +"hasKeyButNoMail" = "Kontakt nutzt Verschlüsselung, hat dir aber noch keine sichere E-Mail gesendet"; "Verified" = "Kontakt ist verifiziert"; "verifyNow" = "Jetzt verifizieren"; "toEncrypted" = "Zur sicheren Ablage"; diff --git a/enzevalos_iphone/providers.json b/enzevalos_iphone/providers.json index 22e88b1986496d368e72243fbbf94ca29ffc7d91..82b66529e6b8443cf5124d924c0f906f506ddea7 100644 --- a/enzevalos_iphone/providers.json +++ b/enzevalos_iphone/providers.json @@ -106,15 +106,179 @@ ] }, "domain-match":[ - "aol\\.com", - "aol" + "aol.com", + "aol", + "games", + "games.com", + "love", + "love.com" ], "mx-match": [ "aol", "aol.com", - "" + "games", + "games.com", + "love", + "love.com" + ] + }, + "gmail":{ + "servers":{ + "imap":[ + { + "port":993, + "hostname":"imap.gmail.com", + "ssl":true, + "auth":"saslPlain" + } + ], + "smtp":[ + { + "port":587, + "hostname":"smtp.gmail.com", + "starttls":true, + "auth":"saslPlain" + } + ] + }, + "domain-match":[ + "googlemail.com", + "googlemail", + "gmail.com", + "gmail" + ], + "mx-match": [ + "googlemail.com", + "googlemail", + "gmail.com", + "gmail" + ] + }, + "arcor":{ + "servers":{ + "imap":[ + { + "port":993, + "hostname":"imap.gmail.com", + "ssl":true, + "auth":"saslPlain" + } + ], + "smtp":[ + { + "port":587, + "hostname":"smtp.gmail.com", + "starttls":true, + "auth":"saslPlain" + } + ] + }, + "domain-match":[ + "googlemail.com", + "googlemail", + "gmail.com", + "gmail" + ], + "mx-match": [ + "googlemail.com", + "googlemail", + "gmail.com", + "gmail" + ] + }, + "gmx":{ + "servers":{ + "imap":[ + { + "port":993, + "hostname":"imap.gmx.net", + "ssl":true, + "auth":"saslPlain" + } + ], + "smtp":[ + { + "port":587, + "hostname":"mail.gmx.net", + "starttls":true, + "auth":"saslPlain" + } + ] + }, + "domain-match":[ + "gmx.net", + "gmx", + "gmx.de" + ], + "mx-match": [ + "gmx.net", + "gmx", + "gmx.de" + ] + }, + "posteo":{ + "servers":{ + "imap":[ + { + "port":143, + "hostname":"posteo.de", + "starttls":true, + "auth":"saslPlain" + } + ], + "smtp":[ + { + "port":587, + "hostname":"posteo.de", + "starttls":true, + "auth":"saslPlain" + } + ] + }, + "domain-match":[ + "posteo.de", + "posteo.net", + "posteo" + ], + "mx-match": [ + "posteo.de", + "posteo.net", + "posteo" + ] + }, + "outlook.com":{ + "servers":{ + "imap":[ + { + "port":993, + "hostname":"imap-mail.outlook.com", + "ssl":true, + "auth":"saslPlain" + } + ], + "smtp":[ + { + "port":587, + "hostname":"smtp-mail.outlook.com", + "starttls":true, + "auth":"saslPlain" + } + ] + }, + "domain-match":[ + "outlook.com", + "outlook.de", + "outlook", + "hotmail.com", + "hotmail" + ], + "mx-match": [ + "outlook.com", + "outlook.de", + "outlook", + "hotmail.com", + "hotmail" ] } - }