IOS-222 Merge IOS-230 into default.
authorDirk Zimmermann <dirk@pep-project.org>
Tue, 25 Oct 2016 14:33:41 +0200
changeset 874b075d5de7688
parent 873 1132b77d9cb4
parent 870 dd67c28b7449
child 875 2d838667f585
IOS-222 Merge IOS-230 into default.
pEpForiOS.xcodeproj/project.pbxproj
pEpForiOS/UI/AccountsAndFolders/AccountsFoldersTableViewController.swift
pEpForiOS/UI/ImapSetup/SMTPSettingsTableView.swift
     1.1 --- a/pEpForiOS.xcodeproj/project.pbxproj	Tue Oct 25 12:59:55 2016 +0200
     1.2 +++ b/pEpForiOS.xcodeproj/project.pbxproj	Tue Oct 25 14:33:41 2016 +0200
     1.3 @@ -56,6 +56,7 @@
     1.4  		434FF7191DB74781008F1724 /* Transport+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 434FF7181DB74781008F1724 /* Transport+Extension.swift */; };
     1.5  		435B42411D211E5900119048 /* MiscUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 435B42401D211E5900119048 /* MiscUtil.swift */; };
     1.6  		4367E26F1CD7360000B05F83 /* CdModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4367E26E1CD7360000B05F83 /* CdModel.swift */; };
     1.7 +		436CB9711DBE178000682C85 /* Message+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 436CB9701DBE178000682C85 /* Message+Extension.swift */; };
     1.8  		436F8E101D367039007E9829 /* StringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 436F8E0F1D367039007E9829 /* StringExtensions.swift */; };
     1.9  		436F8E141D36706A007E9829 /* StringExtensionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 436F8E131D36706A007E9829 /* StringExtensionsTest.swift */; };
    1.10  		436F8E1B1D369B3F007E9829 /* EmailTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 436F8E1A1D369B3F007E9829 /* EmailTextField.swift */; };
    1.11 @@ -294,6 +295,7 @@
    1.12  		435B42401D211E5900119048 /* MiscUtil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MiscUtil.swift; sourceTree = "<group>"; };
    1.13  		4367E26E1CD7360000B05F83 /* CdModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CdModel.swift; sourceTree = "<group>"; };
    1.14  		436C5A8D1CFEDF59006A195F /* UIHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIHelper.swift; sourceTree = "<group>"; };
    1.15 +		436CB9701DBE178000682C85 /* Message+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Message+Extension.swift"; sourceTree = "<group>"; };
    1.16  		436F8E0F1D367039007E9829 /* StringExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringExtensions.swift; sourceTree = "<group>"; };
    1.17  		436F8E131D36706A007E9829 /* StringExtensionsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringExtensionsTest.swift; sourceTree = "<group>"; };
    1.18  		436F8E1A1D369B3F007E9829 /* EmailTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmailTextField.swift; sourceTree = "<group>"; };
    1.19 @@ -752,6 +754,7 @@
    1.20  		43E58EB21CBF8301008AA7A7 /* Models */ = {
    1.21  			isa = PBXGroup;
    1.22  			children = (
    1.23 +				436CB9701DBE178000682C85 /* Message+Extension.swift */,
    1.24  				434FF7181DB74781008F1724 /* Transport+Extension.swift */,
    1.25  				434FF7121DB73D73008F1724 /* Account+Extension.swift */,
    1.26  				4367E26E1CD7360000B05F83 /* CdModel.swift */,
    1.27 @@ -1124,6 +1127,7 @@
    1.28  				431B0B9A1D6734DF0082D0DB /* AccountsFoldersTableViewController.swift in Sources */,
    1.29  				43ED53701CC77F95006AB156 /* EmailListViewController.swift in Sources */,
    1.30  				4380F7C61D1BBD5D00326F62 /* EncryptMailOperation.swift in Sources */,
    1.31 +				436CB9711DBE178000682C85 /* Message+Extension.swift in Sources */,
    1.32  				4305AC7A1DA3FE8C00273D16 /* _CdContact.swift in Sources */,
    1.33  				A1BF165A1D351518005B98F0 /* LabelMailSecurityTableViewCell.swift in Sources */,
    1.34  				43E9BC721DB51D6700AD2352 /* CdAttachment+Extension.swift in Sources */,
     2.1 --- a/pEpForiOS/Background/MessageToAttachmentOperation.swift	Tue Oct 25 12:59:55 2016 +0200
     2.2 +++ b/pEpForiOS/Background/MessageToAttachmentOperation.swift	Tue Oct 25 14:33:41 2016 +0200
     2.3 @@ -12,55 +12,29 @@
     2.4  import MessageModel
     2.5  
     2.6  /**
     2.7 - Simple pojo for attachments.
     2.8 - */
     2.9 -public struct SimpleAttachment {
    2.10 -    let filename: String?
    2.11 -    let contentType: String?
    2.12 -    let data: Data?
    2.13 -    let image: UIImage?
    2.14 -}
    2.15 -
    2.16 -/**
    2.17   Converts a given Message to a (non-core-data) attachment object.
    2.18   */
    2.19 -open class MessageToAttachmentOperation: ConcurrentBaseOperation {
    2.20 +open class MessageToAttachmentOperation: BaseOperation {
    2.21      let comp = "MessageToAttachmentOperation"
    2.22  
    2.23 -    /** The core data objectID */
    2.24 -    let messageID: NSManagedObjectID
    2.25 +    let message: Message
    2.26  
    2.27 -    var attachment: SimpleAttachment?
    2.28 +    var attachment: Attachment?
    2.29  
    2.30 -    public init(message: CdMessage, coreDataUtil: CoreDataUtil) {
    2.31 -        self.messageID = message.objectID
    2.32 -        super.init(coreDataUtil: coreDataUtil)
    2.33 +    public init(message: Message) {
    2.34 +        self.message = message
    2.35      }
    2.36  
    2.37      open override func main() {
    2.38 -        let privateMOC = coreDataUtil.privateContext()
    2.39 -        privateMOC.perform() {
    2.40 -            self.doWork(privateMOC)
    2.41 -            self.markAsFinished()
    2.42 -        }
    2.43 -    }
    2.44 -
    2.45 -    func doWork(_ privateMOC: NSManagedObjectContext) {
    2.46 -        guard let message = privateMOC.object(with: self.messageID) as? CdMessage else {
    2.47 -            errorMessage(NSLocalizedString(
    2.48 -                "Could not find message by objectID", comment: "Internal error"),
    2.49 -                         logMessage: "Could not find message by objectID")
    2.50 -            return
    2.51 -        }
    2.52 -        let pantMail = PEPUtil.pantomimeMailFromMessage(message)
    2.53 +        let pantMail = PEPUtil.pantomimeMail(message: message)
    2.54          guard let data = pantMail.dataValue() else {
    2.55              errorMessage(NSLocalizedString(
    2.56                  "Could not get data from forwarded message", comment: "Internal error"),
    2.57                           logMessage: "Could not get data from forwarded message")
    2.58              return
    2.59          }
    2.60 -        attachment = SimpleAttachment.init(
    2.61 -            filename: "mail.eml", contentType: "message/rfc822", data: data , image: nil)
    2.62 +        attachment = Attachment.create(data: data, mimeType: Constants.attachedEmailMimeType,
    2.63 +                                       fileName: "mail.eml")
    2.64      }
    2.65  
    2.66      func errorMessage(_ localizedMessage: String, logMessage: String) {
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/pEpForiOS/Models/Message+Extension.swift	Tue Oct 25 14:33:41 2016 +0200
     3.3 @@ -0,0 +1,26 @@
     3.4 +//
     3.5 +//  Message+Extension.swift
     3.6 +//  pEpForiOS
     3.7 +//
     3.8 +//  Created by Dirk Zimmermann on 24/10/16.
     3.9 +//  Copyright © 2016 p≡p Security S.A. All rights reserved.
    3.10 +//
    3.11 +
    3.12 +import UIKit
    3.13 +
    3.14 +import MessageModel
    3.15 +
    3.16 +extension Message {
    3.17 +    var pEpRating: PEP_rating? {
    3.18 +        get {
    3.19 +            return PEPUtil.pEpRatingFromInt(pEpRatingInt)
    3.20 +        }
    3.21 +        set {
    3.22 +            if let nv = newValue {
    3.23 +                pEpRatingInt = Int(nv.rawValue)
    3.24 +            } else {
    3.25 +                pEpRatingInt = nil
    3.26 +            }
    3.27 +        }
    3.28 +    }
    3.29 +}
     4.1 --- a/pEpForiOS/UI/AccountsAndFolders/AccountsFoldersTableViewController.swift	Tue Oct 25 12:59:55 2016 +0200
     4.2 +++ b/pEpForiOS/UI/AccountsAndFolders/AccountsFoldersTableViewController.swift	Tue Oct 25 14:33:41 2016 +0200
     4.3 @@ -225,21 +225,10 @@
     4.4                  return
     4.5              }
     4.6              let account = accounts[(indexPath as NSIndexPath).row]
     4.7 -
     4.8 -            let predicateInbox = basicInboxPredicate()
     4.9 -            let predicateAccount = NSPredicate.init(
    4.10 -                format: "folder.account.email = %@", account.user.address)
    4.11 -            let predicates: [NSPredicate] = [predicateInbox, predicateAccount]
    4.12 -            let predicate = NSCompoundPredicate.init(
    4.13 -                andPredicateWithSubpredicates: predicates)
    4.14 -            let sortDescriptors = [NSSortDescriptor.init(key: "receivedDate",
    4.15 -                ascending: false)]
    4.16 +            let inbox = account.inbox()
    4.17  
    4.18              emailListConfig = EmailListViewController.EmailListConfig.init(
    4.19 -                appConfig: ac, predicate: predicate,
    4.20 -                sortDescriptors: sortDescriptors, account: account,
    4.21 -                folderName: ImapSync.defaultImapInboxName,
    4.22 -                syncOnAppear: false)
    4.23 +                appConfig: ac, account: account, folder: inbox)
    4.24  
    4.25              self.performSegue(withIdentifier: segueEmailList, sender: self)
    4.26          } else {
     5.1 --- a/pEpForiOS/UI/AccountsAndFolders/FolderListViewController.swift	Tue Oct 25 12:59:55 2016 +0200
     5.2 +++ b/pEpForiOS/UI/AccountsAndFolders/FolderListViewController.swift	Tue Oct 25 14:33:41 2016 +0200
     5.3 @@ -11,7 +11,9 @@
     5.4  
     5.5  import MessageModel
     5.6  
     5.7 -class FolderListViewController: FetchTableViewController {
     5.8 +class FolderListViewController: UITableViewController {
     5.9 +    let comp = "FolderListViewController"
    5.10 +
    5.11      struct FolderListConfig {
    5.12          let account: Account
    5.13          let appConfig: AppConfig
    5.14 @@ -33,20 +35,16 @@
    5.15  
    5.16      var state = UIState()
    5.17  
    5.18 +    var folders = [Folder]()
    5.19 +
    5.20      override func viewDidLoad() {
    5.21          super.viewDidLoad()
    5.22 -
    5.23          tableView.register(UITableViewCell.self, forCellReuseIdentifier: standardCell)
    5.24 -
    5.25 -        let refreshController = UIRefreshControl.init()
    5.26 -        refreshController.addTarget(self, action: #selector(self.refreshFoldersControl),
    5.27 -                                    for: UIControlEvents.valueChanged)
    5.28 -        self.refreshControl = refreshController
    5.29      }
    5.30  
    5.31      override func viewWillAppear(_ animated: Bool) {
    5.32          super.viewWillAppear(animated)
    5.33 -        prepareFetchRequest()
    5.34 +        updateModel()
    5.35      }
    5.36  
    5.37      override func didReceiveMemoryWarning() {
    5.38 @@ -54,44 +52,8 @@
    5.39          // Dispose of any resources that can be recreated.
    5.40      }
    5.41  
    5.42 -    func prepareFetchRequest() {
    5.43 -        let fetchRequest = NSFetchRequest<NSManagedObject>.init(entityName: CdFolder.entityName())
    5.44 -
    5.45 -        let predicateAccount = NSPredicate.init(
    5.46 -            format: "account.email = %@", config.account.user.address)
    5.47 -        let predicateNotDeleted = NSPredicate.init(
    5.48 -            format: "shouldDelete = false")
    5.49 -        let predicate = NSCompoundPredicate.init(
    5.50 -            andPredicateWithSubpredicates: [predicateAccount, predicateNotDeleted])
    5.51 -
    5.52 -        fetchRequest.predicate = predicate
    5.53 -        fetchRequest.sortDescriptors = [NSSortDescriptor.init(key: "name", ascending: true)]
    5.54 -        fetchController = NSFetchedResultsController.init(
    5.55 -            fetchRequest: fetchRequest,
    5.56 -            managedObjectContext: config.appConfig.coreDataUtil.managedObjectContext,
    5.57 -            sectionNameKeyPath: nil, cacheName: nil)
    5.58 -        fetchController?.delegate = self
    5.59 -        do {
    5.60 -            try fetchController?.performFetch()
    5.61 -        } catch let err as NSError {
    5.62 -            Log.errorComponent(comp, error: err)
    5.63 -        }
    5.64 -    }
    5.65 -
    5.66 -    func refreshFoldersControl(_ refreshControl: UIRefreshControl? = nil) {
    5.67 -        state.isUpdating = true
    5.68 -        updateUI()
    5.69 -        if let connectInfo = config.account.connectInfo {
    5.70 -            config.appConfig.grandOperator.fetchFolders(
    5.71 -                connectInfo, completionBlock: { error in
    5.72 -                    self.state.isUpdating = false
    5.73 -                    self.updateUI()
    5.74 -                    self.tableView.reloadData()
    5.75 -            })
    5.76 -        } else {
    5.77 -            Log.errorComponent(comp,
    5.78 -                               errorString: "No connectInfo for account \(config.account.user.address)")
    5.79 -        }
    5.80 +    func updateModel() {
    5.81 +        folders = config.account.rootFolders
    5.82      }
    5.83  
    5.84      func updateUI() {
    5.85 @@ -110,39 +72,30 @@
    5.86          return cell
    5.87      }
    5.88  
    5.89 -    override func configureCell(_ cell: UITableViewCell, indexPath: IndexPath) {
    5.90 -        if let folder = fetchController?.object(at: indexPath) as? CdFolder {
    5.91 -            cell.textLabel?.text = "\(folder.name)"
    5.92 -            cell.accessoryType = .disclosureIndicator
    5.93 -        }
    5.94 +    func configureCell(_ cell: UITableViewCell, indexPath: IndexPath) {
    5.95 +        let folder = folderAt(indexPath: indexPath)
    5.96 +        cell.textLabel?.text = "\(folder.name)"
    5.97 +        cell.accessoryType = .disclosureIndicator
    5.98      }
    5.99  
   5.100      override func tableView(_ tableView: UITableView,
   5.101                              canEditRowAt indexPath: IndexPath) -> Bool {
   5.102 -        if let folder = fetchController?.object(at: indexPath) as? CdFolder {
   5.103 -            switch folder.folderType.intValue {
   5.104 -            case FolderType.localOutbox.rawValue, FolderType.inbox.rawValue: return false
   5.105 -            default: return true
   5.106 -            }
   5.107 +        let folder = folderAt(indexPath: indexPath)
   5.108 +        switch folder.folderType {
   5.109 +        case FolderType.localOutbox, FolderType.inbox: return false
   5.110 +        default: return true
   5.111          }
   5.112 -        return false
   5.113      }
   5.114  
   5.115      override func tableView(
   5.116          _ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle,
   5.117          forRowAt indexPath: IndexPath) {
   5.118 -        if let folder = fetchController?.object(at: indexPath) as? CdFolder {
   5.119 -            folder.shouldDelete = true
   5.120 -            config.appConfig.model.save()
   5.121 -            state.isUpdating = true
   5.122 -            updateUI()
   5.123 +        let folder = folderAt(indexPath: indexPath)
   5.124 +        folder.delete()
   5.125 +    }
   5.126  
   5.127 -            config.appConfig.grandOperator.deleteFolder(folder as CdFolder) { error in
   5.128 -                UIHelper.displayError(error, controller: self)
   5.129 -                self.state.isUpdating = false
   5.130 -                self.updateUI()
   5.131 -            }
   5.132 -        }
   5.133 +    func folderAt(indexPath: IndexPath) -> Folder {
   5.134 +        return folders[indexPath.row]
   5.135      }
   5.136  
   5.137      // MARK: - Table view delegate
   5.138 @@ -150,47 +103,23 @@
   5.139      override func tableView(
   5.140          _ tableView: UITableView,
   5.141          indentationLevelForRowAt indexPath: IndexPath) -> Int {
   5.142 -        if var folder = fetchController?.object(at: indexPath) as? CdFolder {
   5.143 -            var count = 0
   5.144 -            while folder.parent != nil {
   5.145 -                count += 1
   5.146 -                folder = folder.parent!
   5.147 -            }
   5.148 -            return count
   5.149 +        var folder = folderAt(indexPath: indexPath) as MessageFolder
   5.150 +        var count = 0
   5.151 +        while folder.parent != nil {
   5.152 +            count += 1
   5.153 +            folder = folder.parent!
   5.154          }
   5.155 -        return 0
   5.156 +        return count
   5.157      }
   5.158  
   5.159      override func tableView(_ tableView: UITableView,
   5.160                              didSelectRowAt indexPath: IndexPath) {
   5.161 -        if let fi = fetchController?.object(at: indexPath) as? CdFolder {
   5.162 -            let predicateBasic = config.appConfig.model.basicMessagePredicate()
   5.163 -            let predicateAccount = NSPredicate.init(
   5.164 -                format: "folder.account.email = %@", config.account.user.address)
   5.165 -            let predicateFolder = NSPredicate.init(
   5.166 -                format: "folder.name = %@", fi.name)
   5.167 +        let fi = folderAt(indexPath: indexPath)
   5.168 +        emailListConfig = EmailListViewController.EmailListConfig.init(
   5.169 +            appConfig: config.appConfig,
   5.170 +            account: config.account, folder: fi)
   5.171  
   5.172 -            // If the folder is just local, then don't let the email list view sync.
   5.173 -            var account: Account? = nil
   5.174 -            if let ft = FolderType.fromInt(fi.folderType.intValue) {
   5.175 -                if ft.isRemote() {
   5.176 -                    account = config.account
   5.177 -                }
   5.178 -                // Start syncing emails when it's not an inbox (which was just synced already)
   5.179 -                let syncOnAppear = ft != .inbox
   5.180 -
   5.181 -                emailListConfig = EmailListViewController.EmailListConfig.init(
   5.182 -                    appConfig: config.appConfig,
   5.183 -                    predicate: NSCompoundPredicate.init(
   5.184 -                        andPredicateWithSubpredicates: [predicateBasic, predicateAccount,
   5.185 -                            predicateFolder]),
   5.186 -                    sortDescriptors: [NSSortDescriptor.init(
   5.187 -                        key: "receivedDate", ascending: false)],
   5.188 -                    account: account, folderName: fi.name, syncOnAppear: syncOnAppear)
   5.189 -
   5.190 -                performSegue(withIdentifier: segueShowEmails, sender: self)
   5.191 -            }
   5.192 -        }
   5.193 +        performSegue(withIdentifier: segueShowEmails, sender: self)
   5.194      }
   5.195  
   5.196      // MARK: - Navigation
     6.1 --- a/pEpForiOS/UI/Compose/ComposeViewController.swift	Tue Oct 25 12:59:55 2016 +0200
     6.2 +++ b/pEpForiOS/UI/Compose/ComposeViewController.swift	Tue Oct 25 14:33:41 2016 +0200
     6.3 @@ -23,7 +23,15 @@
     6.4    }
     6.5  }
     6.6  
     6.7 -//import NSEvent
     6.8 +class PhotoAttachment {
     6.9 +    static let contentType = "image/JPEG"
    6.10 +
    6.11 +    let image: UIImage
    6.12 +
    6.13 +    init(image: UIImage) {
    6.14 +        self.image = image
    6.15 +    }
    6.16 +}
    6.17  
    6.18  open class ComposeViewController: UITableViewController, UINavigationControllerDelegate {
    6.19      struct UIModel {
    6.20 @@ -54,7 +62,7 @@
    6.21          /**
    6.22           If there are attachments, they should be stored here, and displayed in the view.
    6.23           */
    6.24 -        var attachments = [SimpleAttachment]()
    6.25 +        var attachments = [Attachment]()
    6.26  
    6.27          /**
    6.28           Set to `true` as soon as the user has changed the body text, or added a recipient.
    6.29 @@ -133,7 +141,7 @@
    6.30      /**
    6.31       The message we're constructing
    6.32       */
    6.33 -    var messageToSend: CdMessage?
    6.34 +    var messageToSend: Message?
    6.35  
    6.36      /**
    6.37       For determining if we give the focus to the to text field.
    6.38 @@ -188,7 +196,7 @@
    6.39       For certain values of `composeMode`, there will be an email to act on
    6.40       (like reply, forward, compose draft). This is it.
    6.41       */
    6.42 -    var originalMessage: CdMessage?
    6.43 +    var originalMessage: Message?
    6.44  
    6.45      /**
    6.46       The original text attributes from a recipient cell text.
    6.47 @@ -214,19 +222,16 @@
    6.48          super.viewWillAppear(animated)
    6.49          if let forwardedMessage = forwardedMessage() {
    6.50              // If we forward a message, add its contents as data
    6.51 -            if let ac = appConfig {
    6.52 -                let op = MessageToAttachmentOperation.init(
    6.53 -                    message: forwardedMessage, coreDataUtil: ac.coreDataUtil)
    6.54 -                op.completionBlock = {
    6.55 -                    GCD.onMain() {
    6.56 -                        if let attch = op.attachment {
    6.57 -                            self.model.attachments.append(attch)
    6.58 -                            // TODO: Update attachment display!
    6.59 -                        }
    6.60 +            let op = MessageToAttachmentOperation.init(message: forwardedMessage)
    6.61 +            op.completionBlock = {
    6.62 +                GCD.onMain() {
    6.63 +                    if let attch = op.attachment {
    6.64 +                        self.model.attachments.append(attch)
    6.65 +                        // TODO: Update attachment display!
    6.66                      }
    6.67                  }
    6.68 -                operationQueue.addOperation(op)
    6.69              }
    6.70 +            operationQueue.addOperation(op)
    6.71          }
    6.72  
    6.73          overrideBackButton()
    6.74 @@ -371,7 +376,7 @@
    6.75              op.completionBlock = {
    6.76                  if !op.isCancelled {
    6.77                      if let pepColor = op.pepColorRating {
    6.78 -                        let color = PEPUtil.colorFromPepRating(pepColor)
    6.79 +                        let color = PEPUtil.pEpColorFromRating(pepColor)
    6.80                          GCD.onMain() {
    6.81                              self.setPrivacyColor(color, toSendButton: self.sendButton)
    6.82                          }
    6.83 @@ -408,22 +413,21 @@
    6.84      /**
    6.85       Updates the given message with data from the view.
    6.86       */
    6.87 -    func populateMessage(message: CdMessage, account: Account,
    6.88 -                         model: ICdModel) {
    6.89 +    func populate(message: Message, account: Account,
    6.90 +                  model: ICdModel) {
    6.91          // reset
    6.92          message.to = []
    6.93          message.cc = []
    6.94          message.bcc = []
    6.95  
    6.96 -        message.subject = nil
    6.97 +        message.shortMessage = nil
    6.98          message.longMessage = nil
    6.99          message.longMessageFormatted = nil
   6.100  
   6.101          message.references = []
   6.102  
   6.103          // from
   6.104 -        message.from = model.insertOrUpdateContactEmail(account.user.address,
   6.105 -                                                        name: account.user.userName)
   6.106 +        message.from = account.user
   6.107  
   6.108          // recipients
   6.109          for (_, cell) in recipientCells {
   6.110 @@ -437,21 +441,17 @@
   6.111                      let mailStrings2 = mailStrings1.filter() {
   6.112                          !$0.isOnlyWhiteSpace()
   6.113                      }
   6.114 -                    let contacts: [CdContact] = mailStrings2.map() {
   6.115 -                        let c = model.insertOrUpdateContactEmail($0, name: nil)
   6.116 -                        return c
   6.117 +                    let contacts: [Identity] = mailStrings2.map() {
   6.118 +                        return Identity.create(address: $0)
   6.119                      }
   6.120 -                    if contacts.count > 0 {
   6.121 -                        if let rt = cell.recipientType {
   6.122 -                            let set = NSOrderedSet.init(array: contacts.map() {$0 as AnyObject})
   6.123 -                            switch rt {
   6.124 -                            case .to:
   6.125 -                                message.to = set
   6.126 -                            case .cc:
   6.127 -                                message.cc = set
   6.128 -                            case .bcc:
   6.129 -                                message.bcc = set
   6.130 -                            }
   6.131 +                    if contacts.count > 0, let rt = cell.recipientType {
   6.132 +                        switch rt {
   6.133 +                        case .to:
   6.134 +                            message.to = contacts
   6.135 +                        case .cc:
   6.136 +                            message.cc = contacts
   6.137 +                        case .bcc:
   6.138 +                            message.bcc = contacts
   6.139                          }
   6.140                      }
   6.141                  }
   6.142 @@ -459,7 +459,7 @@
   6.143          }
   6.144  
   6.145          if let subjectText = subjectTextField?.text {
   6.146 -            message.subject = subjectText
   6.147 +            message.shortMessage = subjectText
   6.148          }
   6.149  
   6.150          if let bodyText = longBodyMessageTextView?.text {
   6.151 @@ -471,17 +471,11 @@
   6.152       Updates the given message with data from the original message,
   6.153       if it exists (e.g., reply)
   6.154       */
   6.155 -    func populateMessageWithReplyData(_ message: CdMessage) {
   6.156 +    func populateWithReplyData(message: Message) {
   6.157          guard let om = replyFromMessage() else {
   6.158              return
   6.159          }
   6.160 -
   6.161 -        guard let model = appConfig?.model else {
   6.162 -            Log.warnComponent(comp, "Can't do anything without model")
   6.163 -            return
   6.164 -        }
   6.165 -
   6.166 -        setupMessageReferences(om, message: message, model: model)
   6.167 +        setupMessageReferences(parent: om, message: message)
   6.168      }
   6.169  
   6.170      /**
   6.171 @@ -489,18 +483,12 @@
   6.172       and a child message (i.e., the message containing the reply).
   6.173       See https://cr.yp.to/immhf/thread.html for general strategy.
   6.174       */
   6.175 -    func setupMessageReferences(_ parent: CdMessage, message: CdMessage, model: ICdModel) {
   6.176 +    func setupMessageReferences(parent: Message, message: Message) {
   6.177          // Inherit all references from the parent
   6.178          message.references = parent.references
   6.179  
   6.180          // Add the parent to the references
   6.181 -        if let references = message.references.mutableCopy() as? NSMutableOrderedSet {
   6.182 -            if let omid = parent.messageID {
   6.183 -                let ref = model.insertOrUpdateMessageReference(omid)
   6.184 -                references.add(ref)
   6.185 -                message.references = references
   6.186 -            }
   6.187 -        }
   6.188 +        message.references.append(parent.messageID)
   6.189      }
   6.190  
   6.191      /**
   6.192 @@ -509,7 +497,7 @@
   6.193       - Note: The forwarded mail attachment was already added to the model,
   6.194       it will be handled by the general attachment handling in another function.
   6.195       */
   6.196 -    func populateMessageWithForwardedData(_ message: CdMessage) {
   6.197 +    func populateWithForwardedData(message: Message) {
   6.198          guard let _ = forwardedMessage() else {
   6.199              return
   6.200          }
   6.201 @@ -520,7 +508,7 @@
   6.202          }
   6.203      }
   6.204  
   6.205 -    func populateMessage(_ message: CdMessage, withAttachmentsFromTextView theTextView: UITextView?) {
   6.206 +    func populate(message: Message, withAttachmentsFromTextView theTextView: UITextView?) {
   6.207          guard let textView = theTextView else {
   6.208              Log.warnComponent(comp, "Trying to get attachments, but no text view")
   6.209              return
   6.210 @@ -535,7 +523,7 @@
   6.211          }
   6.212      }
   6.213  
   6.214 -    func messageForSending() -> CdMessage? {
   6.215 +    func messageForSending() -> Message? {
   6.216          guard let appC = appConfig else {
   6.217              Log.warnComponent(
   6.218                  comp, "Really need a non-nil appConfig for creating send message")
   6.219 @@ -547,8 +535,8 @@
   6.220          }
   6.221  
   6.222          if messageToSend == nil {
   6.223 -            messageToSend = appC.model.insertNewMessageForSendingFromAccountEmail(
   6.224 -                account.user.address)
   6.225 +            messageToSend = Message.create(uuid: "")
   6.226 +            // TODO: IOS-222: Take account into consideration
   6.227          }
   6.228  
   6.229          guard let msg = messageToSend else {
   6.230 @@ -556,10 +544,10 @@
   6.231              return nil
   6.232          }
   6.233  
   6.234 -        populateMessage(message: msg, account: account, model: appC.model)
   6.235 -        populateMessageWithReplyData(msg)
   6.236 -        populateMessageWithForwardedData(msg)
   6.237 -        populateMessage(msg, withAttachmentsFromTextView: longBodyMessageTextView)
   6.238 +        populate(message: msg, account: account, model: appC.model)
   6.239 +        populateWithReplyData(message: msg)
   6.240 +        populateWithForwardedData(message: msg)
   6.241 +        populate(message: msg, withAttachmentsFromTextView: longBodyMessageTextView)
   6.242  
   6.243          return msg
   6.244      }
   6.245 @@ -705,7 +693,7 @@
   6.246      /**
   6.247       - Returns: The original message to be replied on, if it's a reply.
   6.248       */
   6.249 -    func replyFromMessage() -> CdMessage? {
   6.250 +    func replyFromMessage() -> Message? {
   6.251          if composeMode == .replyFrom {
   6.252              if let om = originalMessage {
   6.253                  return om
   6.254 @@ -717,7 +705,7 @@
   6.255      /**
   6.256       - Returns: The message that has to be forwarded.
   6.257       */
   6.258 -    func forwardedMessage() -> CdMessage? {
   6.259 +    func forwardedMessage() -> Message? {
   6.260          if composeMode == .forward {
   6.261              if let om = originalMessage {
   6.262                  return om
   6.263 @@ -729,7 +717,7 @@
   6.264      /**
   6.265       - Returns: The draft message that should be used as a base for the compose.
   6.266       */
   6.267 -    func composeFromDraftMessage() -> CdMessage? {
   6.268 +    func composeFromDraftMessage() -> Message? {
   6.269          if composeMode == .composeDraft {
   6.270              if let om = originalMessage {
   6.271                  return om
   6.272 @@ -772,8 +760,8 @@
   6.273                          if contacts.count > 0 {
   6.274                              changedRecipients = true
   6.275                          }
   6.276 -                        ComposeViewHelper.transferContacts(
   6.277 -                            contacts, toTextField: cell.recipientTextView,
   6.278 +                        ComposeViewHelper.transfer(
   6.279 +                            identities: contacts, toTextField: cell.recipientTextView,
   6.280                              titleText: cell.titleText)
   6.281                      }
   6.282  
   6.283 @@ -781,8 +769,8 @@
   6.284                      if cell.recipientType == .to {
   6.285                          if let om = replyFromMessage() {
   6.286                              if let from = om.from {
   6.287 -                                ComposeViewHelper.transferContacts(
   6.288 -                                    [from], toTextField: cell.recipientTextView,
   6.289 +                                ComposeViewHelper.transfer(
   6.290 +                                    identities: [from], toTextField: cell.recipientTextView,
   6.291                                      titleText: cell.titleText)
   6.292                                  changedRecipients = true
   6.293                              }
   6.294 @@ -823,7 +811,7 @@
   6.295                  }
   6.296  
   6.297                  if let m = composeFromDraftMessage() {
   6.298 -                    subjectTextField?.text = m.subject
   6.299 +                    subjectTextField?.text = m.shortMessage
   6.300                  }
   6.301  
   6.302                  return cell
   6.303 @@ -963,29 +951,24 @@
   6.304              return
   6.305          }
   6.306  
   6.307 -        let photoAttachment = SimpleAttachment.init(
   6.308 -            filename: nil, contentType: "image/JPEG", data: nil, image: attachedImage)
   6.309 +        let photoAttachment = PhotoAttachment.init(image: attachedImage)
   6.310  
   6.311 -        model.attachments.append(photoAttachment)
   6.312 -        insertPhotoAttachment(photoAttachment)
   6.313 +        insert(imageAttachment: photoAttachment)
   6.314  
   6.315          dismiss(animated: true, completion: nil)
   6.316      }
   6.317  
   6.318 -    func insertPhotoAttachment(_ attachment: SimpleAttachment) {
   6.319 -        guard let image = attachment.image else {
   6.320 -            return
   6.321 -        }
   6.322 +    func insert(imageAttachment: PhotoAttachment) {
   6.323          guard let textView = longBodyMessageTextView else {
   6.324              return
   6.325          }
   6.326  
   6.327          let textAttachment = NSTextAttachment()
   6.328 -        textAttachment.image = image
   6.329 +        textAttachment.image = imageAttachment.image
   6.330          let imageString = NSAttributedString(attachment:textAttachment)
   6.331  
   6.332          textAttachment.bounds = obtainContainerToMaintainRatio(
   6.333 -            textView.bounds.width, rectangle: image.size)
   6.334 +            textView.bounds.width, rectangle: imageAttachment.image.size)
   6.335  
   6.336          let selectedRange = textView.selectedRange
   6.337          let attrText = NSMutableAttributedString.init(attributedString: textView.attributedText)
     7.1 --- a/pEpForiOS/UI/Compose/ComposeViewHelper.swift	Tue Oct 25 12:59:55 2016 +0200
     7.2 +++ b/pEpForiOS/UI/Compose/ComposeViewHelper.swift	Tue Oct 25 14:33:41 2016 +0200
     7.3 @@ -8,6 +8,8 @@
     7.4  
     7.5  import UIKit
     7.6  
     7.7 +import MessageModel
     7.8 +
     7.9  open class ComposeViewHelper {
    7.10      /**
    7.11       Builds a pEp mail dictionary from all the related views. This is just a quick
    7.12 @@ -155,11 +157,11 @@
    7.13      /**
    7.14       * Puts the emails from the contacts into a recipient text field.
    7.15       */
    7.16 -    open static func transferContacts(
    7.17 -        _ contacts: [CdContact], toTextField textField: UITextView, titleText: String?) {
    7.18 +    open static func transfer(
    7.19 +        identities: [Identity], toTextField textField: UITextView, titleText: String?) {
    7.20          textField.text = "\(String.orEmpty(titleText))"
    7.21 -        for c in contacts {
    7.22 -            textField.text = "\(textField.text)\(c.email), "
    7.23 +        for c in identities {
    7.24 +            textField.text = "\(textField.text)\(c.address), "
    7.25          }
    7.26      }
    7.27  
    7.28 @@ -167,17 +169,17 @@
    7.29       - Returns: The array of `Contact`s for a given recipient type and message.
    7.30       */
    7.31      open static func contactsForRecipientType(
    7.32 -        _ recipientType: RecipientType?, fromMessage message: CdMessage) -> [CdContact] {
    7.33 +        _ recipientType: RecipientType?, fromMessage message: Message) -> [Identity] {
    7.34          guard let rt = recipientType else {
    7.35              return []
    7.36          }
    7.37          switch rt {
    7.38          case .to:
    7.39 -            return orderedSetToContacts(message.to)
    7.40 +            return message.to
    7.41          case .cc:
    7.42 -            return orderedSetToContacts(message.cc)
    7.43 +            return message.cc
    7.44          case .bcc:
    7.45 -            return orderedSetToContacts(message.bcc)
    7.46 +            return message.bcc
    7.47          }
    7.48      }
    7.49  
     8.1 --- a/pEpForiOS/UI/EmailDisplay/EmailHeaderView.swift	Tue Oct 25 12:59:55 2016 +0200
     8.2 +++ b/pEpForiOS/UI/EmailDisplay/EmailHeaderView.swift	Tue Oct 25 14:33:41 2016 +0200
     8.3 @@ -8,6 +8,8 @@
     8.4  
     8.5  import UIKit
     8.6  
     8.7 +import MessageModel
     8.8 +
     8.9  class EmailHeaderView: UIView {
    8.10      /**
    8.11       Where to start laying out labels from the left.
    8.12 @@ -48,7 +50,7 @@
    8.13       */
    8.14      var lastLeftLabel: UILabel? = nil
    8.15  
    8.16 -    var message: CdMessage!
    8.17 +    var message: Message!
    8.18  
    8.19      let dateFormatter = UIHelper.dateFormatterEmailDetails()
    8.20  
    8.21 @@ -85,7 +87,7 @@
    8.22                                  position: pos, width: width)
    8.23          }
    8.24  
    8.25 -        if let date = message.receivedDate {
    8.26 +        if let date = message.received {
    8.27              pos = biggerNewline(pos)
    8.28              let dateLabel = headerBaseLabelWithText(dateFormatter.string(from: date as Date),
    8.29                                                      maxWidth: width)
    8.30 @@ -96,7 +98,7 @@
    8.31              lastLeftLabel = dateLabel
    8.32          }
    8.33  
    8.34 -        if let subject = message.subject {
    8.35 +        if let subject = message.shortMessage {
    8.36              pos = biggerNewline(pos)
    8.37              let subjectLabel = headerBaseLabelWithText(subject, maxWidth: width)
    8.38              subjectLabel.frame.origin = pos
    8.39 @@ -109,7 +111,7 @@
    8.40          preferredSize = CGSize(width: width, height: pos.y)
    8.41      }
    8.42  
    8.43 -    func addRecipients(_ recipients: NSOrderedSet, title: String, position: CGPoint,
    8.44 +    func addRecipients(_ recipients: [Identity], title: String, position: CGPoint,
    8.45                         width: CGFloat) -> CGPoint {
    8.46          var pos = newline(position)
    8.47  
    8.48 @@ -122,16 +124,14 @@
    8.49  
    8.50          let session = PEPSession.init()
    8.51          for rec in recipients {
    8.52 -            if let contact = rec as? CdContact {
    8.53 -                let recLabel = recipientBaseLabelWithText(contact.displayString())
    8.54 -                let privacyColor = PEPUtil.privacyColorForContact(contact, session: session)
    8.55 -                UIHelper.setBackgroundColor(
    8.56 -                    privacyColor, forLabel: recLabel, defaultColor: recLabel.backgroundColor)
    8.57 -                pos = putAdjacentLeftLabel(lastUsedLabel, rightLabel: recLabel, atLeftPos: pos,
    8.58 -                                           width: width)
    8.59 -                lastUsedLabel = recLabel
    8.60 -                addSubview(recLabel)
    8.61 -            }
    8.62 +            let recLabel = recipientBaseLabelWithText(rec.displayString)
    8.63 +            let privacyColor = PEPUtil.pEpColor(identity: rec, session: session)
    8.64 +            UIHelper.setBackgroundColor(
    8.65 +                privacyColor, forLabel: recLabel, defaultColor: recLabel.backgroundColor)
    8.66 +            pos = putAdjacentLeftLabel(lastUsedLabel, rightLabel: recLabel, atLeftPos: pos,
    8.67 +                                       width: width)
    8.68 +            lastUsedLabel = recLabel
    8.69 +            addSubview(recLabel)
    8.70          }
    8.71  
    8.72          return pos
    8.73 @@ -146,8 +146,8 @@
    8.74          lastLeftLabel = fromTitleLabel
    8.75  
    8.76          if let fromContact = message.from {
    8.77 -            let fromLabel = recipientBaseLabelWithText(fromContact.displayString())
    8.78 -            let privacyColor = PEPUtil.privacyColorForContact(fromContact)
    8.79 +            let fromLabel = recipientBaseLabelWithText(fromContact.displayString)
    8.80 +            let privacyColor = PEPUtil.pEpColor(identity: fromContact)
    8.81              UIHelper.setBackgroundColor(
    8.82                  privacyColor, forLabel: fromLabel, defaultColor: fromLabel.backgroundColor)
    8.83  
     9.1 --- a/pEpForiOS/UI/EmailDisplay/EmailListViewController.swift	Tue Oct 25 12:59:55 2016 +0200
     9.2 +++ b/pEpForiOS/UI/EmailDisplay/EmailListViewController.swift	Tue Oct 25 14:33:41 2016 +0200
     9.3 @@ -33,25 +33,17 @@
     9.4  }
     9.5  
     9.6  
     9.7 -class EmailListViewController: FetchTableViewController {
     9.8 +class EmailListViewController: UITableViewController {
     9.9      struct EmailListConfig {
    9.10          let appConfig: AppConfig
    9.11  
    9.12 -        /** Set to whatever criteria you want to have mails displayed */
    9.13 -        let predicate: NSPredicate?
    9.14 -
    9.15 -        /** The sort descriptors to be used for displaying emails */
    9.16 -        let sortDescriptors: [NSSortDescriptor]?
    9.17 -
    9.18 -        /** If applicable, the account to refresh from */
    9.19          let account: Account?
    9.20  
    9.21 -        /** If applicable, the folder name to sync */
    9.22 -        let folderName: String?
    9.23 +        /** The folder to display, if it exists */
    9.24 +        let folder: Folder?
    9.25 +    }
    9.26  
    9.27 -        /** Should there be a sync directly when the view appears? */
    9.28 -        let syncOnAppear: Bool
    9.29 -    }
    9.30 +    var comp = "EmailListViewController"
    9.31  
    9.32      struct UIState {
    9.33          var isSynching: Bool = false
    9.34 @@ -82,70 +74,36 @@
    9.35      /**
    9.36       The message that should be saved as a draft when compose gets aborted.
    9.37       */
    9.38 -    var draftMessageToStore: CdMessage?
    9.39 +    var draftMessageToStore: Message?
    9.40  
    9.41      /**
    9.42       When the user taps on a draft email, this is the message that was selected
    9.43       and should be given to the compose view.
    9.44       */
    9.45 -    var draftMessageToCompose: CdMessage?
    9.46 +    var draftMessageToCompose: Message?
    9.47  
    9.48      required init?(coder aDecoder: NSCoder) {
    9.49          super.init(coder: aDecoder)
    9.50          self.comp = "EmailListViewController"
    9.51      }
    9.52  
    9.53 -    func isReadedMessage(_ message: CdMessage)-> Bool {
    9.54 -        return message.flagSeen.boolValue
    9.55 +    func isRead(message: Message)-> Bool {
    9.56 +        return message.imapFlags.seen
    9.57      }
    9.58  
    9.59 -    func isImportantMessage(_ message: CdMessage)-> Bool {
    9.60 -        return message.flagFlagged.boolValue
    9.61 +    func isImportant(message: Message)-> Bool {
    9.62 +        return message.imapFlags.flagged
    9.63      }
    9.64  
    9.65      override func viewDidLoad() {
    9.66 -        refreshController = UIRefreshControl.init()
    9.67 -        refreshController.addTarget(self, action: #selector(self.fetchMailsRefreshControl(_:)),
    9.68 -                                    for: UIControlEvents.valueChanged)
    9.69          UIHelper.variableCellHeightsTableView(self.tableView)
    9.70      }
    9.71  
    9.72      override func viewWillAppear(_ animated: Bool) {
    9.73 -        // Disable fetching if there is no account
    9.74 -        if config.account != nil {
    9.75 -            self.refreshControl = refreshController
    9.76 -        } else {
    9.77 -            self.refreshControl = nil
    9.78 -        }
    9.79 -
    9.80 -        prepareFetchRequest()
    9.81 -        if config.syncOnAppear {
    9.82 -            fetchMailsRefreshControl()
    9.83 -        }
    9.84 +        updateModel()
    9.85          super.viewWillAppear(animated)
    9.86      }
    9.87  
    9.88 -    func fetchMailsRefreshControl(_ refreshControl: UIRefreshControl? = nil) {
    9.89 -        if let account = config.account, let connectInfo = account.connectInfo {
    9.90 -            state.isSynching = true
    9.91 -            updateUI()
    9.92 -
    9.93 -            config.appConfig.grandOperator.fetchEmailsAndDecryptImapSmtp(connectInfos: 
    9.94 -                [connectInfo], folderName: config.folderName,
    9.95 -                completionBlock: { error in
    9.96 -                    Log.infoComponent(self.comp, "Sync completed, error: \(error)")
    9.97 -                    UIHelper.displayError(error, controller: self)
    9.98 -                    self.config.appConfig.model.save()
    9.99 -                    self.state.isSynching = false
   9.100 -                    refreshControl?.endRefreshing()
   9.101 -                    self.updateUI()
   9.102 -            })
   9.103 -        } else {
   9.104 -            state.isSynching = false
   9.105 -            updateUI()
   9.106 -        }
   9.107 -    }
   9.108 -
   9.109      @IBAction func mailSentSegue(_ segue: UIStoryboardSegue) {
   9.110      }
   9.111  
   9.112 @@ -153,37 +111,34 @@
   9.113      }
   9.114  
   9.115      @IBAction func backFromComposeSaveDraftSegue(_ segue: UIStoryboardSegue) {
   9.116 -        guard let msg = draftMessageToStore else {
   9.117 +        guard let message = draftMessageToStore else {
   9.118              return
   9.119          }
   9.120  
   9.121          state.isSynching = true
   9.122          updateUI()
   9.123  
   9.124 -        config.appConfig.grandOperator.saveDraftMail(
   9.125 -            msg, account: msg.folder.account, completionBlock: { error in
   9.126 -                GCD.onMain() {
   9.127 -                    UIHelper.displayError(error, controller: self)
   9.128 -                    self.state.isSynching = false
   9.129 -                    self.updateUI()
   9.130 -                }
   9.131 -        })
   9.132 +        message.imapFlags.draft = true
   9.133 +
   9.134 +        // TODO: IOS 222: Save as draft
   9.135 +        if let folder = draftMessageToStore?.parent as? Folder {
   9.136 +            if folder.folderType == .drafts {
   9.137 +                message.save()
   9.138 +                return
   9.139 +            }
   9.140 +        }
   9.141 +
   9.142 +        guard let account = config.account else {
   9.143 +            return
   9.144 +        }
   9.145 +        
   9.146 +        if let folder = account.folder(ofType: FolderType.drafts) {
   9.147 +            folder.save(message: message)
   9.148 +            return
   9.149 +        }
   9.150      }
   9.151  
   9.152 -    func prepareFetchRequest() {
   9.153 -        let fetchRequest = NSFetchRequest<NSManagedObject>.init(entityName: CdMessage.entityName())
   9.154 -        fetchRequest.predicate = config.predicate
   9.155 -        fetchRequest.sortDescriptors = config.sortDescriptors
   9.156 -        fetchController = NSFetchedResultsController.init(
   9.157 -            fetchRequest: fetchRequest,
   9.158 -            managedObjectContext: config.appConfig.coreDataUtil.managedObjectContext,
   9.159 -            sectionNameKeyPath: nil, cacheName: nil)
   9.160 -        fetchController?.delegate = self
   9.161 -        do {
   9.162 -            try fetchController?.performFetch()
   9.163 -        } catch let err as NSError {
   9.164 -            Log.errorComponent(comp, error: err)
   9.165 -        }
   9.166 +    func updateModel() {
   9.167      }
   9.168  
   9.169      // MARK: - UI State
   9.170 @@ -198,19 +153,15 @@
   9.171      // MARK: - UITableViewDataSource
   9.172  
   9.173      override func numberOfSections(in tableView: UITableView) -> Int {
   9.174 -        if let count = fetchController?.sections?.count {
   9.175 -            return count
   9.176 -        } else {
   9.177 -            return 0
   9.178 +        if let _ = config.folder {
   9.179 +            return 1
   9.180          }
   9.181 +        return 0
   9.182      }
   9.183  
   9.184      override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
   9.185 -        if fetchController?.sections?.count > 0 {
   9.186 -            if let sections = fetchController?.sections {
   9.187 -                let sectionInfo = sections[section]
   9.188 -                return sectionInfo.numberOfObjects
   9.189 -            }
   9.190 +        if let fol = config.folder {
   9.191 +            return fol.messageCount()
   9.192          }
   9.193          return 0
   9.194      }
   9.195 @@ -227,6 +178,16 @@
   9.196          return cell
   9.197      }
   9.198  
   9.199 +    /**
   9.200 +     The message at the given position.
   9.201 +     */
   9.202 +    func messageAt(indexPath: IndexPath) -> Message? {
   9.203 +        if let fol = config.folder {
   9.204 +            return fol.messageByIndex(indexPath.row)
   9.205 +        }
   9.206 +        return nil
   9.207 +    }
   9.208 +
   9.209      // MARK: - UITableViewDelegate
   9.210  
   9.211      override func tableView(_ tableView: UITableView,
   9.212 @@ -235,11 +196,9 @@
   9.213  
   9.214          let cell = tableView.cellForRow(at: indexPath)
   9.215  
   9.216 -        if let fn = config.folderName, let ac = config.account,
   9.217 -            let folder = config.appConfig.model.folderByName(fn, email: ac.user.address) {
   9.218 -            if folder.folderType.intValue == FolderType.drafts.rawValue {
   9.219 -                draftMessageToCompose = fetchController?.object(at: indexPath)
   9.220 -                    as? CdMessage
   9.221 +        if let fol = config.folder {
   9.222 +            if fol.folderType == .drafts {
   9.223 +                draftMessageToCompose = messageAt(indexPath: indexPath)
   9.224                  performSegue(withIdentifier: segueCompose, sender: cell)
   9.225                  return
   9.226              }
   9.227 @@ -250,25 +209,25 @@
   9.228  
   9.229      override func tableView(_ tableView: UITableView, editActionsForRowAt
   9.230          indexPath: IndexPath)-> [UITableViewRowAction]? {
   9.231 -
   9.232          let cell = tableView.cellForRow(at: indexPath) as! EmailListViewCell
   9.233 -        let email = fetchController?.object(at: indexPath) as! CdMessage
   9.234 -
   9.235 -        let isFlagAction = createIsFlagAction(email, cell: cell)
   9.236 -        let deleteAction = createDeleteAction(cell)
   9.237 -        let isReadAction = createIsReadAction(email, cell: cell)
   9.238 -        return [deleteAction,isFlagAction,isReadAction]
   9.239 +        if let email = messageAt(indexPath: indexPath) {
   9.240 +            let isFlagAction = createIsFlagAction(message: email, cell: cell)
   9.241 +            let deleteAction = createDeleteAction(cell)
   9.242 +            let isReadAction = createIsReadAction(message: email, cell: cell)
   9.243 +            return [deleteAction,isFlagAction,isReadAction]
   9.244 +        }
   9.245 +        return nil
   9.246      }
   9.247  
   9.248      // MARK: - Misc
   9.249  
   9.250 -    override func configureCell(_ theCell: UITableViewCell, indexPath: IndexPath) {
   9.251 +    func configureCell(_ theCell: UITableViewCell, indexPath: IndexPath) {
   9.252          guard let cell = theCell as? EmailListViewCell else {
   9.253              return
   9.254          }
   9.255 -        if let email = fetchController?.object(at: indexPath) as? CdMessage {
   9.256 -            if let colorRating = PEPUtil.colorRatingFromInt(email.pepColorRating?.intValue) {
   9.257 -                let privacyColor = PEPUtil.colorFromPepRating(colorRating)
   9.258 +        if let email = messageAt(indexPath: indexPath) {
   9.259 +            if let pEpRating = email.pEpRating {
   9.260 +                let privacyColor = PEPUtil.pEpColorFromRating(pEpRating)
   9.261                  if let uiColor = UIHelper.textBackgroundUIColorFromPrivacyColor(privacyColor) {
   9.262                      cell.backgroundColor = uiColor
   9.263                  } else {
   9.264 @@ -277,8 +236,8 @@
   9.265                      }
   9.266                  }
   9.267              }
   9.268 -            UIHelper.putString(email.from?.displayString(), toLabel: cell.senderLabel)
   9.269 -            UIHelper.putString(email.subject, toLabel: cell.subjectLabel)
   9.270 +            UIHelper.putString(email.from?.displayString, toLabel: cell.senderLabel)
   9.271 +            UIHelper.putString(email.shortMessage, toLabel: cell.subjectLabel)
   9.272  
   9.273              // Snippet
   9.274              if let text = email.longMessage {
   9.275 @@ -292,25 +251,25 @@
   9.276                  UIHelper.putString(nil, toLabel: cell.summaryLabel)
   9.277              }
   9.278  
   9.279 -            if let receivedDate = email.receivedDate {
   9.280 +            if let receivedDate = email.received {
   9.281                  UIHelper.putString(dateFormatter.string(from: receivedDate as Date),
   9.282                                     toLabel: cell.dateLabel)
   9.283              } else {
   9.284                  UIHelper.putString(nil, toLabel: cell.dateLabel)
   9.285              }
   9.286  
   9.287 -            if (isImportantMessage(email) && isReadedMessage(email)) {
   9.288 +            if (isImportant(message: email) && isRead(message: email)) {
   9.289                  cell.isImportantImage.isHidden = false
   9.290                  cell.isImportantImage.backgroundColor = UIColor.orange
   9.291              }
   9.292 -            else if (isImportantMessage(email) && !isReadedMessage(email)) {
   9.293 +            else if (isImportant(message: email) && !isRead(message: email)) {
   9.294                  cell.isImportantImage.isHidden = false
   9.295                  cell.isImportantImage.backgroundColor = UIColor.blue
   9.296                  cell.isImportantImage.layer.borderWidth = 2
   9.297                  cell.isImportantImage.layer.borderColor = UIColor.orange.cgColor
   9.298 -            } else if (!isImportantMessage(email) && isReadedMessage(email)) {
   9.299 +            } else if (!isImportant(message: email) && isRead(message: email)) {
   9.300                      cell.isImportantImage.isHidden = true
   9.301 -            } else if (!isImportantMessage(email) && !isReadedMessage(email)) {
   9.302 +            } else if (!isImportant(message: email) && !isRead(message: email)) {
   9.303                  cell.isImportantImage.isHidden = false
   9.304                  cell.isImportantImage.backgroundColor = UIColor.blue
   9.305              }
   9.306 @@ -326,8 +285,7 @@
   9.307                  as! ComposeViewController
   9.308              destination.appConfig = config.appConfig
   9.309              if let draft = draftMessageToCompose {
   9.310 -                draft.flagSeen = true
   9.311 -                draft.updateFlags()
   9.312 +                draft.imapFlags.seen = true
   9.313                  config.appConfig.model.save()
   9.314  
   9.315                  destination.originalMessage = draft
   9.316 @@ -338,7 +296,7 @@
   9.317                  let vc = segue.destination as? EmailViewController,
   9.318                  let cell = sender as? UITableViewCell,
   9.319                  let indexPath = self.tableView.indexPath(for: cell),
   9.320 -                let email = fetchController?.object(at: indexPath) as? CdMessage else {
   9.321 +                let email = messageAt(indexPath: indexPath) else {
   9.322                      return
   9.323              }
   9.324              vc.appConfig = config.appConfig
   9.325 @@ -346,37 +304,33 @@
   9.326          }
   9.327      }
   9.328  
   9.329 -    func syncFlagsToServer(_ message: CdMessage) {
   9.330 -        self.config.appConfig.grandOperator.syncFlagsToServerForFolder(
   9.331 -            message.folder,
   9.332 -            completionBlock: { error in
   9.333 -                UIHelper.displayError(error, controller: self)
   9.334 -        })
   9.335 +    func syncFlagsToServer(message: Message) {
   9.336 +        // TODO: IOS 222: Sync flags back to server
   9.337      }
   9.338  
   9.339 -    func createIsFlagAction(_ message: CdMessage, cell: EmailListViewCell) -> UITableViewRowAction {
   9.340 -
   9.341 +    func createIsFlagAction(message: Message, cell: EmailListViewCell) -> UITableViewRowAction {
   9.342          // preparing the title action to show when user swipe
   9.343          var localizedIsFlagTitle = " "
   9.344 -        if (isImportantMessage(message)) {
   9.345 -            localizedIsFlagTitle = NSLocalizedString("Unflag",
   9.346 -                                                     comment: "Unflag button title in swipe action on EmailListViewController")
   9.347 +        if (isImportant(message: message)) {
   9.348 +            localizedIsFlagTitle = NSLocalizedString(
   9.349 +                "Unflag",
   9.350 +                comment: "Unflag button title in swipe action on EmailListViewController")
   9.351          } else {
   9.352 -            localizedIsFlagTitle = NSLocalizedString("Flag",
   9.353 -                                                     comment: "Flag button title in swipe action on EmailListViewController")
   9.354 +            localizedIsFlagTitle = NSLocalizedString(
   9.355 +                "Flag",
   9.356 +                comment: "Flag button title in swipe action on EmailListViewController")
   9.357          }
   9.358  
   9.359          // preparing action to trigger when user swipe
   9.360          let isFlagCompletionHandler: (UITableViewRowAction, IndexPath) -> Void =
   9.361              { (action, indexPath) in
   9.362 -                if (self.isImportantMessage(message)) {
   9.363 -                    message.flagFlagged = false
   9.364 +                if (self.isImportant(message: message)) {
   9.365 +                    message.imapFlags.flagged = false
   9.366  
   9.367                  } else {
   9.368 -                    message.flagFlagged = true
   9.369 +                    message.imapFlags.flagged = true
   9.370                  }
   9.371 -                message.updateFlags()
   9.372 -                self.syncFlagsToServer(message)
   9.373 +                self.syncFlagsToServer(message: message)
   9.374                  self.tableView.reloadRows(at: [indexPath], with: .none)
   9.375          }
   9.376          // creating the action
   9.377 @@ -391,15 +345,15 @@
   9.378      func createDeleteAction (_ cell: EmailListViewCell) -> UITableViewRowAction {
   9.379  
   9.380          // preparing the title action to show when user swipe
   9.381 -        let localizedDeleteTitle = NSLocalizedString("Erase",
   9.382 -                                                     comment: "Erase button title in swipe action on EmailListViewController")
   9.383 +        let localizedDeleteTitle = NSLocalizedString(
   9.384 +            "Erase",
   9.385 +            comment: "Erase button title in swipe action on EmailListViewController")
   9.386  
   9.387          let deleteCompletionHandler: (UITableViewRowAction, IndexPath) -> Void =
   9.388              { (action, indexPath) in
   9.389 -                let managedObject = self.fetchController?.object(at: indexPath) as? CdMessage
   9.390 -                managedObject?.flagDeleted = true
   9.391 -                managedObject?.updateFlags()
   9.392 -                self.syncFlagsToServer(managedObject!)
   9.393 +                let message = self.messageAt(indexPath: indexPath)
   9.394 +                message?.imapFlags.deleted = true
   9.395 +                self.syncFlagsToServer(message: message!)
   9.396          }
   9.397  
   9.398          // creating the action
   9.399 @@ -408,29 +362,28 @@
   9.400          return deleteAction
   9.401      }
   9.402  
   9.403 -    func createIsReadAction (_ message: CdMessage, cell: EmailListViewCell) -> UITableViewRowAction {
   9.404 -
   9.405 +    func createIsReadAction(message: Message, cell: EmailListViewCell) -> UITableViewRowAction {
   9.406          // preparing the title action to show when user swipe
   9.407          var localizedisReadTitle = " "
   9.408 -        if (isReadedMessage(message)) {
   9.409 -            localizedisReadTitle = NSLocalizedString("Unread",
   9.410 -                                                     comment: "Unread button title in swipe action on EmailListViewController")
   9.411 +        if (isRead(message: message)) {
   9.412 +            localizedisReadTitle = NSLocalizedString(
   9.413 +                "Unread",
   9.414 +                comment: "Unread button title in swipe action on EmailListViewController")
   9.415          } else {
   9.416 -            localizedisReadTitle = NSLocalizedString("Read",
   9.417 -                                                     comment: "Read button title in swipe action on EmailListViewController")
   9.418 +            localizedisReadTitle = NSLocalizedString(
   9.419 +                "Read",
   9.420 +                comment: "Read button title in swipe action on EmailListViewController")
   9.421          }
   9.422  
   9.423          // creating the action
   9.424          let isReadCompletionHandler: (UITableViewRowAction, IndexPath) -> Void =
   9.425              { (action, indexPath) in
   9.426 -                if (self.isReadedMessage(message)) {
   9.427 -                    message.flagSeen = false
   9.428 -                    message.updateFlags()
   9.429 +                if (self.isRead(message: message)) {
   9.430 +                    message.imapFlags.seen = false
   9.431                  } else {
   9.432 -                    message.flagSeen = true
   9.433 -                    message.updateFlags()
   9.434 +                    message.imapFlags.seen = true
   9.435                  }
   9.436 -                self.syncFlagsToServer(message)
   9.437 +                self.syncFlagsToServer(message: message)
   9.438                  self.tableView.reloadRows(at: [indexPath], with: .none)
   9.439          }
   9.440          let isReadAction = UITableViewRowAction(style: .default, title: localizedisReadTitle,
    10.1 --- a/pEpForiOS/UI/EmailDisplay/EmailViewController.swift	Tue Oct 25 12:59:55 2016 +0200
    10.2 +++ b/pEpForiOS/UI/EmailDisplay/EmailViewController.swift	Tue Oct 25 14:33:41 2016 +0200
    10.3 @@ -10,6 +10,8 @@
    10.4  import UIKit
    10.5  import WebKit
    10.6  
    10.7 +import MessageModel
    10.8 +
    10.9  class EmailViewController: UIViewController {
   10.10      /** Segue name for replying to the sender (from) */
   10.11      let segueReplyFrom = "segueReplyFrom"
   10.12 @@ -31,7 +33,7 @@
   10.13      let headerView = EmailHeaderView.init()
   10.14      var webView: WKWebView!
   10.15  
   10.16 -    var message: CdMessage!
   10.17 +    var message: Message!
   10.18  
   10.19      override func viewDidLoad() {
   10.20          super.viewDidLoad()
   10.21 @@ -53,8 +55,7 @@
   10.22          headerView.update(view.bounds.size.width)
   10.23  
   10.24          // Mark as read. Duh!
   10.25 -        message.flagSeen = true
   10.26 -        message.updateFlags()
   10.27 +        message.imapFlags.seen = true
   10.28          appConfig.model.save()
   10.29  
   10.30          if webView.scrollView.contentInset.top == 0 {
    11.1 --- a/pEpForiOS/UI/ImapSetup/SMTPSettingsTableView.swift	Tue Oct 25 12:59:55 2016 +0200
    11.2 +++ b/pEpForiOS/UI/ImapSetup/SMTPSettingsTableView.swift	Tue Oct 25 14:33:41 2016 +0200
    11.3 @@ -40,6 +40,9 @@
    11.4  
    11.5      open override func viewWillAppear(_ animated: Bool) {
    11.6          super.viewWillAppear(animated)
    11.7 +
    11.8 +        Account.delegate = self
    11.9 +
   11.10          if model.serverSMTP == nil {
   11.11              serverValue.becomeFirstResponder()
   11.12          }
   11.13 @@ -53,6 +56,11 @@
   11.14              portValueTextField], parentView: self.view)
   11.15      }
   11.16  
   11.17 +    open override func viewWillDisappear(_ animated: Bool) {
   11.18 +        super.viewWillDisappear(animated)
   11.19 +        Account.delegate = nil
   11.20 +    }
   11.21 +
   11.22      open override func didReceiveMemoryWarning() {
   11.23          super.didReceiveMemoryWarning()
   11.24      }
    12.1 --- a/pEpForiOS/UI/Trustwords/HandshakeViewController.swift	Tue Oct 25 12:59:55 2016 +0200
    12.2 +++ b/pEpForiOS/UI/Trustwords/HandshakeViewController.swift	Tue Oct 25 14:33:41 2016 +0200
    12.3 @@ -8,9 +8,11 @@
    12.4  
    12.5  import UIKit
    12.6  
    12.7 +import MessageModel
    12.8 +
    12.9  class HandshakeViewController: UITableViewController, UIGestureRecognizerDelegate {
   12.10 -    var message: CdMessage?
   12.11 -    var partner: CdContact?
   12.12 +    var message: Message?
   12.13 +    var partner: Identity?
   12.14      var appConfig: AppConfig!
   12.15      var hexamode: Bool = false
   12.16  
   12.17 @@ -56,7 +58,7 @@
   12.18              return cell
   12.19          } else if ((indexPath as NSIndexPath).row == partnerContact) {
   12.20              let cell = tableView.dequeueReusableCell(withIdentifier: "contactCell", for: indexPath) as! HandshakeLabelTableViewCell
   12.21 -            cell.handshakeLabel.text = partner!.displayString()
   12.22 +            cell.handshakeLabel.text = partner?.displayString
   12.23              return cell
   12.24          } else if ((indexPath as NSIndexPath).row == explanationTrustwords) {
   12.25              let cell = tableView.dequeueReusableCell(withIdentifier: "trustwordCell", for: indexPath) as! HandshakeTexViewTableViewCell
   12.26 @@ -67,7 +69,7 @@
   12.27              let cell = tableView.dequeueReusableCell(withIdentifier: "trustwordCell", for: indexPath) as! HandshakeTexViewTableViewCell
   12.28              if let p = partner, let myselfEmail = appConfig.currentAccount?.user.address,
   12.29                  let myselfContact = appConfig.model.contactByEmail(myselfEmail) {
   12.30 -                let partnerPepContact = PEPUtil.pepContact(p)
   12.31 +                let partnerPepContact = PEPUtil.pEp(identity: p)
   12.32                  let myselfContactPepContact = PEPUtil.pepContact(myselfContact)
   12.33                  let recognizer = UITapGestureRecognizer(target: self, action:#selector(HandshakeViewController.handleTap(_:)))
   12.34                  recognizer.delegate = self
   12.35 @@ -77,9 +79,9 @@
   12.36                          myselfContactPepContact, identity2: partnerPepContact,
   12.37                          language: "en", session: nil)
   12.38                  } else {
   12.39 -                    let myselfFingerprints = PEPUtil.fingprprintForContact(myselfContact)
   12.40 +                    let myselfFingerprints = PEPUtil.fingerPrintForContact(myselfContact)
   12.41  
   12.42 -                    let partnerFingerprints = PEPUtil.fingprprintForContact(partner!)
   12.43 +                    let partnerFingerprints = PEPUtil.fingerPrint(identity: partner!)
   12.44                      let bothFingerprints = "\(fingerprintFormat(partnerFingerprints!))\n\n\(fingerprintFormat(myselfFingerprints!))"
   12.45                      cell.handshakeTextView.text = bothFingerprints
   12.46                      cell.handshakeTextView.font = UIFont(name: "Menlo", size: UIFont.systemFontSize)
   12.47 @@ -118,14 +120,14 @@
   12.48  
   12.49      @IBAction func confirmTrustwords(_ sender: AnyObject) {
   12.50          if let p = partner {
   12.51 -            PEPUtil.trustContact(p)
   12.52 +            PEPUtil.trust(identity: p)
   12.53              let _ = navigationController?.popViewController(animated: true)
   12.54          }
   12.55      }
   12.56  
   12.57      @IBAction func wrongTrustwords(_ sender: AnyObject) {
   12.58          if let p = partner {
   12.59 -            PEPUtil.mistrustContact(p)
   12.60 +            PEPUtil.mistrust(identity: p)
   12.61              let _ = navigationController?.popViewController(animated: true)
   12.62          }
   12.63      }
    13.1 --- a/pEpForiOS/UI/Trustwords/TrustWordsViewController.swift	Tue Oct 25 12:59:55 2016 +0200
    13.2 +++ b/pEpForiOS/UI/Trustwords/TrustWordsViewController.swift	Tue Oct 25 14:33:41 2016 +0200
    13.3 @@ -8,15 +8,17 @@
    13.4  
    13.5  import UIKit
    13.6  
    13.7 +import MessageModel
    13.8 +
    13.9  class TrustWordsViewController: UITableViewController {
   13.10      var appConfig: AppConfig!
   13.11 -    var message: CdMessage?
   13.12 +    var message: Message?
   13.13  
   13.14      /** All recipients to be able to do a handshake */
   13.15 -    var allRecipientsFiltered = [CdContact]()
   13.16 +    var allRecipientsFiltered = [Identity]()
   13.17  
   13.18      /** A set of accounts from the same user on the device with another email */
   13.19 -    var otherMyselfAccount = NSMutableSet()
   13.20 +    var otherMyselfAccount = Set<Identity>()
   13.21  
   13.22      var firstReload = true
   13.23  
   13.24 @@ -28,30 +30,21 @@
   13.25  
   13.26      override func viewWillAppear(_ animated: Bool) {
   13.27          super.viewWillAppear(animated)
   13.28 +        UIHelper.variableCellHeightsTableView(self.tableView)
   13.29          self.tableView.reloadData()
   13.30  
   13.31 -        let allRecipients: NSMutableOrderedSet?
   13.32 -
   13.33 -        otherMyselfAccount.removeAllObjects()
   13.34 +        otherMyselfAccount.removeAll()
   13.35          allRecipientsFiltered.removeAll()
   13.36 -        UIHelper.variableCellHeightsTableView(self.tableView)
   13.37          if let m = self.message {
   13.38 -            allRecipients = m.allRecipienst().mutableCopy() as? NSMutableOrderedSet
   13.39 -            if let ar = allRecipients {
   13.40 -                if let f = m.from {
   13.41 -                    ar.add(f)
   13.42 -                }
   13.43 -                for contact in ar {
   13.44 -                    if let c = contact as? CdContact {
   13.45 -                        if c.isMySelf.boolValue {
   13.46 -                            if appConfig.currentAccount?.user.address != c.email {
   13.47 -                                allRecipientsFiltered.append(c)
   13.48 -                                otherMyselfAccount.add(c)
   13.49 -                            }
   13.50 -                        } else {
   13.51 -                            allRecipientsFiltered.append(c)
   13.52 -                        }
   13.53 +            let allRecipients = m.allRecipients.sorted { $0.address < $1.address }
   13.54 +            for c in allRecipients {
   13.55 +                if c.isMySelf {
   13.56 +                    if appConfig.currentAccount?.user.address != c.address {
   13.57 +                        allRecipientsFiltered.append(c)
   13.58 +                        otherMyselfAccount.insert(c)
   13.59                      }
   13.60 +                } else {
   13.61 +                    allRecipientsFiltered.append(c)
   13.62                  }
   13.63              }
   13.64          }
   13.65 @@ -83,19 +76,17 @@
   13.66  
   13.67              if let m = message {
   13.68                  cell.backgroundColor = defaultBackground
   13.69 -                if let mailPepColor = m.pepColorRating?.intValue {
   13.70 -                    if let pc = PEPUtil.colorRatingFromInt(mailPepColor) {
   13.71 -                        let privateColor = PEPUtil.colorFromPepRating(pc)
   13.72 -                        if let uiColor = UIHelper.trustWordsCellBackgroundColorFromPepColor(
   13.73 -                            privateColor) {
   13.74 -                            cell.backgroundColor = uiColor
   13.75 -                        }
   13.76 -                        let securityTitleText = PEPUtil.pepTitleFromColor(pc)
   13.77 -                        let lenghtOfSecurityLabel = securityTitleText?.characters.count
   13.78 -                        let attributedString = NSMutableAttributedString(string:securityTitleText!)
   13.79 -                        attributedString.addAttribute(NSLinkAttributeName, value: "https://", range: NSRange(location: 0, length: lenghtOfSecurityLabel!))
   13.80 -                        cell.mailSecurityUILabel.attributedText = attributedString
   13.81 +                if let pEpRating = m.pEpRating {
   13.82 +                    let privateColor = PEPUtil.pEpColorFromRating(pEpRating)
   13.83 +                    if let uiColor = UIHelper.trustWordsCellBackgroundColorFromPepColor(
   13.84 +                        privateColor) {
   13.85 +                        cell.backgroundColor = uiColor
   13.86                      }
   13.87 +                    let securityTitleText = PEPUtil.pEpTitleFromRating(pEpRating)
   13.88 +                    let lenghtOfSecurityLabel = securityTitleText?.characters.count
   13.89 +                    let attributedString = NSMutableAttributedString(string:securityTitleText!)
   13.90 +                    attributedString.addAttribute(NSLinkAttributeName, value: "https://", range: NSRange(location: 0, length: lenghtOfSecurityLabel!))
   13.91 +                    cell.mailSecurityUILabel.attributedText = attributedString
   13.92                  }
   13.93              }
   13.94              return cell
   13.95 @@ -106,11 +97,9 @@
   13.96  
   13.97              cell.mailExplanationSecurityUILabel.text = ""
   13.98              if let m = message {
   13.99 -                if let mailPepColor = m.pepColorRating?.intValue {
  13.100 -                    if let pepColor = PEPUtil.colorRatingFromInt(mailPepColor) {
  13.101 -                        cell.mailExplanationSecurityUILabel.text =
  13.102 -                            PEPUtil.pepExplanationFromColor(pepColor)
  13.103 -                    }
  13.104 +                if let pEpRating = m.pEpRating {
  13.105 +                    cell.mailExplanationSecurityUILabel.text =
  13.106 +                        PEPUtil.pEpExplanationFromRating(pEpRating)
  13.107                  }
  13.108              }
  13.109              return cell
  13.110 @@ -118,11 +107,11 @@
  13.111              let cell = tableView.dequeueReusableCell(withIdentifier: "trustwordsCell",
  13.112                                                             for: indexPath) as! TrustWordsViewCell
  13.113              let contactIndex = (indexPath as NSIndexPath).row-numberOfStaticCells
  13.114 -            let contact: CdContact  = allRecipientsFiltered[contactIndex]
  13.115 +            let contact = allRecipientsFiltered[contactIndex]
  13.116  
  13.117 -            cell.handshakeContactUILabel.text = contact.displayString()
  13.118 +            cell.handshakeContactUILabel.text = contact.displayString
  13.119              cell.handshakeUIButton.tag = contactIndex
  13.120 -            let privacyColor = PEPUtil.privacyColorForContact(contact)
  13.121 +            let privacyColor = PEPUtil.pEpColor(identity: contact)
  13.122              cell.backgroundColor = UIHelper.trustWordsCellBackgroundColorFromPepColor(
  13.123                  privacyColor)
  13.124  
  13.125 @@ -154,11 +143,9 @@
  13.126  
  13.127      @IBAction func showMoreInfo(_ sender: AnyObject) {
  13.128          if let m = message {
  13.129 -            if let mailPepColor = m.pepColorRating?.intValue {
  13.130 -                if let pepColor = PEPUtil.colorRatingFromInt(mailPepColor) {
  13.131 -                    if let suggestion = PEPUtil.pepSuggestionFromColor(pepColor) {
  13.132 -                        self.showSuggestionMessage(suggestion)
  13.133 -                    }
  13.134 +            if let pEpRating = m.pEpRating {
  13.135 +                if let suggestion = PEPUtil.pEpSuggestionFromRating(pEpRating) {
  13.136 +                    self.showSuggestionMessage(suggestion)
  13.137                  }
  13.138              }
  13.139          }
  13.140 @@ -167,9 +154,9 @@
  13.141      @IBAction func goToHandshakeScreen(_ sender: AnyObject) {
  13.142          let contactIndex = sender.tag
  13.143          let contact = allRecipientsFiltered[contactIndex!]
  13.144 -        let pepColor = PEPUtil.privacyColorForContact(contact)
  13.145 +        let pepColor = PEPUtil.pEpColor(identity: contact)
  13.146          if pepColor == PEP_color_red || pepColor == PEP_color_green {
  13.147 -            PEPUtil.resetTrustForContact(contact)
  13.148 +            PEPUtil.resetTrust(identity: contact)
  13.149              self.tableView.reloadData()
  13.150          } else {
  13.151              performSegue(withIdentifier: handshakeSegue, sender: sender)
    14.1 --- a/pEpForiOS/Util/PEPUtil.swift	Tue Oct 25 12:59:55 2016 +0200
    14.2 +++ b/pEpForiOS/Util/PEPUtil.swift	Tue Oct 25 14:33:41 2016 +0200
    14.3 @@ -19,123 +19,123 @@
    14.4      }
    14.5  }
    14.6  
    14.7 -/**
    14.8 - For translating integer values into `PEP_rating`.
    14.9 - */
   14.10 -let pepColorDictionary: [Int32: PEP_rating] =
   14.11 -    [PEP_rating_undefined.rawValue: PEP_rating_undefined,
   14.12 -     PEP_rating_cannot_decrypt.rawValue: PEP_rating_cannot_decrypt,
   14.13 -     PEP_rating_have_no_key.rawValue: PEP_rating_have_no_key,
   14.14 -     PEP_rating_unencrypted.rawValue: PEP_rating_unencrypted,
   14.15 -     PEP_rating_unencrypted_for_some.rawValue:  PEP_rating_unencrypted_for_some,
   14.16 -     PEP_rating_unreliable.rawValue: PEP_rating_unreliable,
   14.17 -     PEP_rating_reliable.rawValue: PEP_rating_reliable,
   14.18 -     PEP_rating_trusted.rawValue: PEP_rating_trusted,
   14.19 -     PEP_rating_trusted_and_anonymized.rawValue: PEP_rating_trusted_and_anonymized,
   14.20 -     PEP_rating_fully_anonymous.rawValue: PEP_rating_fully_anonymous,
   14.21 -     PEP_rating_mistrust.rawValue: PEP_rating_mistrust,
   14.22 -     PEP_rating_b0rken.rawValue: PEP_rating_b0rken,
   14.23 -     PEP_rating_under_attack.rawValue: PEP_rating_under_attack]
   14.24 -
   14.25 -/**
   14.26 - All privacy status strings, i18n ready.
   14.27 - */
   14.28 -let pepPricacyStatusTranslations: [PEP_rating: (String, String, String)] =
   14.29 -    [PEP_rating_under_attack:
   14.30 -        (NSLocalizedString("Under Attack",
   14.31 -            comment: "Privacy status title"),
   14.32 -            NSLocalizedString("This message is not secure and has been tampered with.",
   14.33 -                comment: "Privacy status explanation"),
   14.34 -            NSLocalizedString("Separately verify the content of this message with your communication partner.",
   14.35 -                comment: "Privacy status suggestion")),
   14.36 -     PEP_rating_b0rken:
   14.37 -        (NSLocalizedString("Ooops: Internal problem",
   14.38 -            comment: "Privacy status title"),
   14.39 -            NSLocalizedString("-",
   14.40 -                comment: "Privacy status explanation"),
   14.41 -            NSLocalizedString("-", comment: "")),
   14.42 -     PEP_rating_mistrust:
   14.43 -        (NSLocalizedString("Mistrusted",
   14.44 -            comment: "Privacy status title"),
   14.45 -            NSLocalizedString("This message has a communication partner that has previously been marked as mistrusted.",
   14.46 -                comment: "Privacy status explanation"),
   14.47 -            NSLocalizedString("Re-establish the connection with your communication partner and try to complete another handshake.",
   14.48 -                comment: "Privacy status suggestion")),
   14.49 -        PEP_rating_fully_anonymous:
   14.50 -            (NSLocalizedString("Secure & Trusted",
   14.51 -                comment: "Privacy status title"),
   14.52 -                NSLocalizedString("This message is secure and trusted.",
   14.53 -                    comment: "Privacy status explanation"),
   14.54 -                NSLocalizedString("No action needed!",
   14.55 -                    comment: "Privacy status suggestion")),
   14.56 -        PEP_rating_trusted_and_anonymized:
   14.57 -            (NSLocalizedString("Secure & Trusted",
   14.58 -                comment: "Privacy status title"),
   14.59 -                NSLocalizedString("This message is secure and trusted.",
   14.60 -                    comment: "Privacy status explanation"),
   14.61 -                NSLocalizedString("No action needed!",
   14.62 -                    comment: "Privacy status suggestion")),
   14.63 -        PEP_rating_trusted:
   14.64 -            (NSLocalizedString("Secure & Trusted",
   14.65 -                comment: "Privacy status title"),
   14.66 -                NSLocalizedString("This message is secure and trusted.",
   14.67 -                    comment: "Privacy status explanation"),
   14.68 -                NSLocalizedString("No action needed!",
   14.69 -                    comment: "Privacy status suggestion")),
   14.70 -        PEP_rating_reliable:
   14.71 -            (NSLocalizedString("Secure",
   14.72 -                comment: "Privacy status title"),
   14.73 -                NSLocalizedString("This message is secure but you still need to verify the identity of your communication partner.",
   14.74 -                    comment: "Privacy status explanation"),
   14.75 -                NSLocalizedString("Complete a handshake with your communication partner. A handshake is needed only once per partner and will ensure secure and trusted communication.",
   14.76 -                    comment: "Privacy status suggestion")),
   14.77 -        PEP_rating_unreliable:
   14.78 -            (NSLocalizedString("Unreliable Security",
   14.79 -                comment: "Privacy status title"),
   14.80 -                NSLocalizedString("This message has unreliable protection",
   14.81 -                    comment: "Privacy status explanation"),
   14.82 -                NSLocalizedString("This message has no reliable encryption or no signature. Ask your communication partner to upgrade their encryption solution or install p≡p.",
   14.83 -                    comment: "Privacy status suggestion")),
   14.84 -        PEP_rating_unencrypted_for_some:
   14.85 -            (NSLocalizedString("Unsecure for Some",
   14.86 -                comment: "Privacy status title"),
   14.87 -                NSLocalizedString("This message is unsecure for some communication partners.",
   14.88 -                    comment: "Privacy status explanation"),
   14.89 -                NSLocalizedString("Make sure the privacy status for each communication partner listed is at least secure",
   14.90 -                    comment: "Privacy status suggestion")),
   14.91 -        PEP_rating_unencrypted:
   14.92 -            (NSLocalizedString("Unsecure",
   14.93 -                comment: "Privacy status title"),
   14.94 -                NSLocalizedString("This message is unsecure.",
   14.95 -                    comment: "Privacy status explanation"),
   14.96 -                NSLocalizedString("Please ask your communication partner to use an encryption solution or install p≡p.",
   14.97 -                    comment: "Privacy status suggestion")),
   14.98 -        PEP_rating_have_no_key:
   14.99 -            (NSLocalizedString("Cannot Decrypt",
  14.100 -                comment: "Privacy status title"),
  14.101 -                NSLocalizedString("This message cannot be decrypted because the key is not available.",
  14.102 -                    comment: "Privacy status explanation"),
  14.103 -                NSLocalizedString("If this message was addressed to you, please inform the sender that you don't have the key.",
  14.104 -                    comment: "Privacy status suggestion")),
  14.105 -        PEP_rating_cannot_decrypt:
  14.106 -            (NSLocalizedString("Cannot Decrypt",
  14.107 -                comment: "Privacy status title"),
  14.108 -                NSLocalizedString("This message cannot be decrypted.",
  14.109 -                    comment: "Privacy status explanation"),
  14.110 -                NSLocalizedString("If this message was addressed to you, please inform the sender that you don't have the key.",
  14.111 -                    comment: "Privacy status suggestion")),
  14.112 -        PEP_rating_undefined:
  14.113 -            (NSLocalizedString("Unknown",
  14.114 -                comment: "Privacy status title"),
  14.115 -                NSLocalizedString("This message does not contain enough information to determine if it is secure.",
  14.116 -                    comment: "Privacy status explanation"),
  14.117 -                NSLocalizedString("Please add the necessary information.",
  14.118 -                    comment: "Privacy status suggestion"))]
  14.119 -
  14.120  open class PEPUtil {
  14.121      static let comp = "PEPUtil"
  14.122  
  14.123      /**
  14.124 +     For translating integer values into `PEP_rating`.
  14.125 +     */
  14.126 +    static let pEpRatingDictionary: [Int32: PEP_rating] =
  14.127 +        [PEP_rating_undefined.rawValue: PEP_rating_undefined,
  14.128 +         PEP_rating_cannot_decrypt.rawValue: PEP_rating_cannot_decrypt,
  14.129 +         PEP_rating_have_no_key.rawValue: PEP_rating_have_no_key,
  14.130 +         PEP_rating_unencrypted.rawValue: PEP_rating_unencrypted,
  14.131 +         PEP_rating_unencrypted_for_some.rawValue:  PEP_rating_unencrypted_for_some,
  14.132 +         PEP_rating_unreliable.rawValue: PEP_rating_unreliable,
  14.133 +         PEP_rating_reliable.rawValue: PEP_rating_reliable,
  14.134 +         PEP_rating_trusted.rawValue: PEP_rating_trusted,
  14.135 +         PEP_rating_trusted_and_anonymized.rawValue: PEP_rating_trusted_and_anonymized,
  14.136 +         PEP_rating_fully_anonymous.rawValue: PEP_rating_fully_anonymous,
  14.137 +         PEP_rating_mistrust.rawValue: PEP_rating_mistrust,
  14.138 +         PEP_rating_b0rken.rawValue: PEP_rating_b0rken,
  14.139 +         PEP_rating_under_attack.rawValue: PEP_rating_under_attack]
  14.140 +
  14.141 +    /**
  14.142 +     All privacy status strings, i18n ready.
  14.143 +     */
  14.144 +    static let pEpRatingTranslations: [PEP_rating: (String, String, String)] =
  14.145 +        [PEP_rating_under_attack:
  14.146 +            (NSLocalizedString("Under Attack",
  14.147 +                               comment: "Privacy status title"),
  14.148 +             NSLocalizedString("This message is not secure and has been tampered with.",
  14.149 +                               comment: "Privacy status explanation"),
  14.150 +             NSLocalizedString("Separately verify the content of this message with your communication partner.",
  14.151 +                               comment: "Privacy status suggestion")),
  14.152 +         PEP_rating_b0rken:
  14.153 +            (NSLocalizedString("Ooops: Internal problem",
  14.154 +                               comment: "Privacy status title"),
  14.155 +             NSLocalizedString("-",
  14.156 +                               comment: "Privacy status explanation"),
  14.157 +             NSLocalizedString("-", comment: "")),
  14.158 +         PEP_rating_mistrust:
  14.159 +            (NSLocalizedString("Mistrusted",
  14.160 +                               comment: "Privacy status title"),
  14.161 +             NSLocalizedString("This message has a communication partner that has previously been marked as mistrusted.",
  14.162 +                               comment: "Privacy status explanation"),
  14.163 +             NSLocalizedString("Re-establish the connection with your communication partner and try to complete another handshake.",
  14.164 +                               comment: "Privacy status suggestion")),
  14.165 +         PEP_rating_fully_anonymous:
  14.166 +            (NSLocalizedString("Secure & Trusted",
  14.167 +                               comment: "Privacy status title"),
  14.168 +             NSLocalizedString("This message is secure and trusted.",
  14.169 +                               comment: "Privacy status explanation"),
  14.170 +             NSLocalizedString("No action needed!",
  14.171 +                               comment: "Privacy status suggestion")),
  14.172 +         PEP_rating_trusted_and_anonymized:
  14.173 +            (NSLocalizedString("Secure & Trusted",
  14.174 +                               comment: "Privacy status title"),
  14.175 +             NSLocalizedString("This message is secure and trusted.",
  14.176 +                               comment: "Privacy status explanation"),
  14.177 +             NSLocalizedString("No action needed!",
  14.178 +                               comment: "Privacy status suggestion")),
  14.179 +         PEP_rating_trusted:
  14.180 +            (NSLocalizedString("Secure & Trusted",
  14.181 +                               comment: "Privacy status title"),
  14.182 +             NSLocalizedString("This message is secure and trusted.",
  14.183 +                               comment: "Privacy status explanation"),
  14.184 +             NSLocalizedString("No action needed!",
  14.185 +                               comment: "Privacy status suggestion")),
  14.186 +         PEP_rating_reliable:
  14.187 +            (NSLocalizedString("Secure",
  14.188 +                               comment: "Privacy status title"),
  14.189 +             NSLocalizedString("This message is secure but you still need to verify the identity of your communication partner.",
  14.190 +                               comment: "Privacy status explanation"),
  14.191 +             NSLocalizedString("Complete a handshake with your communication partner. A handshake is needed only once per partner and will ensure secure and trusted communication.",
  14.192 +                               comment: "Privacy status suggestion")),
  14.193 +         PEP_rating_unreliable:
  14.194 +            (NSLocalizedString("Unreliable Security",
  14.195 +                               comment: "Privacy status title"),
  14.196 +             NSLocalizedString("This message has unreliable protection",
  14.197 +                               comment: "Privacy status explanation"),
  14.198 +             NSLocalizedString("This message has no reliable encryption or no signature. Ask your communication partner to upgrade their encryption solution or install p≡p.",
  14.199 +                               comment: "Privacy status suggestion")),
  14.200 +         PEP_rating_unencrypted_for_some:
  14.201 +            (NSLocalizedString("Unsecure for Some",
  14.202 +                               comment: "Privacy status title"),
  14.203 +             NSLocalizedString("This message is unsecure for some communication partners.",
  14.204 +                               comment: "Privacy status explanation"),
  14.205 +             NSLocalizedString("Make sure the privacy status for each communication partner listed is at least secure",
  14.206 +                               comment: "Privacy status suggestion")),
  14.207 +         PEP_rating_unencrypted:
  14.208 +            (NSLocalizedString("Unsecure",
  14.209 +                               comment: "Privacy status title"),
  14.210 +             NSLocalizedString("This message is unsecure.",
  14.211 +                               comment: "Privacy status explanation"),
  14.212 +             NSLocalizedString("Please ask your communication partner to use an encryption solution or install p≡p.",
  14.213 +                               comment: "Privacy status suggestion")),
  14.214 +         PEP_rating_have_no_key:
  14.215 +            (NSLocalizedString("Cannot Decrypt",
  14.216 +                               comment: "Privacy status title"),
  14.217 +             NSLocalizedString("This message cannot be decrypted because the key is not available.",
  14.218 +                               comment: "Privacy status explanation"),
  14.219 +             NSLocalizedString("If this message was addressed to you, please inform the sender that you don't have the key.",
  14.220 +                               comment: "Privacy status suggestion")),
  14.221 +         PEP_rating_cannot_decrypt:
  14.222 +            (NSLocalizedString("Cannot Decrypt",
  14.223 +                               comment: "Privacy status title"),
  14.224 +             NSLocalizedString("This message cannot be decrypted.",
  14.225 +                               comment: "Privacy status explanation"),
  14.226 +             NSLocalizedString("If this message was addressed to you, please inform the sender that you don't have the key.",
  14.227 +                               comment: "Privacy status suggestion")),
  14.228 +         PEP_rating_undefined:
  14.229 +            (NSLocalizedString("Unknown",
  14.230 +                               comment: "Privacy status title"),
  14.231 +             NSLocalizedString("This message does not contain enough information to determine if it is secure.",
  14.232 +                               comment: "Privacy status explanation"),
  14.233 +             NSLocalizedString("Please add the necessary information.",
  14.234 +                               comment: "Privacy status suggestion"))]
  14.235 +
  14.236 +    /**
  14.237       Content type for MIME multipart/alternative.
  14.238       */
  14.239      open static let kMimeTypeMultipartAlternative = "multipart/alternative"
  14.240 @@ -617,47 +617,47 @@
  14.241          let theSession = useOrCreateSession(session)
  14.242          let pepC = pepContact(contact)
  14.243          let color = theSession.identityColor(pepC)
  14.244 -        return colorFromPepRating(color)
  14.245 +        return pEpColorFromRating(color)
  14.246      }
  14.247  
  14.248 -    open static func privacyColor(identity: Identity,
  14.249 +    open static func pEpColor(identity: Identity,
  14.250                                    session: PEPSession? = nil) -> PEP_color {
  14.251          let theSession = useOrCreateSession(session)
  14.252          let pepC = pEp(identity: identity)
  14.253          let color = theSession.identityColor(pepC)
  14.254 -        return colorFromPepRating(color)
  14.255 +        return pEpColorFromRating(color)
  14.256      }
  14.257  
  14.258 -    open static func colorFromPepRating(_ pepColorRating: PEP_rating) -> PEP_color {
  14.259 +    open static func pEpColorFromRating(_ pepColorRating: PEP_rating) -> PEP_color {
  14.260          return color_from_rating(pepColorRating)
  14.261      }
  14.262  
  14.263 -    open static func colorRatingFromInt(_ i: Int?) -> PEP_rating? {
  14.264 +    open static func pEpRatingFromInt(_ i: Int?) -> PEP_rating? {
  14.265          guard let theInt = i else {
  14.266              return nil
  14.267          }
  14.268          let int32 = Int32(theInt)
  14.269 -        return pepColorDictionary[int32]
  14.270 +        return PEPUtil.pEpRatingDictionary[int32]
  14.271      }
  14.272  
  14.273 -    open static func pepTitleFromColor(_ pepColorRating: PEP_rating) -> String? {
  14.274 -        if let (title, _, _) = pepPricacyStatusTranslations[pepColorRating] {
  14.275 +    open static func pEpTitleFromRating(_ pepColorRating: PEP_rating) -> String? {
  14.276 +        if let (title, _, _) = PEPUtil.pEpRatingTranslations[pepColorRating] {
  14.277              return title
  14.278          }
  14.279          Log.warnComponent(comp, "No privacy title for color rating \(pepColorRating)")
  14.280          return nil
  14.281      }
  14.282  
  14.283 -    open static func pepExplanationFromColor(_ pepColorRating: PEP_rating) -> String? {
  14.284 -        if let (_, explanation, _) = pepPricacyStatusTranslations[pepColorRating] {
  14.285 +    open static func pEpExplanationFromRating(_ pepColorRating: PEP_rating) -> String? {
  14.286 +        if let (_, explanation, _) = PEPUtil.pEpRatingTranslations[pepColorRating] {
  14.287              return explanation
  14.288          }
  14.289          Log.warnComponent(comp, "No privacy explanation for color rating \(pepColorRating)")
  14.290          return nil
  14.291      }
  14.292  
  14.293 -    open static func pepSuggestionFromColor(_ pepColorRating: PEP_rating) -> String? {
  14.294 -        if let (_, _, suggestion) = pepPricacyStatusTranslations[pepColorRating] {
  14.295 +    open static func pEpSuggestionFromRating(_ pepColorRating: PEP_rating) -> String? {
  14.296 +        if let (_, _, suggestion) = pEpRatingTranslations[pepColorRating] {
  14.297              return suggestion
  14.298          }
  14.299          Log.warnComponent(comp, "No privacy suggestion for color rating \(pepColorRating)")
  14.300 @@ -686,28 +686,8 @@
  14.301                                                language: String,
  14.302                                                session: PEPSession?) -> String? {
  14.303          let theSession = sessionOrReuse(session)
  14.304 -        let dict1 = NSMutableDictionary.init(dictionary: identity1)
  14.305 -        let dict2 = NSMutableDictionary.init(dictionary: identity2)
  14.306 -        theSession.updateIdentity(dict1)
  14.307 -        theSession.updateIdentity(dict2)
  14.308 -
  14.309 -        guard let fpr1 = dict1[kPepFingerprint] as? String else {
  14.310 -            return nil
  14.311 -        }
  14.312 -        guard let fpr2 = dict2[kPepFingerprint] as? String else {
  14.313 -            return nil
  14.314 -        }
  14.315 -
  14.316 -        let trustwords1 = shortTrustwordsForFpr(fpr1, language: language, session: session)
  14.317 -        let trustwords2 = shortTrustwordsForFpr(fpr2, language: language, session: session)
  14.318 -
  14.319 -        let comp = fpr1.compare(fpr2)
  14.320 -        switch comp {
  14.321 -        case .orderedAscending, .orderedSame:
  14.322 -            return "\(trustwords1) \(trustwords2)"
  14.323 -        default:
  14.324 -            return "\(trustwords2) \(trustwords1)"
  14.325 -        }
  14.326 +        return theSession.getTrustwordsIdentity1(identity1, identity2: identity2,
  14.327 +                                                 language: language, full: true)
  14.328      }
  14.329  
  14.330      /**
  14.331 @@ -803,16 +783,16 @@
  14.332      /**
  14.333       - Returns: The fingerprint for a contact.
  14.334       */
  14.335 -    open static func fingprprintForContact(
  14.336 +    open static func fingerPrintForContact(
  14.337          _ contact: CdContact, session: PEPSession? = nil) -> String? {
  14.338          let pepC = pepContact(contact)
  14.339 -        return fingprprintForPepContact(pepC)
  14.340 +        return fingerPrintForPepContact(pepC)
  14.341      }
  14.342  
  14.343      /**
  14.344       - Returns: The fingerprint for a pEp contact.
  14.345       */
  14.346 -    open static func fingprprintForPepContact(
  14.347 +    open static func fingerPrintForPepContact(
  14.348          _ contact: PEPContact, session: PEPSession? = nil) -> String? {
  14.349          let pepDict = NSMutableDictionary.init(dictionary: contact)
  14.350  
  14.351 @@ -822,6 +802,18 @@
  14.352          return pepDict[kPepFingerprint] as? String
  14.353      }
  14.354  
  14.355 +    open static func fingerPrint(identity: Identity, session: PEPSession? = nil) -> String? {
  14.356 +        if let fpr = identity.fingerPrint {
  14.357 +            return fpr
  14.358 +        }
  14.359 +
  14.360 +        let theSession = useOrCreateSession(session)
  14.361 +        let pEpID = pEp(identity: identity)
  14.362 +        let pEpDict = NSMutableDictionary.init(dictionary: pEpID)
  14.363 +        theSession.updateIdentity(pEpDict)
  14.364 +        return pEpDict[kPepFingerprint] as? String
  14.365 +    }
  14.366 +
  14.367      /**
  14.368       Trust that contact (yellow to green).
  14.369       */
  14.370 @@ -833,6 +825,16 @@
  14.371      }
  14.372  
  14.373      /**
  14.374 +     Trust that contact (yellow to green).
  14.375 +     */
  14.376 +    open static func trust(identity: Identity, session: PEPSession? = nil) {
  14.377 +        let theSession = useOrCreateSession(session)
  14.378 +        let pepC = NSMutableDictionary.init(dictionary: pEp(identity: identity))
  14.379 +        theSession.updateIdentity(pepC)
  14.380 +        theSession.trustPersonalKey(pepC)
  14.381 +    }
  14.382 +
  14.383 +    /**
  14.384       Mistrust the identity (yellow to red)
  14.385       */
  14.386      open static func mistrustContact(_ contact: CdContact, session: PEPSession? = nil) {
  14.387 @@ -843,6 +845,16 @@
  14.388      }
  14.389  
  14.390      /**
  14.391 +     Mistrust the identity (yellow to red)
  14.392 +     */
  14.393 +    open static func mistrust(identity: Identity, session: PEPSession? = nil) {
  14.394 +        let theSession = useOrCreateSession(session)
  14.395 +        let pepC = NSMutableDictionary.init(dictionary: pEp(identity: identity))
  14.396 +        theSession.updateIdentity(pepC)
  14.397 +        theSession.keyMistrusted(pepC)
  14.398 +    }
  14.399 +
  14.400 +    /**
  14.401       Resets the trust for the given contact. Use both for trusting again after
  14.402       mistrusting a key, and for mistrusting a key after you have first trusted it.
  14.403       */
  14.404 @@ -854,6 +866,17 @@
  14.405      }
  14.406  
  14.407      /**
  14.408 +     Resets the trust for the given `Identity`. Use both for trusting again after
  14.409 +     mistrusting a key, and for mistrusting a key after you have first trusted it.
  14.410 +     */
  14.411 +    open static func resetTrust(identity: Identity, session: PEPSession? = nil) {
  14.412 +        let theSession = useOrCreateSession(session)
  14.413 +        let pepC = NSMutableDictionary.init(dictionary: pEp(identity: identity))
  14.414 +        theSession.updateIdentity(pepC)
  14.415 +        theSession.keyResetTrust(pepC)
  14.416 +    }
  14.417 +
  14.418 +    /**
  14.419       Checks the given pEp status and the given encrypted mail for errors and
  14.420       logs them.
  14.421       - Returns: A tuple of the encrypted mail and an error. Both can be nil.
    15.1 --- a/pEpForiOS/Util/ReplyUtil.swift	Tue Oct 25 12:59:55 2016 +0200
    15.2 +++ b/pEpForiOS/Util/ReplyUtil.swift	Tue Oct 25 14:33:41 2016 +0200
    15.3 @@ -8,15 +8,17 @@
    15.4  
    15.5  import UIKit
    15.6  
    15.7 +import MessageModel
    15.8 +
    15.9  public struct ReplyUtil {
   15.10      static let nameSeparator = ", "
   15.11      static let newline = "\n"
   15.12  
   15.13 -    public static func replyNameFromContact(_ contact: CdContact) -> String {
   15.14 -        if let name = contact.name {
   15.15 +    public static func replyNameFromIdentity(_ identity: Identity) -> String {
   15.16 +        if let name = identity.userName {
   15.17              return name
   15.18          }
   15.19 -        return contact.email
   15.20 +        return identity.address
   15.21      }
   15.22  
   15.23      public static func quoteText(_ text: String) -> String {
   15.24 @@ -29,28 +31,30 @@
   15.25          return quotedText
   15.26      }
   15.27  
   15.28 -    public static func citationHeaderForMessage(_ message: CdMessage, replyAll: Bool) -> String {
   15.29 +    public static func citationHeaderForMessage(_ message: Message, replyAll: Bool) -> String {
   15.30          let dateFormatter = DateFormatter.init()
   15.31          dateFormatter.dateStyle = DateFormatter.Style.long
   15.32          dateFormatter.timeStyle = DateFormatter.Style.long
   15.33  
   15.34 -        let theDate = message.receivedDate
   15.35 +        let theDate = message.received
   15.36  
   15.37          var theNames = [String]()
   15.38          if replyAll {
   15.39 -            let contacts = message.allRecipienst().array
   15.40 +            let contacts = message.allRecipients
   15.41              theNames.append(
   15.42 -                contentsOf: contacts.map() { return replyNameFromContact($0 as! CdContact) })
   15.43 +                contentsOf: contacts.map() { return replyNameFromIdentity($0) })
   15.44          } else {
   15.45              if let from = message.from {
   15.46 -                theNames.append(replyNameFromContact(from))
   15.47 +                theNames.append(replyNameFromIdentity(from))
   15.48              }
   15.49          }
   15.50  
   15.51          if theNames.count == 0 {
   15.52              if let rd = theDate {
   15.53 -                return String.init(format: NSLocalizedString("Someone wrote on %@:", comment: "Reply to unknown sender with date"),
   15.54 -                                   dateFormatter.string(from: rd as Date))
   15.55 +                return String.init(
   15.56 +                    format: NSLocalizedString("Someone wrote on %@:",
   15.57 +                                              comment: "Reply to unknown sender with date"),
   15.58 +                    dateFormatter.string(from: rd as Date))
   15.59              } else {
   15.60                  return NSLocalizedString("Someone wrote:",
   15.61                                           comment: "Reply to unknown sender without date")
   15.62 @@ -89,7 +93,7 @@
   15.63                                   comment: "Mail footer/default text")
   15.64      }
   15.65  
   15.66 -    public static func quotedMailTextForMail(_ mail: CdMessage, replyAll: Bool) -> String {
   15.67 +    public static func quotedMailTextForMail(_ mail: Message, replyAll: Bool) -> String {
   15.68          if let text = mail.longMessage {
   15.69              let quotedText = quoteText(text)
   15.70              let citation: String? = citationHeaderForMessage(mail, replyAll: replyAll)
   15.71 @@ -100,8 +104,8 @@
   15.72          return footer()
   15.73      }
   15.74  
   15.75 -    public static func replySubjectForMail(_ mail: CdMessage) -> String {
   15.76 -        if let subject = mail.subject {
   15.77 +    public static func replySubjectForMail(_ mail: Message) -> String {
   15.78 +        if let subject = mail.shortMessage {
   15.79              let re = NSLocalizedString(
   15.80                  "Re: ", comment: "The 'Re:' that gets appended to the subject line")
   15.81              return "\(re) \(subject)"