merge refactor IOS-1469
authorAlejandro Gelos <agp@pep.security>
Mon, 18 Mar 2019 10:54:14 +0100
branchIOS-1469
changeset 80156de02130d308
parent 7747 0ef7496f38b1
parent 7975 0687a4a6d8c2
child 8016 c7c6910a6614
merge refactor
pEpForiOS/Background/Error/BackgroundError.swift
pEpForiOS/Background/Error/ServiceErrorProtocol.swift
pEpForiOS/Background/FetchMessagesOperation.swift
pEpForiOS/Background/SelfReferencingOperation.swift
pEpForiOS/Background/StoreFolderOperation.swift
pEpForiOS/Error/ErrorPropagator.swift
pEpForiOS/Network/ConnectInfo/EmailConnectInfo.swift
pEpForiOS/Network/Service/FetchNumberOfNewMailsService.swift
pEpForiOS/Network/Service/ImapConnectionDataCache.swift
pEpForiOS/Network/Service/LoginImapOperation.swift
pEpForiOS/Network/Service/LoginSmtpOperation.swift
pEpForiOS/Network/Service/ServiceUtil.swift
pEpForiOS/Network/Service/SharedObjects.swift
pEpForiOS/UI/Util/CGImageSource+Extension.swift
pEpForiOS/UI/Util/CGRect+Util.swift
pEpForiOS/UI/Util/CGSize+Extension.swift
pEpForiOS/UI/Util/CredentialTextField.swift
pEpForiOS/UI/Util/UIAlertController+Extension.swift
pEpForiOS/UI/Util/UIBarButtonItem+Extension.swift
pEpForiOS/UI/Util/UIButton+Extension.swift
pEpForiOS/UI/Util/UIColor+Extension.swift
pEpForiOS/UI/Util/UIImage+Extension.swift
pEpForiOS/UI/Util/UIImage+GIF.swift
pEpForiOS/UI/Util/UIImageView+Extension.swift
pEpForiOS/UI/Util/UINavigationController+Extensions.swift
pEpForiOS/UI/Util/UITableView+Extension.swift
pEpForiOS/UI/Util/UITextField+Extension.swift
pEpForiOS/UI/Util/UIView+Autolayout.swift
pEpForiOS/UI/Util/UIView+Util.swift
pEpForiOS/UI/Util/UIViewController+Extension.swift
pEpForiOS/Util/AsyncStateMachine.swift
pEpForiOS/Util/AsyncStateMachineProtocol.swift
pEpForiOS/Util/BackgroundTaskProtocol.swift
pEpForiOS/Util/Extensions/Array+SortingAndSearching.swift
pEpForiOS/Util/Extensions/Data+Extensions.swift
pEpForiOS/Util/Extensions/Date+Extension.swift
pEpForiOS/Util/Extensions/NSAttributedString+Extensions.swift
pEpForiOS/Util/Extensions/NSAttributedString+Parsing.swift
pEpForiOS/Util/Extensions/NSRegularExpression+Extension.swift
pEpForiOS/Util/Extensions/OperationQueue+Extension.swift
pEpForiOS/Util/Extensions/String+Email.swift
pEpForiOS/Util/Extensions/String+Extensions.swift
pEpForiOS/Util/Extensions/Thread+Extension.swift
pEpForiOS/Util/GCD.swift
pEpForiOS/Util/KickOffMySelfProtocol.swift
pEpForiOS/Util/Log+ASL/Log+ASL.swift
pEpForiOS/Util/Log.swift
pEpForiOS/Util/Logger.swift
pEpForiOS/Util/MiscUtil.swift
pEpForiOS/Util/SegueHandlerType.swift
pEpForiOS/Util/SortedSet.swift
pEpForiOS/Util/Tuple.swift
pEpForiOS/Util/Weak.swift
pEpForiOSTests/SortedSetTest.swift
     1.1 --- a/.hgtags	Wed Feb 20 11:00:07 2019 +0100
     1.2 +++ b/.hgtags	Mon Mar 18 10:54:14 2019 +0100
     1.3 @@ -52,3 +52,4 @@
     1.4  0bb233ebdff57c4d56af32e918df1565de9d5ebd v0.0.41
     1.5  e6f3a95032a7f1178d5b7667716cd0d91ec9c4c8 v0.0.41_b2
     1.6  43bb6db6c495713868e09008abe1aae32c1e2251 v0.0.41_b3
     1.7 +b1a210a695e21af4f626d5e612c16aa7cac15e78 v0.0.42_b1
     2.1 --- a/CHANGESETS	Wed Feb 20 11:00:07 2019 +0100
     2.2 +++ b/CHANGESETS	Mon Mar 18 10:54:14 2019 +0100
     2.3 @@ -1,9 +1,9 @@
     2.4 -v0.0.41_b3
     2.5 -pEpEngine 0d3e23fbdaec
     2.6 -pEpObjCAdapter b0785b78c8e8
     2.7 +v0.0.42_b1
     2.8 +pEpEngine f344cad791f2 (sync)
     2.9 +pEpObjCAdapter f5eeb38557f3
    2.10  netpgp-et 8848ce82014d
    2.11 -MessageModel 9675c5dabc4b
    2.12 -pantomime-iOS b03f347f2576
    2.13 +MessageModel 20449892372f
    2.14 +pantomime-iOS e05d5f2d02bc
    2.15  libAccountSettings 3d94e78b587e
    2.16  ldns 70cfa2739c2a71db098e738d2fd16ae1025b2362
    2.17  OpenSSL-for-iPhone 10019638e80e8a8a5fc19642a840d8a69fac7349
     3.1 --- a/README.md	Wed Feb 20 11:00:07 2019 +0100
     3.2 +++ b/README.md	Mon Mar 18 10:54:14 2019 +0100
     3.3 @@ -20,7 +20,7 @@
     3.4  sudo port install py27-lxml
     3.5  
     3.6  sudo port install python_select
     3.7 -sudo port select python python27
     3.8 +0
     3.9  
    3.10  sudo port install autoconf
    3.11  sudo port install libtool
    3.12 @@ -61,13 +61,6 @@
    3.13  hg clone https://pep.foundation/dev/repos/libAccountSettings/
    3.14  
    3.15  hg clone https://pep-security.ch/dev/repos/pEp_for_iOS/
    3.16 -
    3.17 -# Temp hot fix
    3.18 -cd ~/ldns
    3.19 -git checkout IOS-749
    3.20 -cd ..
    3.21 -cd ~/SwipeCellKit
    3.22 -git checkout master
    3.23  ```
    3.24  
    3.25  ### Build Project
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/Submodules/pEpIOSToolbox/pEpIOSToolbox/Foundation/GCD.swift	Mon Mar 18 10:54:14 2019 +0100
     4.3 @@ -0,0 +1,32 @@
     4.4 +//
     4.5 +//  GCD.swift
     4.6 +//  pEpForiOS
     4.7 +//
     4.8 +//  Created by Dirk Zimmermann on 20/04/16.
     4.9 +//  Copyright © 2016 p≡p Security S.A. All rights reserved.
    4.10 +//
    4.11 +import Foundation
    4.12 +
    4.13 +public struct GCD {
    4.14 +    /**
    4.15 +     Since you will do this all the time in UI callbacks.
    4.16 +     */
    4.17 +    public static func onMain(_ block: @escaping () -> Void) {
    4.18 +        DispatchQueue.main.async(execute: {
    4.19 +            block()
    4.20 +        })
    4.21 +    }
    4.22 +
    4.23 +    /**
    4.24 +     Since you will do this all the time in UI callbacks.
    4.25 +     */
    4.26 +    public static func onMainWait(_ block: @escaping () -> Void) {
    4.27 +        if Thread.isMainThread {
    4.28 +            block()
    4.29 +        } else {
    4.30 +            DispatchQueue.main.sync(execute: {
    4.31 +                block()
    4.32 +            })
    4.33 +        }
    4.34 +    }
    4.35 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/Submodules/pEpIOSToolbox/pEpIOSToolbox/Other/Logger.swift	Mon Mar 18 10:54:14 2019 +0100
     5.3 @@ -0,0 +1,337 @@
     5.4 +//
     5.5 +//  Logger.swift
     5.6 +//  pEp
     5.7 +//
     5.8 +//  Created by Dirk Zimmermann on 18.12.18.
     5.9 +//  Copyright © 2018 p≡p Security S.A. All rights reserved.
    5.10 +//
    5.11 +
    5.12 +import Foundation
    5.13 +import os.log
    5.14 +
    5.15 +/**
    5.16 + Thin layer over `os_log` where not available.
    5.17 + */
    5.18 +@available(iOS 10.0, macOS 10.12, tvOS 10.0, watchOS 3.0, *)
    5.19 +public class Logger {
    5.20 +    /**
    5.21 +     Map `os_log` levels.
    5.22 +     */
    5.23 +    public enum Severity {
    5.24 +        /**
    5.25 +         - Note: Not persisted by default, but will be written in case of errors.
    5.26 +         */
    5.27 +        case info
    5.28 +
    5.29 +        /**
    5.30 +         - Note: Not persisted by default, but will be written in case of errors.
    5.31 +         */
    5.32 +        case debug
    5.33 +
    5.34 +        /**
    5.35 +         This is the lowest priority that gets written to disk by default.
    5.36 +         Used like WARN in this logger.
    5.37 +         */
    5.38 +        case `default`
    5.39 +
    5.40 +        case error
    5.41 +
    5.42 +        /**
    5.43 +         - Note: As this is referring to inter-process problems, I don't see a use-case
    5.44 +         for iOS.
    5.45 +         */
    5.46 +        case fault
    5.47 +
    5.48 +        public func osLogType() -> OSLogType {
    5.49 +            switch self {
    5.50 +            case .info:
    5.51 +                return .info
    5.52 +            case .debug:
    5.53 +                return .debug
    5.54 +            case .default:
    5.55 +                return .default
    5.56 +            case .error:
    5.57 +                return .error
    5.58 +            case .fault:
    5.59 +                return .fault
    5.60 +            }
    5.61 +        }
    5.62 +    }
    5.63 +
    5.64 +    //!!!: remove this loggers  from to the app if any
    5.65 +
    5.66 +    @available(*, deprecated, message: "Instead create a singleton per Xcode project (Module) yourself")
    5.67 +    public static let frontendLogger = Logger(category: "frontend")
    5.68 +    @available(*, deprecated, message: "Instead create a singleton per Xcode project (Module) yourself")
    5.69 +    public static let backendLogger = Logger(category: "backend")
    5.70 +    @available(*, deprecated, message: "Instead create a singleton per Xcode project (Module) yourself")
    5.71 +    public static let utilLogger = Logger(category: "util")
    5.72 +    @available(*, deprecated, message: "Instead create a singleton per Xcode project (Module) yourself")
    5.73 +    public static let htmlParsingLogger = Logger(category: "htmlParsing")
    5.74 +    @available(*, deprecated, message: "Instead create a singleton per Xcode project (Module) yourself")
    5.75 +    public static let modelLogger = Logger(category: "model")
    5.76 +    @available(*, deprecated, message: "Instead create a singleton per Xcode project (Module) yourself")
    5.77 +    public static let appDelegateLogger = Logger(category: "appDelegate")
    5.78 +
    5.79 +    public init(subsystem: String = "security.pEp.app.iOS", category: String) {
    5.80 +        self.subsystem = subsystem
    5.81 +        self.category = category
    5.82 +        osLogger = OSLog(subsystem: subsystem, category: category)
    5.83 +    }
    5.84 +
    5.85 +    /**
    5.86 +     Logs to default.
    5.87 +     */
    5.88 +    public func log(function: String = #function,
    5.89 +                    filePath: String = #file,
    5.90 +                    fileLine: Int = #line,
    5.91 +                    _ message: StaticString,
    5.92 +                    _ args: CVarArg...) {
    5.93 +        saveLog(message: message,
    5.94 +                severity: .default,
    5.95 +                function: function,
    5.96 +                filePath: filePath,
    5.97 +                fileLine: fileLine,
    5.98 +                args: args)
    5.99 +    }
   5.100 +
   5.101 +    /**
   5.102 +     os_log doesn't have a warn per se, but default is coming close.
   5.103 +     This is the same as log.
   5.104 +     */
   5.105 +    public func warn(function: String = #function,
   5.106 +                     filePath: String = #file,
   5.107 +                     fileLine: Int = #line,
   5.108 +                     _ message: StaticString,
   5.109 +                     _ args: CVarArg...) {
   5.110 +        saveLog(message: message,
   5.111 +                severity: .default,
   5.112 +                function: function,
   5.113 +                filePath: filePath,
   5.114 +                fileLine: fileLine,
   5.115 +                args: args)
   5.116 +    }
   5.117 +
   5.118 +    /**
   5.119 +     Logs to info.
   5.120 +     */
   5.121 +    public func info(function: String = #function,
   5.122 +                     filePath: String = #file,
   5.123 +                     fileLine: Int = #line,
   5.124 +                     _ message: StaticString,
   5.125 +                     _ args: CVarArg...) {
   5.126 +        saveLog(message: message,
   5.127 +                severity: .info,
   5.128 +                function: function,
   5.129 +                filePath: filePath,
   5.130 +                fileLine: fileLine,
   5.131 +                args: args)
   5.132 +    }
   5.133 +
   5.134 +    /**
   5.135 +     Logs to debug.
   5.136 +     */
   5.137 +    public func debug(function: String = #function,
   5.138 +                      filePath: String = #file,
   5.139 +                      fileLine: Int = #line,
   5.140 +                      _ message: StaticString,
   5.141 +                      _ args: CVarArg...) {
   5.142 +        saveLog(message: message,
   5.143 +                severity: .debug,
   5.144 +                function: function,
   5.145 +                filePath: filePath,
   5.146 +                fileLine: fileLine,
   5.147 +                args: args)
   5.148 +    }
   5.149 +
   5.150 +    /**
   5.151 +     Logs to error.
   5.152 +     */
   5.153 +    public func error(function: String = #function,
   5.154 +                      filePath: String = #file,
   5.155 +                      fileLine: Int = #line,
   5.156 +                      _ message: StaticString,
   5.157 +                      _ args: CVarArg...) {
   5.158 +        saveLog(message: message,
   5.159 +                severity: .error,
   5.160 +                function: function,
   5.161 +                filePath: filePath,
   5.162 +                fileLine: fileLine,
   5.163 +                args: args)
   5.164 +    }
   5.165 +
   5.166 +    /**
   5.167 +     Logs to fault.
   5.168 +     */
   5.169 +    public func fault(function: String = #function,
   5.170 +                      filePath: String = #file,
   5.171 +                      fileLine: Int = #line,
   5.172 +                      _ message: StaticString,
   5.173 +                      _ args: CVarArg...) {
   5.174 +        saveLog(message: message,
   5.175 +                severity: .fault,
   5.176 +                function: function,
   5.177 +                filePath: filePath,
   5.178 +                fileLine: fileLine,
   5.179 +                args: args)
   5.180 +    }
   5.181 +
   5.182 +    public func errorAndCrash(function: String = #function,
   5.183 +                              filePath: String = #file,
   5.184 +                              fileLine: Int = #line,
   5.185 +                              _ message: StaticString,
   5.186 +                              _ args: CVarArg...) {
   5.187 +        saveLog(message: message,
   5.188 +                severity: .fault,
   5.189 +                function: function,
   5.190 +                filePath: filePath,
   5.191 +                fileLine: fileLine,
   5.192 +                args: args)
   5.193 +
   5.194 +        SystemUtils.crash("\(filePath):\(function):\(fileLine) - \(message)")
   5.195 +    }
   5.196 +
   5.197 +    /**
   5.198 +     Logs an error.
   5.199 +     */
   5.200 +    public func log(function: String = #function,
   5.201 +                    filePath: String = #file,
   5.202 +                    fileLine: Int = #line,
   5.203 +                    error: Error) {
   5.204 +        // Error is not supported by "%@", because it doesn't conform to CVArg
   5.205 +        // and CVArg is only meant for internal types.
   5.206 +        // An alternative would be to use localizedDescription(),
   5.207 +        // but if they are indeed localized you end up with international
   5.208 +        // log messages.
   5.209 +        // So we wrap it into an NSError which does suppord CVArg.
   5.210 +        let nsErr = NSError(domain: subsystem, code: 0, userInfo: [NSUnderlyingErrorKey: error])
   5.211 +
   5.212 +        saveLog(message: "%{public}@",
   5.213 +                severity: .default,
   5.214 +                function: function,
   5.215 +                filePath: filePath,
   5.216 +                fileLine: fileLine,
   5.217 +                args: [nsErr])
   5.218 +    }
   5.219 +
   5.220 +    /**
   5.221 +     Since this kind of logging is used so often in the codebase, it has its
   5.222 +     own method.
   5.223 +     */
   5.224 +    public func lostMySelf() {
   5.225 +        errorAndCrash("Lost MySelf")
   5.226 +    }
   5.227 +
   5.228 +    private let subsystem: String
   5.229 +    private let category: String
   5.230 +
   5.231 +    private let osLogger: Any?
   5.232 +
   5.233 +    private func saveLog(message: StaticString,
   5.234 +                         severity: Severity,
   5.235 +                         function: String = #function,
   5.236 +                         filePath: String = #file,
   5.237 +                         fileLine: Int = #line,
   5.238 +                         args: [CVarArg]) {
   5.239 +        osLog(message: message,
   5.240 +              severity: severity,
   5.241 +              function: function,
   5.242 +              filePath: filePath,
   5.243 +              fileLine: fileLine,
   5.244 +              args: args)
   5.245 +    }
   5.246 +
   5.247 +    /**
   5.248 +     - Note: If the number of arguments to the format string exceeds 10,
   5.249 +     the logging doesn't work correctly. Can be easily fixed though, if really needed.
   5.250 +     */
   5.251 +    private func osLog(message: StaticString,
   5.252 +                       severity: Severity,
   5.253 +                       function: String = #function,
   5.254 +                       filePath: String = #file,
   5.255 +                       fileLine: Int = #line,
   5.256 +                       args: [CVarArg]) {
   5.257 +        let theLog = osLogger as! OSLog
   5.258 +        let theType = severity.osLogType()
   5.259 +
   5.260 +        // I haven't found a way of injecting `function` etc. into the original message for
   5.261 +        // just one call to `os_log`, so the 'position' is logged on a separate line.
   5.262 +        os_log("%@:%d %@:",
   5.263 +               log: theLog,
   5.264 +               type: theType,
   5.265 +               filePath,
   5.266 +               fileLine,
   5.267 +               function)
   5.268 +
   5.269 +        // We have to expand the array of arguments into positional ones.
   5.270 +        // There is no attempt of trying to format the string on our side
   5.271 +        // in order to make use of `os_log`'s fast 'offline' formatting
   5.272 +        // (that is, the work is delayed until actual log display).
   5.273 +        switch args.count {
   5.274 +        case 0:
   5.275 +            os_log(message,
   5.276 +                   log: theLog,
   5.277 +                   type: theType)
   5.278 +        case 1:
   5.279 +            os_log(message,
   5.280 +                   log: theLog,
   5.281 +                   type: theType,
   5.282 +                   args[0])
   5.283 +        case 2:
   5.284 +            os_log(message,
   5.285 +                   log: theLog,
   5.286 +                   type: theType,
   5.287 +                   args[0], args[1])
   5.288 +        case 3:
   5.289 +            os_log(message,
   5.290 +                   log: theLog,
   5.291 +                   type: theType,
   5.292 +                   args[0], args[1], args[2])
   5.293 +        case 4:
   5.294 +            os_log(message,
   5.295 +                   log: theLog,
   5.296 +                   type: theType,
   5.297 +                   args[0], args[1], args[2], args[3])
   5.298 +        case 5:
   5.299 +            os_log(message,
   5.300 +                   log: theLog,
   5.301 +                   type: theType,
   5.302 +                   args[0], args[1], args[2], args[3], args[4])
   5.303 +        case 6:
   5.304 +            os_log(message,
   5.305 +                   log: theLog,
   5.306 +                   type: theType,
   5.307 +                   args[0], args[1], args[2], args[3], args[4], args[5])
   5.308 +        case 7:
   5.309 +            os_log(message,
   5.310 +                   log: theLog,
   5.311 +                   type: theType,
   5.312 +                   args[0], args[1], args[2], args[3], args[4], args[5], args[6])
   5.313 +        case 8:
   5.314 +            os_log(message,
   5.315 +                   log: theLog,
   5.316 +                   type: theType,
   5.317 +                   args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7])
   5.318 +        case 9:
   5.319 +            os_log(message,
   5.320 +                   log: theLog,
   5.321 +                   type: theType,
   5.322 +                   args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7],
   5.323 +                   args[8])
   5.324 +        case 10:
   5.325 +            os_log(message,
   5.326 +                   log: theLog,
   5.327 +                   type: theType,
   5.328 +                   args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7],
   5.329 +                   args[8], args[9])
   5.330 +        default:
   5.331 +            os_log("Using more than 10 parameters",
   5.332 +                   log: theLog,
   5.333 +                   type: .error)
   5.334 +            os_log(message,
   5.335 +                   log: theLog,
   5.336 +                   type: theType,
   5.337 +                   args)
   5.338 +        }
   5.339 +    }
   5.340 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/Submodules/pEpIOSToolbox/pEpIOSToolbox/Other/MiscUtil.swift	Mon Mar 18 10:54:14 2019 +0100
     6.3 @@ -0,0 +1,36 @@
     6.4 +//
     6.5 +//  MiscUtil.swift
     6.6 +//  pEpForiOS
     6.7 +//
     6.8 +//  Created by Dirk Zimmermann on 27/06/16.
     6.9 +//  Copyright © 2016 p≡p Security S.A. All rights reserved.
    6.10 +//
    6.11 +import Foundation
    6.12 +
    6.13 +open class MiscUtil {
    6.14 +    public static func optionalHashValue<T: Hashable>(_ someVar: T?) -> Int {
    6.15 +        if let theVar = someVar {
    6.16 +            return theVar.hashValue
    6.17 +        } else {
    6.18 +            return 0
    6.19 +        }
    6.20 +    }
    6.21 +
    6.22 +    public static func isNilOrEmptyNSArray(_ array: NSArray?) -> Bool {
    6.23 +        return array == nil || array?.count == 0
    6.24 +    }
    6.25 +
    6.26 +    public static func isEmptyString(_ s: String?) -> Bool {
    6.27 +        if s == nil {
    6.28 +            return true
    6.29 +        }
    6.30 +        if s?.count == 0 {
    6.31 +            return true
    6.32 +        }
    6.33 +        return false
    6.34 +    }
    6.35 +
    6.36 +    public static func isUnitTest() -> Bool {
    6.37 +        return ProcessInfo.processInfo.environment["XCTestConfigurationFilePath"] != nil
    6.38 +    }
    6.39 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/Submodules/pEpIOSToolbox/pEpIOSToolbox/Other/SortedSet.swift	Mon Mar 18 10:54:14 2019 +0100
     7.3 @@ -0,0 +1,219 @@
     7.4 +//
     7.5 +//  SortedSet.swift
     7.6 +//  pEp
     7.7 +//
     7.8 +//  Created by Andreas Buff on 02.10.17.
     7.9 +//  Copyright © 2017 p≡p Security S.A. All rights reserved.
    7.10 +//
    7.11 +
    7.12 +import UIKit
    7.13 +
    7.14 +/// Automatically keeps containted objects sorted to the criteria of a given sort block.
    7.15 +/// The implementation is completely trival and unperformant.
    7.16 +/// Has to be improved if this causes performance issue in the app.
    7.17 +public class SortedSet<T: Equatable>: Sequence {
    7.18 +    // MARK: - Public API
    7.19 +
    7.20 +    public typealias SortBlock = (_ first: T,_  second: T) -> ComparisonResult
    7.21 +
    7.22 +    public var count: Int {
    7.23 +        return set.count
    7.24 +    }
    7.25 +    
    7.26 +    public init(array: [T], sortBlock block: @escaping SortBlock) {
    7.27 +        set = NSMutableOrderedSet(array: array)
    7.28 +        sortBlock = block
    7.29 +        sort()
    7.30 +    }
    7.31 +    
    7.32 +    /// Inserts an object keeping the Set sorted. Returns the index it has been inserted to.
    7.33 +    ///
    7.34 +    /// - Parameter object: object to insert
    7.35 +    /// - Returns: index the object has been inserted to
    7.36 +    @discardableResult public func insert(object: T) -> Int {
    7.37 +        objc_sync_enter(self)
    7.38 +        defer { objc_sync_exit(self) }
    7.39 +
    7.40 +        let idx = indexOfObjectIfInserted(obj: object)
    7.41 +        set.insert(object, at: idx)
    7.42 +        return idx
    7.43 +    }
    7.44 +    
    7.45 +    public func remove(object: T) {
    7.46 +        objc_sync_enter(self)
    7.47 +        defer { objc_sync_exit(self) }
    7.48 +
    7.49 +        set.remove(object)
    7.50 +    }
    7.51 +    
    7.52 +    public func removeObject(at index: Int) {
    7.53 +        objc_sync_enter(self)
    7.54 +        defer { objc_sync_exit(self) }
    7.55 +
    7.56 +        guard isValidIndex(index) else {
    7.57 +            Logger.frontendLogger.errorAndCrash("Index out of range")
    7.58 +            return
    7.59 +        }
    7.60 +        set.removeObject(at: index)
    7.61 +    }
    7.62 +    
    7.63 +    public func replaceObject(at index: Int, with object: T) {
    7.64 +        objc_sync_enter(self)
    7.65 +        defer { objc_sync_exit(self) }
    7.66 +
    7.67 +        guard isValidIndex(index) else {
    7.68 +            Logger.frontendLogger.errorAndCrash("Index out of range")
    7.69 +            return
    7.70 +        }
    7.71 +        set.replaceObject(at: index, with: object)
    7.72 +    }
    7.73 +
    7.74 +    public func object(at index: Int) -> T? {
    7.75 +        objc_sync_enter(self)
    7.76 +        defer { objc_sync_exit(self) }
    7.77 +
    7.78 +        guard isValidIndex(index) else {
    7.79 +            Logger.frontendLogger.errorAndCrash("Index out of range")
    7.80 +            return nil
    7.81 +        }
    7.82 +
    7.83 +        return set.object(at: index) as? T
    7.84 +    }
    7.85 +
    7.86 +    /**
    7.87 +     - Returns: The index of `object` or nil.
    7.88 +     */
    7.89 +    public func index(of object: T) -> Int? {
    7.90 +        let idx = indexOrNotFound(of: object)
    7.91 +        if idx != NSNotFound {
    7.92 +            return idx
    7.93 +        } else {
    7.94 +            return nil
    7.95 +        }
    7.96 +    }
    7.97 +
    7.98 +    /**
    7.99 +     - Returns: The index of `object` or NSNotFound.
   7.100 +     */
   7.101 +    public func indexOrNotFound(of object: T) -> Int {
   7.102 +        objc_sync_enter(self)
   7.103 +        defer { objc_sync_exit(self) }
   7.104 +
   7.105 +        for i in 0..<set.count {
   7.106 +            guard let testee = set.object(at: i) as? T else {
   7.107 +                Logger.frontendLogger.errorAndCrash("error casting")
   7.108 +                return NSNotFound
   7.109 +            }
   7.110 +            if testee == object {
   7.111 +                return i
   7.112 +            }
   7.113 +        }
   7.114 +        return NSNotFound
   7.115 +    }
   7.116 +    
   7.117 +    public func removeAllObjects() {
   7.118 +        objc_sync_enter(self)
   7.119 +        defer { objc_sync_exit(self) }
   7.120 +        set.removeAllObjects()
   7.121 +    }
   7.122 +
   7.123 +    // MARK: - Array Support
   7.124 +
   7.125 +    public func array() -> [T] {
   7.126 +        objc_sync_enter(self)
   7.127 +        defer { objc_sync_exit(self) }
   7.128 +
   7.129 +        if let theArray = set.array as? [T] {
   7.130 +            return theArray
   7.131 +        } else {
   7.132 +            return []
   7.133 +        }
   7.134 +    }
   7.135 +
   7.136 +    public subscript(safe index: Int) -> T? {
   7.137 +        objc_sync_enter(self)
   7.138 +        defer { objc_sync_exit(self) }
   7.139 +
   7.140 +        if index >= set.count {
   7.141 +            return nil
   7.142 +        }
   7.143 +
   7.144 +        if let obj = set.object(at: index) as? T {
   7.145 +            return obj
   7.146 +        } else {
   7.147 +            return nil
   7.148 +        }
   7.149 +    }
   7.150 +
   7.151 +    // MARK: - Sequence
   7.152 +
   7.153 +    public typealias Iterator = SortedSetIterator<T>
   7.154 +
   7.155 +    public func makeIterator() -> SortedSet<T>.SortedSetIterator<T> {
   7.156 +        return SortedSetIterator.init(elements: set.array as! [T])
   7.157 +    }
   7.158 +
   7.159 +    // MARK: - Iterator
   7.160 +
   7.161 +    public struct SortedSetIterator<T>: IteratorProtocol {
   7.162 +        public typealias Element = T
   7.163 +
   7.164 +        private let elements: [T]
   7.165 +        private var index = 0
   7.166 +        private let maxIndex: Int
   7.167 +
   7.168 +        public init(elements: [T]) {
   7.169 +            self.elements = elements
   7.170 +            maxIndex = elements.count - 1
   7.171 +        }
   7.172 +
   7.173 +        public mutating func next() -> SortedSetIterator.Element? {
   7.174 +            if index > maxIndex {
   7.175 +                return nil
   7.176 +            } else {
   7.177 +                let e = elements[index]
   7.178 +                index += 1
   7.179 +                return e
   7.180 +            }
   7.181 +        }
   7.182 +    }
   7.183 +
   7.184 +    // MARK: -
   7.185 +    
   7.186 +    private var set = NSMutableOrderedSet()
   7.187 +    private var sortBlock: SortBlock
   7.188 +
   7.189 +    private func sort()  {
   7.190 +        set.sort { (first: Any, second: Any) -> ComparisonResult in
   7.191 +            guard let firstT = first as? T,
   7.192 +                let secondT = second as? T else {
   7.193 +                    Logger.frontendLogger.errorAndCrash("Error casting.")
   7.194 +                    return .orderedSame
   7.195 +            }
   7.196 +            return sortBlock(firstT, secondT)
   7.197 +        }
   7.198 +    }
   7.199 +    
   7.200 +    private func indexOfObjectIfInserted(obj: T) -> Int {
   7.201 +        for i in 0..<set.count {
   7.202 +            guard let testee = set.object(at: i) as? T else {
   7.203 +                Logger.frontendLogger.errorAndCrash("Error casing")
   7.204 +                return 0
   7.205 +            }
   7.206 +            if set.count == 0 {
   7.207 +                //set is empty
   7.208 +                return 0
   7.209 +            }
   7.210 +            if sortBlock(obj, testee) == .orderedAscending {
   7.211 +                // following object found
   7.212 +                return i
   7.213 +            }
   7.214 +        }
   7.215 +        // we would insert as the last object
   7.216 +        return Swift.max(0, set.count)
   7.217 +    }
   7.218 +
   7.219 +    private func isValidIndex(_ idx: Int) -> Bool {
   7.220 +        return idx >= 0 && idx < set.count
   7.221 +    }
   7.222 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/Submodules/pEpIOSToolbox/pEpIOSToolbox/Other/SystemUtils.swift	Mon Mar 18 10:54:14 2019 +0100
     8.3 @@ -0,0 +1,18 @@
     8.4 +//
     8.5 +//  SystemUtils.swift
     8.6 +//  MessageModel
     8.7 +//
     8.8 +//  Created by Andreas Buff on 08/03/2017.
     8.9 +//  Copyright © 2017 pEp Security S.A. All rights reserved.
    8.10 +//
    8.11 +
    8.12 +import Foundation
    8.13 +
    8.14 +/// Crashes when in debug configuration
    8.15 +public struct SystemUtils {
    8.16 +    static public func crash(_ message: String) {
    8.17 +        #if DEBUG
    8.18 +            preconditionFailure(message)
    8.19 +        #endif
    8.20 +    }
    8.21 +}
     9.1 --- a/pEpForiOS.xcodeproj/project.pbxproj	Wed Feb 20 11:00:07 2019 +0100
     9.2 +++ b/pEpForiOS.xcodeproj/project.pbxproj	Mon Mar 18 10:54:14 2019 +0100
     9.3 @@ -35,7 +35,6 @@
     9.4  		005A21FB20CAA5F50082D19F /* ThreadedEmailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 005A21FA20CAA5F50082D19F /* ThreadedEmailViewModel.swift */; };
     9.5  		0069DCFB2110679200846EB1 /* EmailViewController+UIPopoverPresentationControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0069DCFA2110679200846EB1 /* EmailViewController+UIPopoverPresentationControllerDelegate.swift */; };
     9.6  		006BE6BC20F4B63C00DDE8C9 /* EmailDetailType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 006BE6BB20F4B63C00DDE8C9 /* EmailDetailType.swift */; };
     9.7 -		008335A1210F28C7006E9306 /* SecretUITestData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 008335A0210F28C7006E9306 /* SecretUITestData.swift */; };
     9.8  		00A12CAE20D3D9AC00B82BE3 /* FullMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00A12CAD20D3D9AC00B82BE3 /* FullMessageCell.swift */; };
     9.9  		00AEB2F620DBA7DA00DA185A /* NeedsRefreshDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00AEB2F520DBA7DA00DA185A /* NeedsRefreshDelegate.swift */; };
    9.10  		00BEC89720B85FD300A36E60 /* NoMessagesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00BEC89620B85FD300A36E60 /* NoMessagesViewController.swift */; };
    9.11 @@ -49,14 +48,12 @@
    9.12  		1500199D1F2B2C73003E670A /* Notification+CWServiceClientNotificationParsing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1500199C1F2B2C73003E670A /* Notification+CWServiceClientNotificationParsing.swift */; };
    9.13  		1500199F1F2BA2EF003E670A /* SyncFlagsToServerOperationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1500199E1F2BA2EF003E670A /* SyncFlagsToServerOperationTest.swift */; };
    9.14  		150707DC21006CD000AA213F /* ComposeUtilTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 150707DB21006CD000AA213F /* ComposeUtilTest.swift */; };
    9.15 -		1508AEAA1F862C85001D5230 /* SortedSetTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1508AEA91F862C85001D5230 /* SortedSetTest.swift */; };
    9.16  		150B84C420A44DE100D8B288 /* MoveToFolderOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 150B84C320A44DE100D8B288 /* MoveToFolderOperation.swift */; };
    9.17  		150B84C620A5DD0600D8B288 /* UIDCopyOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 150B84C520A5DD0600D8B288 /* UIDCopyOperation.swift */; };
    9.18  		150B8E981FCDACBB00374438 /* ErrorPropagator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 150B8E961FCDACBB00374438 /* ErrorPropagator.swift */; };
    9.19  		150B8E991FCDACBB00374438 /* AccountSettingsUserInputError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 150B8E971FCDACBB00374438 /* AccountSettingsUserInputError.swift */; };
    9.20  		150B8EB31FCEB93D00374438 /* UIUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 150B8EB21FCEB93D00374438 /* UIUtils.swift */; };
    9.21  		150DF6D02052A13700A9DCF7 /* SecureWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 150DF6CF2052A13700A9DCF7 /* SecureWebViewController.swift */; };
    9.22 -		150DF6D32052ED4800A9DCF7 /* UIView+Autolayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 150DF6D22052ED4800A9DCF7 /* UIView+Autolayout.swift */; };
    9.23  		150E18C0219D8C6C009E9048 /* ComposeViewModelSectionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 150E18BF219D8C6C009E9048 /* ComposeViewModelSectionTest.swift */; };
    9.24  		15175CEC205929FB00A8D9D0 /* CidHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15175CEB205929FB00A8D9D0 /* CidHandler.swift */; };
    9.25  		151AD7AD219D74C700FC36FF /* ComposeViewModelTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 151AD7AC219D74C700FC36FF /* ComposeViewModelTest.swift */; };
    9.26 @@ -158,13 +155,11 @@
    9.27  		1568FEA11FACDCC600993EA3 /* IOS-211_hi_there.txt in Resources */ = {isa = PBXBuildFile; fileRef = 1568FEA01FACDCC500993EA3 /* IOS-211_hi_there.txt */; };
    9.28  		1569AEA520E14DC3002102A0 /* ReUploadTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1569AEA420E14DC2002102A0 /* ReUploadTest.swift */; };
    9.29  		1569DDB8215395BE007A0398 /* NSAttributedString+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1569DDB7215395BE007A0398 /* NSAttributedString+Extension.swift */; };
    9.30 -		157455C81FDFD2D4008CA78F /* NSAttributedString+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 157455C71FDFD2D4008CA78F /* NSAttributedString+Extensions.swift */; };
    9.31  		1574D078211356E000FEDC93 /* UrlClickHandlerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1574D077211356E000FEDC93 /* UrlClickHandlerProtocol.swift */; };
    9.32  		1574D07A211464CC00FEDC93 /* URL+MailTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1574D079211464CC00FEDC93 /* URL+MailTo.swift */; };
    9.33  		1574D07D2114696B00FEDC93 /* URL+MailToTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1574D07C2114696B00FEDC93 /* URL+MailToTest.swift */; };
    9.34  		1574D09B21186A1D00FEDC93 /* AddToContactsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1574D09A21186A1D00FEDC93 /* AddToContactsViewController.swift */; };
    9.35  		157743B8217885EA0007222C /* RecipientTextViewModelTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 157743B7217885EA0007222C /* RecipientTextViewModelTest.swift */; };
    9.36 -		1579397B1F4E00AF00A2A6CF /* UINavigationController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1579397A1F4E00AF00A2A6CF /* UINavigationController+Extensions.swift */; };
    9.37  		157C05482180756300E530DE /* DocumentAttachmentPickerViewModelTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 157C05472180756300E530DE /* DocumentAttachmentPickerViewModelTest.swift */; };
    9.38  		15865A8920319ADC00F7A4B5 /* Folder+pEp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15865A8820319ADC00F7A4B5 /* Folder+pEp.swift */; };
    9.39  		15874BC12127493E00A3A4A6 /* SettingSwitchTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15874BA82127493E00A3A4A6 /* SettingSwitchTableViewCell.swift */; };
    9.40 @@ -202,12 +197,10 @@
    9.41  		15BA536A20A08B100090F126 /* Account+Extentions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15BA536920A08B100090F126 /* Account+Extentions.swift */; };
    9.42  		15BA536C20A08D270090F126 /* UnifiedInbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15BA536B20A08D270090F126 /* UnifiedInbox.swift */; };
    9.43  		15BA536E20A095410090F126 /* UnifiedInboxTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15BA536D20A095410090F126 /* UnifiedInboxTest.swift */; };
    9.44 -		15BA537020A0A4350090F126 /* Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43980EDF1CBD24B000A7FC3C /* Log.swift */; };
    9.45  		15BBBC631FD0496800B9DCC8 /* ReportingErrorContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15BBBC621FD0496800B9DCC8 /* ReportingErrorContainer.swift */; };
    9.46  		15BBBC681FD04DFC00B9DCC8 /* ReportingErrorContainerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15BBBC671FD04DFC00B9DCC8 /* ReportingErrorContainerTest.swift */; };
    9.47  		15BBBC6B1FD0527200B9DCC8 /* DisplayUserErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15BBBC6A1FD0527200B9DCC8 /* DisplayUserErrorTest.swift */; };
    9.48  		15BBBC6C1FD05F4300B9DCC8 /* DisplayUserError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 152130531FD00B7A00688DF2 /* DisplayUserError.swift */; };
    9.49 -		15C5F2461F823752007DE086 /* SortedSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15C5F2451F823752007DE086 /* SortedSet.swift */; };
    9.50  		15D4399A216E697700EB3933 /* AccountPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15D43999216E697700EB3933 /* AccountPickerView.swift */; };
    9.51  		15D4399C216E698E00EB3933 /* AccountPickerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15D4399B216E698E00EB3933 /* AccountPickerViewModel.swift */; };
    9.52  		15D439A5216F7E0E00EB3933 /* AccountPickerViewModelTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15D439A4216F7E0E00EB3933 /* AccountPickerViewModelTest.swift */; };
    9.53 @@ -223,7 +216,6 @@
    9.54  		15EBE44320E5353E00268859 /* unittest_ios_3_peptest_ch_550A_9E62_6822_040E_57CB_151A_651C_4A5D_B15B_77A3_sec.asc in Resources */ = {isa = PBXBuildFile; fileRef = 15EBE44120E5353D00268859 /* unittest_ios_3_peptest_ch_550A_9E62_6822_040E_57CB_151A_651C_4A5D_B15B_77A3_sec.asc */; };
    9.55  		15F0F7AA21358B33002BE853 /* CdMessagePredicateFactory+Imap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15F0F7A921358B33002BE853 /* CdMessagePredicateFactory+Imap.swift */; };
    9.56  		15F0F7AD213594FC002BE853 /* Folder+Imap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15F0F7AC213594FC002BE853 /* Folder+Imap.swift */; };
    9.57 -		15F0F7AF2135984C002BE853 /* Array+SortingAndSearching.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15F0F7AE2135984C002BE853 /* Array+SortingAndSearching.swift */; };
    9.58  		15F0F7B62136F6D1002BE853 /* CdFolderPredicateFactory+IMAP.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15F0F7B52136F6D1002BE853 /* CdFolderPredicateFactory+IMAP.swift */; };
    9.59  		15F835241F34BE1300FCE887 /* AccountUserInput.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15F835231F34BE1300FCE887 /* AccountUserInput.swift */; };
    9.60  		15F835281F3B497D00FCE887 /* FetchMessagesOperationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15F835271F3B497D00FCE887 /* FetchMessagesOperationTest.swift */; };
    9.61 @@ -298,7 +290,6 @@
    9.62  		43257C841F50629700DDC7F0 /* HtmlToAttributedTextSaxParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43257C831F50629700DDC7F0 /* HtmlToAttributedTextSaxParser.swift */; };
    9.63  		43257C861F50659200DDC7F0 /* StringHTMLExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43257C851F50659200DDC7F0 /* StringHTMLExtensionTests.swift */; };
    9.64  		43257C891F50683600DDC7F0 /* NSAttributedString+pEp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43257C871F5067BE00DDC7F0 /* NSAttributedString+pEp.swift */; };
    9.65 -		432645811F4C26CF002E3EF8 /* NSAttributedString+Parsing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 432645801F4C26CF002E3EF8 /* NSAttributedString+Parsing.swift */; };
    9.66  		43264E9B1D76B7110098DCAC /* SyncFlagsToServerOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43264E9A1D76B7110098DCAC /* SyncFlagsToServerOperation.swift */; };
    9.67  		4326D3FF1EFBC8DB0016AB0D /* FolderInfoOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4326D3FE1EFBC8DB0016AB0D /* FolderInfoOperation.swift */; };
    9.68  		43293EFB1EB9DD6700EEE010 /* UIViewController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43293EFA1EB9DD6700EEE010 /* UIViewController+Extension.swift */; };
    9.69 @@ -318,11 +309,9 @@
    9.70  		4333A2A51E5C9B6E0025D8A5 /* FixAttachmentsOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4333A2A41E5C9B6E0025D8A5 /* FixAttachmentsOperation.swift */; };
    9.71  		4334CF302020CFFE00B3193E /* OAuth2Type+LibAccountSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4334CF2F2020CFFE00B3193E /* OAuth2Type+LibAccountSettings.swift */; };
    9.72  		4336229E1DC76B8100133B3D /* MessageModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4336229D1DC76B8100133B3D /* MessageModelTests.swift */; };
    9.73 -		4337E52A21B68FCA00826CAB /* Thread+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4337E52921B68FCA00826CAB /* Thread+Extension.swift */; };
    9.74  		433BCD951D5388C100DD98EF /* ReplyUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 433BCD941D5388C100DD98EF /* ReplyUtil.swift */; };
    9.75  		433C51D31E66CCA900272E19 /* CreateRequiredFoldersOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 433C51D11E66CB9C00272E19 /* CreateRequiredFoldersOperation.swift */; };
    9.76  		433F2E2A21E3581800E1CA49 /* ENGINE-505_Mail_NullInnerMimeType.txt in Resources */ = {isa = PBXBuildFile; fileRef = 433F2E2921E3581800E1CA49 /* ENGINE-505_Mail_NullInnerMimeType.txt */; };
    9.77 -		4341980520AB037E0062F7F6 /* CGImageSource+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4341980420AB037E0062F7F6 /* CGImageSource+Extension.swift */; };
    9.78  		4341EBCF2089F674004CE6B8 /* QualifyServerIsLocalOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4341EBCE2089F674004CE6B8 /* QualifyServerIsLocalOperation.swift */; };
    9.79  		4341EBD1208A0961004CE6B8 /* QualifyServerIsLocalServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4341EBD0208A0961004CE6B8 /* QualifyServerIsLocalServiceProtocol.swift */; };
    9.80  		43425EDB1FE3DE6E004A2728 /* OAuth2ProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43425EDA1FE3DE6E004A2728 /* OAuth2ProviderProtocol.swift */; };
    9.81 @@ -365,18 +354,10 @@
    9.82  		4356FFE52135448600804089 /* ReplyAllPossibleChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4356FFE42135448600804089 /* ReplyAllPossibleChecker.swift */; };
    9.83  		4356FFE721354A4B00804089 /* ReplyAllPossibleCheckerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4356FFE621354A4B00804089 /* ReplyAllPossibleCheckerProtocol.swift */; };
    9.84  		4356FFEC21356CB600804089 /* ReplyAllPossibleCheckerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4356FFEB21356CB600804089 /* ReplyAllPossibleCheckerTest.swift */; };
    9.85 -		435B42411D211E5900119048 /* MiscUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 435B42401D211E5900119048 /* MiscUtil.swift */; };
    9.86  		435F7C75215E05DA00F21EFD /* 1364_Mail_missing_attached_image.txt in Resources */ = {isa = PBXBuildFile; fileRef = 435F7C74215E05DA00F21EFD /* 1364_Mail_missing_attached_image.txt */; };
    9.87  		4360282D1ED6F27600C95FC4 /* NetworkError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4360282C1ED6F27600C95FC4 /* NetworkError.swift */; };
    9.88  		4360282F1ED6F33400C95FC4 /* ImapSyncError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4360282E1ED6F33400C95FC4 /* ImapSyncError.swift */; };
    9.89 -		4362398C1EADD61B00BD2EB9 /* CGSize+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4362398B1EADD61B00BD2EB9 /* CGSize+Extension.swift */; };
    9.90  		436239931EAE08F400BD2EB9 /* PEPSession+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4362398F1EAE08F400BD2EB9 /* PEPSession+Extensions.swift */; };
    9.91 -		436239941EAE08F400BD2EB9 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 436239901EAE08F400BD2EB9 /* String+Extensions.swift */; };
    9.92 -		436239951EAE08F400BD2EB9 /* String+pEp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 436239911EAE08F400BD2EB9 /* String+pEp.swift */; };
    9.93 -		4362399B1EAE0CE800BD2EB9 /* Date+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 436239971EAE0CE800BD2EB9 /* Date+Extension.swift */; };
    9.94 -		4362399C1EAE0CE800BD2EB9 /* NSRegularExpression+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 436239981EAE0CE800BD2EB9 /* NSRegularExpression+Extension.swift */; };
    9.95 -		4362399D1EAE0CE800BD2EB9 /* OperationQueue+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 436239991EAE0CE800BD2EB9 /* OperationQueue+Extension.swift */; };
    9.96 -		4362399F1EAE2F0A00BD2EB9 /* UITableView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4362399E1EAE2F0A00BD2EB9 /* UITableView+Extension.swift */; };
    9.97  		43628766213D7A5E0066CD03 /* IOS-1300_odt_attachment.txt in Resources */ = {isa = PBXBuildFile; fileRef = 43628765213D7A5E0066CD03 /* IOS-1300_odt_attachment.txt */; };
    9.98  		436795F81EE98B9A00B03E23 /* MessageReevalutionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 436795F71EE98B9A00B03E23 /* MessageReevalutionTests.swift */; };
    9.99  		436795FB1EE98E9900B03E23 /* CommunicationTypeTests_test002@peptest.ch_sec.asc in Resources */ = {isa = PBXBuildFile; fileRef = 436795F91EE98E9900B03E23 /* CommunicationTypeTests_test002@peptest.ch_sec.asc */; };
   9.100 @@ -398,10 +379,8 @@
   9.101  		438052891FE3E24400ACF729 /* OAuth2AuthorizationProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 438052881FE3E24400ACF729 /* OAuth2AuthorizationProtocol.swift */; };
   9.102  		4380528B1FE3E2E800ACF729 /* OAuth2AuthorizationURLHandlerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4380528A1FE3E2E800ACF729 /* OAuth2AuthorizationURLHandlerProtocol.swift */; };
   9.103  		4381D0FF1E51A124002743C3 /* NetworkServiceWorker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4381D0FE1E51A124002743C3 /* NetworkServiceWorker.swift */; };
   9.104 -		43826F87212FF91D00BF1F7B /* Substring+Email.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43826F86212FF91D00BF1F7B /* Substring+Email.swift */; };
   9.105  		438281831E891B7E00087343 /* DateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 438281821E891B7E00087343 /* DateTests.swift */; };
   9.106  		4382E6431CC600FF00AA27EA /* PersistentImapFolder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4382E6421CC600FF00AA27EA /* PersistentImapFolder.swift */; };
   9.107 -		4384ABB01F3B5A11006982B8 /* Data+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4384ABAF1F3B5A11006982B8 /* Data+Extensions.swift */; };
   9.108  		4388A0E22008F813008CB98D /* OAuth2AccessToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4388A0E12008F813008CB98D /* OAuth2AccessToken.swift */; };
   9.109  		4388A0E42008F8F4008CB98D /* OAuth2AccessTokenProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4388A0E32008F8F4008CB98D /* OAuth2AccessTokenProtocol.swift */; };
   9.110  		438BA0F5214F89CD001A4A82 /* MailParsingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 438BA0F4214F89CC001A4A82 /* MailParsingTests.swift */; };
   9.111 @@ -412,7 +391,6 @@
   9.112  		438F4EE1215F9CB300168B5E /* SimplifiedKeyImport_Harry_To_Rick_with_Leon.txt in Resources */ = {isa = PBXBuildFile; fileRef = 438F4EE0215F9CB300168B5E /* SimplifiedKeyImport_Harry_To_Rick_with_Leon.txt */; };
   9.113  		438F4EE5215FAD0500168B5E /* Harry Bryant iostest002@peptest.ch (0x5716EA2D9AE32468) pub-sec.asc in Resources */ = {isa = PBXBuildFile; fileRef = 438F4EE4215FAD0500168B5E /* Harry Bryant iostest002@peptest.ch (0x5716EA2D9AE32468) pub-sec.asc */; };
   9.114  		438F4EE9215FB99400168B5E /* Leon Kowalski (19B9EE3B) – Private.asc in Resources */ = {isa = PBXBuildFile; fileRef = 438F4EE8215FB99400168B5E /* Leon Kowalski (19B9EE3B) – Private.asc */; };
   9.115 -		4395CDEC20AAB2E9003FC5F1 /* UIImage+GIF.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4395CDEB20AAB2E9003FC5F1 /* UIImage+GIF.swift */; };
   9.116  		4395CDEE20AAC909003FC5F1 /* UIImageExtensionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4395CDED20AAC909003FC5F1 /* UIImageExtensionsTests.swift */; };
   9.117  		4395CDF020AAD0D7003FC5F1 /* icon_001.gif in Resources */ = {isa = PBXBuildFile; fileRef = 4395CDEF20AAD0D6003FC5F1 /* icon_001.gif */; };
   9.118  		439680981D1855D400DA31D2 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 439680971D1855D400DA31D2 /* WebKit.framework */; };
   9.119 @@ -420,18 +398,15 @@
   9.120  		43980E2C1CBD0BC900A7FC3C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 43980E2A1CBD0BC900A7FC3C /* Main.storyboard */; };
   9.121  		43980E311CBD0BCA00A7FC3C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 43980E301CBD0BCA00A7FC3C /* Assets.xcassets */; };
   9.122  		43980E341CBD0BCA00A7FC3C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 43980E321CBD0BCA00A7FC3C /* LaunchScreen.storyboard */; };
   9.123 -		43980EE01CBD24B000A7FC3C /* Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43980EDF1CBD24B000A7FC3C /* Log.swift */; };
   9.124  		43980EFA1CBD415700A7FC3C /* AppConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43980EF91CBD415700A7FC3C /* AppConfig.swift */; };
   9.125  		43985D0A2044296D0080FA9A /* OAuth2AuthViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43985D092044296D0080FA9A /* OAuth2AuthViewModel.swift */; };
   9.126  		43985D0E204438480080FA9A /* AccountSettingsProtocol+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43985D0D204438480080FA9A /* AccountSettingsProtocol+Extension.swift */; };
   9.127 -		439932291FEA7E7A00E92C35 /* String+Email.swift in Sources */ = {isa = PBXBuildFile; fileRef = 439932281FEA7E7A00E92C35 /* String+Email.swift */; };
   9.128  		439932301FEA9B7200E92C35 /* SwipeCellKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 439932311FEA9B7200E92C35 /* SwipeCellKit.framework */; };
   9.129  		439A23E520B40FAC00417AF5 /* PEP_rating+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 439A23E420B40FAC00417AF5 /* PEP_rating+Extension.swift */; };
   9.130  		439AAC561F21D0CC0018A29E /* CdFolder+Pantomime.swift in Sources */ = {isa = PBXBuildFile; fileRef = 439AAC551F21D0CC0018A29E /* CdFolder+Pantomime.swift */; };
   9.131  		439D40701CC78930009A4E7C /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 439D406F1CC78930009A4E7C /* libz.tbd */; };
   9.132  		439D40721CC78958009A4E7C /* libbz2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 439D40711CC78958009A4E7C /* libbz2.tbd */; };
   9.133  		439D40741CC7897B009A4E7C /* libiconv.2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 439D40731CC7897B009A4E7C /* libiconv.2.tbd */; };
   9.134 -		439D407A1CC79423009A4E7C /* GCD.swift in Sources */ = {isa = PBXBuildFile; fileRef = 439D40791CC79423009A4E7C /* GCD.swift */; };
   9.135  		43A0B2CF214006FC00FB779D /* ReplyUtilTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43A0B2CE214006FC00FB779D /* ReplyUtilTests.swift */; };
   9.136  		43A26FBA1E0408FB00AF0B84 /* ServiceErrorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43A26FB91E0408FB00AF0B84 /* ServiceErrorProtocol.swift */; };
   9.137  		43A26FBF1E041BF200AF0B84 /* ImapSyncOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43A26FBE1E041BF200AF0B84 /* ImapSyncOperation.swift */; };
   9.138 @@ -440,7 +415,6 @@
   9.139  		43A5DE381D631D49001153AF /* UnencryptedHTMLMail.txt in Resources */ = {isa = PBXBuildFile; fileRef = 43A5DE371D631D49001153AF /* UnencryptedHTMLMail.txt */; };
   9.140  		43A6E04B1E5726C8005BEE69 /* ReevaluateMessageRatingOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43A6E04A1E5726C8005BEE69 /* ReevaluateMessageRatingOperation.swift */; };
   9.141  		43A6E0581E57400E005BEE69 /* RatingReEvaluator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43A6E0571E57400E005BEE69 /* RatingReEvaluator.swift */; };
   9.142 -		43AA82531E9B925C00ABD5A8 /* UIView+Util.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43AA82521E9B925C00ABD5A8 /* UIView+Util.swift */; };
   9.143  		43AA825B1E9BC5FF00ABD5A8 /* AttachmentViewContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43AA825A1E9BC5FF00ABD5A8 /* AttachmentViewContainer.swift */; };
   9.144  		43AA825D1E9BD60600ABD5A8 /* AttachmentsViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43AA825C1E9BD60600ABD5A8 /* AttachmentsViewDelegate.swift */; };
   9.145  		43AAC22A1F7A5AEE00F435F4 /* BaseTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43AAC2281F7A5AED00F435F4 /* BaseTableViewController.swift */; };
   9.146 @@ -458,15 +432,9 @@
   9.147  		43BB86941DB4E76D00980267 /* CdAccount+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43BB86931DB4E76D00980267 /* CdAccount+Extension.swift */; };
   9.148  		43BBB5E71E267A3800104070 /* EncryptAndSendOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43BBB5E61E267A3800104070 /* EncryptAndSendOperation.swift */; };
   9.149  		43C046BF1CF48EA500BD0D9D /* AddressBook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43C046BE1CF48EA500BD0D9D /* AddressBook.framework */; };
   9.150 -		43C273DB21C8F96D002EB4C8 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C273DA21C8F96D002EB4C8 /* Logger.swift */; };
   9.151  		43C273DD21C9024A002EB4C8 /* LoggerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C273DC21C9024A002EB4C8 /* LoggerTest.swift */; };
   9.152  		43C322051EA89EED005073FB /* HandshakePartnerTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C322041EA89EED005073FB /* HandshakePartnerTableViewCell.swift */; };
   9.153 -		43C322071EA8E7AD005073FB /* UIButton+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C322061EA8E7AD005073FB /* UIButton+Extension.swift */; };
   9.154  		43C322091EA90192005073FB /* PEP+UI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C322081EA90192005073FB /* PEP+UI.swift */; };
   9.155 -		43C3220C1EA915C6005073FB /* CGRect+Util.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C3220A1EA915C6005073FB /* CGRect+Util.swift */; };
   9.156 -		43C3220D1EA915C6005073FB /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C3220B1EA915C6005073FB /* UIColor+Extension.swift */; };
   9.157 -		43C322101EA91764005073FB /* UIImage+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C3220E1EA91764005073FB /* UIImage+Extension.swift */; };
   9.158 -		43C322111EA91764005073FB /* UIImageView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C3220F1EA91764005073FB /* UIImageView+Extension.swift */; };
   9.159  		43C3B1602003851100ED48A4 /* DecryptImportedMessagesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C3B15F2003851100ED48A4 /* DecryptImportedMessagesTests.swift */; };
   9.160  		43C3B1622003896800ED48A4 /* IOS-884_001_Mail_from_P4A.txt in Resources */ = {isa = PBXBuildFile; fileRef = 43C3B1612003896800ED48A4 /* IOS-884_001_Mail_from_P4A.txt */; };
   9.161  		43C3B16820038B2500ED48A4 /* IOS-884_001_test010@peptest.ch.pub.key in Resources */ = {isa = PBXBuildFile; fileRef = 43C3B16520038B2500ED48A4 /* IOS-884_001_test010@peptest.ch.pub.key */; };
   9.162 @@ -486,7 +454,6 @@
   9.163  		43D755EB1F25D234006F933A /* MatchUidToMsnOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43D755EA1F25D234006F933A /* MatchUidToMsnOperation.swift */; };
   9.164  		43D755F61F262B37006F933A /* PantomimeError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43D755F51F262B37006F933A /* PantomimeError.swift */; };
   9.165  		43D755FC1F26382B006F933A /* EmailConnectInfo+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43D755FB1F26382B006F933A /* EmailConnectInfo+Extension.swift */; };
   9.166 -		43D86EB821BE62DD00C18418 /* Log+ASL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43EC75A3216498AD00048CFE /* Log+ASL.swift */; };
   9.167  		43DA52681CEF1B4F0023D540 /* NewAccountSetupUITest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43DA52671CEF1B4F0023D540 /* NewAccountSetupUITest.swift */; };
   9.168  		43DB81331E2A56BE00A20902 /* AppendMailsOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43DB81321E2A56BE00A20902 /* AppendMailsOperation.swift */; };
   9.169  		43DFB0331E36083D00175C9C /* MessageHeapBufferOverflow.txt in Resources */ = {isa = PBXBuildFile; fileRef = 43DFB0321E36083D00175C9C /* MessageHeapBufferOverflow.txt */; };
   9.170 @@ -497,11 +464,8 @@
   9.171  		43E657E71F3CAB310014CBEC /* HtmlToMarkdownSaxParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43E657E61F3CAB310014CBEC /* HtmlToMarkdownSaxParser.swift */; };
   9.172  		43E74C741E38DE2200A2F7A6 /* ImapFlagsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43E74C731E38DE2200A2F7A6 /* ImapFlagsTests.swift */; };
   9.173  		43E7B6751DE4A53A0017D707 /* CdIdentity+pEp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43E7B6741DE4A53A0017D707 /* CdIdentity+pEp.swift */; };
   9.174 -		43E88BDE1EFA665600E0B224 /* AsyncStateMachineProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43E88BDD1EFA665600E0B224 /* AsyncStateMachineProtocol.swift */; };
   9.175 -		43E88BE01EFA667600E0B224 /* AsyncStateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43E88BDF1EFA667600E0B224 /* AsyncStateMachine.swift */; };
   9.176  		43E9BC641DB518A700AD2352 /* CdFolder+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43E9BC631DB518A700AD2352 /* CdFolder+Extension.swift */; };
   9.177  		43EC03481F4AE28F0026E152 /* String+Attachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43EC03471F4AE28F0026E152 /* String+Attachment.swift */; };
   9.178 -		43EC75A4216498AD00048CFE /* Log+ASL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43EC75A3216498AD00048CFE /* Log+ASL.swift */; };
   9.179  		43EC75AC2164C26100048CFE /* SetOwnKeyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43EC75AB2164C26100048CFE /* SetOwnKeyViewController.swift */; };
   9.180  		43EC75AE2164D03500048CFE /* SetOwnKeyViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43EC75AD2164D03500048CFE /* SetOwnKeyViewModel.swift */; };
   9.181  		43EC75B32164E97800048CFE /* DecryptionUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43EC75B22164E97800048CFE /* DecryptionUtil.swift */; };
   9.182 @@ -518,10 +482,8 @@
   9.183  		43F6DFD71DEEC752006B526F /* FetchMessagesOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43F6DFD61DEEC752006B526F /* FetchMessagesOperation.swift */; };
   9.184  		43F7F07A1F6AD44600BDF151 /* HandshakeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43F7F0791F6AD44600BDF151 /* HandshakeTests.swift */; };
   9.185  		43F7F07C1F6AD4FD00BDF151 /* HandshakeTests_mail_001.txt in Resources */ = {isa = PBXBuildFile; fileRef = 43F7F07B1F6AD4FD00BDF151 /* HandshakeTests_mail_001.txt */; };
   9.186 -		43F848491EAA09AE00DBE460 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43F848481EAA09AE00DBE460 /* Weak.swift */; };
   9.187  		43F84CD21CD899760092FCAE /* SyncFoldersFromServerOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43F84CD11CD899760092FCAE /* SyncFoldersFromServerOperation.swift */; };
   9.188  		43F9D99A1E92725700F78A1C /* AttachmentsViewHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43F9D9991E92725700F78A1C /* AttachmentsViewHelper.swift */; };
   9.189 -		43FAA0D21EC9972B005BFC4B /* Tuple.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43FAA0D11EC9972B005BFC4B /* Tuple.swift */; };
   9.190  		43FAA0D41EC9CBC0005BFC4B /* DecryptionTestsInternal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43FAA0D31EC9CBC0005BFC4B /* DecryptionTestsInternal.swift */; };
   9.191  		43FC02121F4D913D00273304 /* NSHTML_2017-08-09 15_40_53 +0000.html in Resources */ = {isa = PBXBuildFile; fileRef = 43FC02111F4D913D00273304 /* NSHTML_2017-08-09 15_40_53 +0000.html */; };
   9.192  		43FE802E209992B800E97AB3 /* QualifyServerIsLocalService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43FE802D209992B800E97AB3 /* QualifyServerIsLocalService.swift */; };
   9.193 @@ -547,7 +509,6 @@
   9.194  		49A6114E2179F3A1006BA3C5 /* UnitTestUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49A6114D2179F3A1006BA3C5 /* UnitTestUtils.swift */; };
   9.195  		49C2750120C04DDB0075F6FF /* EmailViewController+DisplayedMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49C2750020C04DDB0075F6FF /* EmailViewController+DisplayedMessage.swift */; };
   9.196  		49C34AF620E4F649009D11CC /* CellDetailTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49C34AF520E4F649009D11CC /* CellDetailTransition.swift */; };
   9.197 -		49D292A320F3ABA600F33C78 /* CredentialTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49D292A220F3ABA600F33C78 /* CredentialTextField.swift */; };
   9.198  		49D3BECC20F8F7330043E05D /* LoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49D3BECB20F8F7330043E05D /* LoginViewController.swift */; };
   9.199  		49D521541E73E1C20097987B /* MessageModel.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49D521531E73E1C20097987B /* MessageModel.framework */; };
   9.200  		49D521551E73E1C20097987B /* MessageModel.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 49D521531E73E1C20097987B /* MessageModel.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
   9.201 @@ -559,9 +520,11 @@
   9.202  		5D039AA21D0EEA3700AD59EC /* DecryptMessagesOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D039AA11D0EEA3700AD59EC /* DecryptMessagesOperation.swift */; };
   9.203  		5DEBAA481DE59C3B00FAE12C /* NetworkServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DEBAA471DE59C3B00FAE12C /* NetworkServiceTests.swift */; };
   9.204  		8B69E3991E30F80E0022959E /* Appearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B69E3981E30F80E0022959E /* Appearance.swift */; };
   9.205 -		8B81BB901E03F73100D38C82 /* SegueHandlerType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B81BB8F1E03F73100D38C82 /* SegueHandlerType.swift */; };
   9.206  		A1014DA71D1173CD00C472A8 /* UIHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 436C5A8D1CFEDF59006A195F /* UIHelper.swift */; };
   9.207  		A1B50A841CD26FF100B1A997 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B50A811CD26FF100B1A997 /* Constants.swift */; };
   9.208 +		B70A3A63220065F600EDCE61 /* String+pEp.swift in Sources */ = {isa = PBXBuildFile; fileRef = B70A3A62220065F500EDCE61 /* String+pEp.swift */; };
   9.209 +		B70A3A9322089D5000EDCE61 /* Log+ASL.swift in Sources */ = {isa = PBXBuildFile; fileRef = B70A3A9122089D5000EDCE61 /* Log+ASL.swift */; };
   9.210 +		B70A3A9422089D5000EDCE61 /* Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = B70A3A9222089D5000EDCE61 /* Log.swift */; };
   9.211  		B70A3C401E817CFA0036876F /* FolderViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B70A3C3F1E817CFA0036876F /* FolderViewModel.swift */; };
   9.212  		B716056020D3ECC900A733D6 /* MoveToFolderTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B716055F20D3ECC900A733D6 /* MoveToFolderTableViewController.swift */; };
   9.213  		B71EBBBC1E55E4AE00150177 /* FolderTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B71EBBBB1E55E4AE00150177 /* FolderTableViewController.swift */; };
   9.214 @@ -570,18 +533,29 @@
   9.215  		B722EC7A1E5C879000A2B9D5 /* FolderUiProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = B722EC791E5C879000A2B9D5 /* FolderUiProtocols.swift */; };
   9.216  		B729BEC61E7C35E200793110 /* FilterUpdateProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B729BEC51E7C35E200793110 /* FilterUpdateProtocol.swift */; };
   9.217  		B73119001FEBE2DB0006573B /* SwipeCellKit.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 439932311FEA9B7200E92C35 /* SwipeCellKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
   9.218 -		B7365CDE1EAF45F30036ECC7 /* UITextField+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7365CDD1EAF45F30036ECC7 /* UITextField+Extension.swift */; };
   9.219  		B740B75D1E4B1C2D002585E1 /* jsonMimeType.txt in Resources */ = {isa = PBXBuildFile; fileRef = B740B75C1E4B1C2D002585E1 /* jsonMimeType.txt */; };
   9.220  		B740B75F1E4B1C46002585E1 /* MimeTypeUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = B740B75E1E4B1C46002585E1 /* MimeTypeUtil.swift */; };
   9.221  		B74F81021EB0E20000519FCC /* LoginViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B74F81011EB0E20000519FCC /* LoginViewModel.swift */; };
   9.222  		B75FF00B1EFD420F00C57289 /* EmailListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B75FF00A1EFD420F00C57289 /* EmailListViewModel.swift */; };
   9.223 -		B761A80A20F5F0A6000832C2 /* UIBarButtonItem+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = B761A80920F5F0A6000832C2 /* UIBarButtonItem+Extension.swift */; };
   9.224  		B76CF8B320D2739B002429A8 /* MoveToFolderViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B76CF8B220D2739B002429A8 /* MoveToFolderViewModel.swift */; };
   9.225 +		B7745839221C191600664282 /* SecretUITestData.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7745838221C191600664282 /* SecretUITestData.swift */; };
   9.226 +		B774583A221C320B00664282 /* pEpIOSToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B7DB7FEA221AFE10003968DA /* pEpIOSToolbox.framework */; };
   9.227 +		B774583B221C320B00664282 /* pEpIOSToolbox.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = B7DB7FEA221AFE10003968DA /* pEpIOSToolbox.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
   9.228  		B78309C81EAA09040051A2E0 /* AccountCreation.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B78309C61EAA09040051A2E0 /* AccountCreation.storyboard */; };
   9.229  		B78CF8251E76D706008C1739 /* FilterTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B78CF8241E76D706008C1739 /* FilterTableViewController.swift */; };
   9.230  		B78CF8291E76E0F1008C1739 /* FilterViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B78CF8281E76E0F1008C1739 /* FilterViewModel.swift */; };
   9.231  		B78CF82B1E76E146008C1739 /* FilterCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B78CF82A1E76E146008C1739 /* FilterCellViewModel.swift */; };
   9.232  		B7D1EEC81E8BEC8D00F190E3 /* CollapsibleTableViewHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7D1EEC71E8BEC8D00F190E3 /* CollapsibleTableViewHeader.swift */; };
   9.233 +		B7DB7FC42215C4FF003968DA /* UINavigationController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7DB7FC32215C4FF003968DA /* UINavigationController+Extensions.swift */; };
   9.234 +		B7DB7FC72215C57F003968DA /* UIView+Autolayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7DB7FC52215C57F003968DA /* UIView+Autolayout.swift */; };
   9.235 +		B7DB7FC82215C57F003968DA /* UIView+Util.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7DB7FC62215C57F003968DA /* UIView+Util.swift */; };
   9.236 +		B7DB7FCA2215D69C003968DA /* CredentialTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7DB7FC92215D69C003968DA /* CredentialTextField.swift */; };
   9.237 +		B7DB7FD2221AD332003968DA /* SegueHandlerType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7DB7FD1221AD332003968DA /* SegueHandlerType.swift */; };
   9.238 +		B7DB7FD6221AD3BB003968DA /* UITextField+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7DB7FD3221AD3BB003968DA /* UITextField+Extension.swift */; };
   9.239 +		B7DB7FD7221AD3BB003968DA /* UIButton+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7DB7FD4221AD3BB003968DA /* UIButton+Extension.swift */; };
   9.240 +		B7DB7FD8221AD3BB003968DA /* UITableView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7DB7FD5221AD3BB003968DA /* UITableView+Extension.swift */; };
   9.241 +		B7DB7FDA221ADDAF003968DA /* UIBarButtonItem+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7DB7FD9221ADDAF003968DA /* UIBarButtonItem+Extension.swift */; };
   9.242 +		B7DB7FDC221ADDBD003968DA /* UIImageView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7DB7FDB221ADDBD003968DA /* UIImageView+Extension.swift */; };
   9.243  		B7F4A793212DDFC500507B76 /* EmailListViewModelTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7F4A792212DDFC500507B76 /* EmailListViewModelTest.swift */; };
   9.244  		F73E4F72217F238300CCFFED /* FolderSectionViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F73E4F71217F238300CCFFED /* FolderSectionViewModelTests.swift */; };
   9.245  		F73E4F7A2180744700CCFFED /* FolderCellViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F73E4F792180744700CCFFED /* FolderCellViewModelTests.swift */; };
   9.246 @@ -615,6 +589,7 @@
   9.247  			dstPath = "";
   9.248  			dstSubfolderSpec = 10;
   9.249  			files = (
   9.250 +				B774583B221C320B00664282 /* pEpIOSToolbox.framework in CopyFiles */,
   9.251  				15FE1F791FE19A3A00CC2D97 /* AppAuth.framework in CopyFiles */,
   9.252  				43754AC81FCD8348009A8E63 /* ldns_xcode.framework in CopyFiles */,
   9.253  				B73119001FEBE2DB0006573B /* SwipeCellKit.framework in CopyFiles */,
   9.254 @@ -652,7 +627,6 @@
   9.255  		005A21FA20CAA5F50082D19F /* ThreadedEmailViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThreadedEmailViewModel.swift; sourceTree = "<group>"; };
   9.256  		0069DCFA2110679200846EB1 /* EmailViewController+UIPopoverPresentationControllerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EmailViewController+UIPopoverPresentationControllerDelegate.swift"; sourceTree = "<group>"; };
   9.257  		006BE6BB20F4B63C00DDE8C9 /* EmailDetailType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmailDetailType.swift; sourceTree = "<group>"; };
   9.258 -		008335A0210F28C7006E9306 /* SecretUITestData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecretUITestData.swift; sourceTree = "<group>"; };
   9.259  		00A12CAD20D3D9AC00B82BE3 /* FullMessageCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FullMessageCell.swift; sourceTree = "<group>"; };
   9.260  		00AEB2F520DBA7DA00DA185A /* NeedsRefreshDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NeedsRefreshDelegate.swift; sourceTree = "<group>"; };
   9.261  		00BEC89620B85FD300A36E60 /* NoMessagesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoMessagesViewController.swift; sourceTree = "<group>"; };
   9.262 @@ -666,14 +640,12 @@
   9.263  		1500199C1F2B2C73003E670A /* Notification+CWServiceClientNotificationParsing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Notification+CWServiceClientNotificationParsing.swift"; sourceTree = "<group>"; };
   9.264  		1500199E1F2BA2EF003E670A /* SyncFlagsToServerOperationTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SyncFlagsToServerOperationTest.swift; sourceTree = "<group>"; };
   9.265  		150707DB21006CD000AA213F /* ComposeUtilTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeUtilTest.swift; sourceTree = "<group>"; };
   9.266 -		1508AEA91F862C85001D5230 /* SortedSetTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SortedSetTest.swift; sourceTree = "<group>"; };
   9.267  		150B84C320A44DE100D8B288 /* MoveToFolderOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoveToFolderOperation.swift; sourceTree = "<group>"; };
   9.268  		150B84C520A5DD0600D8B288 /* UIDCopyOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIDCopyOperation.swift; sourceTree = "<group>"; };
   9.269  		150B8E961FCDACBB00374438 /* ErrorPropagator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ErrorPropagator.swift; sourceTree = "<group>"; };
   9.270  		150B8E971FCDACBB00374438 /* AccountSettingsUserInputError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountSettingsUserInputError.swift; sourceTree = "<group>"; };
   9.271  		150B8EB21FCEB93D00374438 /* UIUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIUtils.swift; sourceTree = "<group>"; };
   9.272  		150DF6CF2052A13700A9DCF7 /* SecureWebViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureWebViewController.swift; sourceTree = "<group>"; };
   9.273 -		150DF6D22052ED4800A9DCF7 /* UIView+Autolayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Autolayout.swift"; sourceTree = "<group>"; };
   9.274  		150E18BF219D8C6C009E9048 /* ComposeViewModelSectionTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeViewModelSectionTest.swift; sourceTree = "<group>"; };
   9.275  		15175CEB205929FB00A8D9D0 /* CidHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CidHandler.swift; sourceTree = "<group>"; };
   9.276  		151AD7AC219D74C700FC36FF /* ComposeViewModelTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeViewModelTest.swift; sourceTree = "<group>"; };
   9.277 @@ -776,13 +748,11 @@
   9.278  		1568FEA01FACDCC500993EA3 /* IOS-211_hi_there.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "IOS-211_hi_there.txt"; sourceTree = "<group>"; };
   9.279  		1569AEA420E14DC2002102A0 /* ReUploadTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReUploadTest.swift; sourceTree = "<group>"; };
   9.280  		1569DDB7215395BE007A0398 /* NSAttributedString+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "NSAttributedString+Extension.swift"; path = "pEpForiOS/Util/NSAttributedString+Extension.swift"; sourceTree = SOURCE_ROOT; };
   9.281 -		157455C71FDFD2D4008CA78F /* NSAttributedString+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSAttributedString+Extensions.swift"; sourceTree = "<group>"; };
   9.282  		1574D077211356E000FEDC93 /* UrlClickHandlerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UrlClickHandlerProtocol.swift; sourceTree = "<group>"; };
   9.283  		1574D079211464CC00FEDC93 /* URL+MailTo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+MailTo.swift"; sourceTree = "<group>"; };
   9.284  		1574D07C2114696B00FEDC93 /* URL+MailToTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+MailToTest.swift"; sourceTree = "<group>"; };
   9.285  		1574D09A21186A1D00FEDC93 /* AddToContactsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AddToContactsViewController.swift; path = AddToContactsViewController/AddToContactsViewController.swift; sourceTree = "<group>"; };
   9.286  		157743B7217885EA0007222C /* RecipientTextViewModelTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecipientTextViewModelTest.swift; sourceTree = "<group>"; };
   9.287 -		1579397A1F4E00AF00A2A6CF /* UINavigationController+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Extensions.swift"; sourceTree = "<group>"; };
   9.288  		157C05472180756300E530DE /* DocumentAttachmentPickerViewModelTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentAttachmentPickerViewModelTest.swift; sourceTree = "<group>"; };
   9.289  		15865A8820319ADC00F7A4B5 /* Folder+pEp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Folder+pEp.swift"; sourceTree = "<group>"; };
   9.290  		15874BA82127493E00A3A4A6 /* SettingSwitchTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingSwitchTableViewCell.swift; sourceTree = "<group>"; };
   9.291 @@ -824,7 +794,6 @@
   9.292  		15BBBC621FD0496800B9DCC8 /* ReportingErrorContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportingErrorContainer.swift; sourceTree = "<group>"; };
   9.293  		15BBBC671FD04DFC00B9DCC8 /* ReportingErrorContainerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportingErrorContainerTest.swift; sourceTree = "<group>"; };
   9.294  		15BBBC6A1FD0527200B9DCC8 /* DisplayUserErrorTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplayUserErrorTest.swift; sourceTree = "<group>"; };
   9.295 -		15C5F2451F823752007DE086 /* SortedSet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SortedSet.swift; sourceTree = "<group>"; };
   9.296  		15D43999216E697700EB3933 /* AccountPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountPickerView.swift; sourceTree = "<group>"; };
   9.297  		15D4399B216E698E00EB3933 /* AccountPickerViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountPickerViewModel.swift; sourceTree = "<group>"; };
   9.298  		15D439A4216F7E0E00EB3933 /* AccountPickerViewModelTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountPickerViewModelTest.swift; sourceTree = "<group>"; };
   9.299 @@ -840,7 +809,6 @@
   9.300  		15EBE44120E5353D00268859 /* unittest_ios_3_peptest_ch_550A_9E62_6822_040E_57CB_151A_651C_4A5D_B15B_77A3_sec.asc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = unittest_ios_3_peptest_ch_550A_9E62_6822_040E_57CB_151A_651C_4A5D_B15B_77A3_sec.asc; sourceTree = "<group>"; };
   9.301  		15F0F7A921358B33002BE853 /* CdMessagePredicateFactory+Imap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CdMessagePredicateFactory+Imap.swift"; sourceTree = "<group>"; };
   9.302  		15F0F7AC213594FC002BE853 /* Folder+Imap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Folder+Imap.swift"; sourceTree = "<group>"; };
   9.303 -		15F0F7AE2135984C002BE853 /* Array+SortingAndSearching.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+SortingAndSearching.swift"; sourceTree = "<group>"; };
   9.304  		15F0F7B52136F6D1002BE853 /* CdFolderPredicateFactory+IMAP.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CdFolderPredicateFactory+IMAP.swift"; sourceTree = "<group>"; };
   9.305  		15F835231F34BE1300FCE887 /* AccountUserInput.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountUserInput.swift; sourceTree = "<group>"; };
   9.306  		15F835271F3B497D00FCE887 /* FetchMessagesOperationTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchMessagesOperationTest.swift; sourceTree = "<group>"; };
   9.307 @@ -914,7 +882,6 @@
   9.308  		43257C831F50629700DDC7F0 /* HtmlToAttributedTextSaxParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HtmlToAttributedTextSaxParser.swift; sourceTree = "<group>"; };
   9.309  		43257C851F50659200DDC7F0 /* StringHTMLExtensionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringHTMLExtensionTests.swift; sourceTree = "<group>"; };
   9.310  		43257C871F5067BE00DDC7F0 /* NSAttributedString+pEp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSAttributedString+pEp.swift"; sourceTree = "<group>"; };
   9.311 -		432645801F4C26CF002E3EF8 /* NSAttributedString+Parsing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSAttributedString+Parsing.swift"; sourceTree = "<group>"; };
   9.312  		43264E9A1D76B7110098DCAC /* SyncFlagsToServerOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SyncFlagsToServerOperation.swift; sourceTree = "<group>"; };
   9.313  		4326D3FE1EFBC8DB0016AB0D /* FolderInfoOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FolderInfoOperation.swift; sourceTree = "<group>"; };
   9.314  		43293EFA1EB9DD6700EEE010 /* UIViewController+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+Extension.swift"; sourceTree = "<group>"; };
   9.315 @@ -935,11 +902,9 @@
   9.316  		4334CF2F2020CFFE00B3193E /* OAuth2Type+LibAccountSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OAuth2Type+LibAccountSettings.swift"; sourceTree = "<group>"; };
   9.317  		4336229D1DC76B8100133B3D /* MessageModelTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageModelTests.swift; sourceTree = "<group>"; };
   9.318  		433724FC1DA2C2B1005E8DF5 /* pEp.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = pEp.entitlements; path = ../pEp.entitlements; sourceTree = "<group>"; };
   9.319 -		4337E52921B68FCA00826CAB /* Thread+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Thread+Extension.swift"; sourceTree = "<group>"; };
   9.320  		433BCD941D5388C100DD98EF /* ReplyUtil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReplyUtil.swift; sourceTree = "<group>"; };
   9.321  		433C51D11E66CB9C00272E19 /* CreateRequiredFoldersOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreateRequiredFoldersOperation.swift; sourceTree = "<group>"; };
   9.322  		433F2E2921E3581800E1CA49 /* ENGINE-505_Mail_NullInnerMimeType.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = "ENGINE-505_Mail_NullInnerMimeType.txt"; sourceTree = "<group>"; };
   9.323 -		4341980420AB037E0062F7F6 /* CGImageSource+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CGImageSource+Extension.swift"; sourceTree = "<group>"; };
   9.324  		4341EBCE2089F674004CE6B8 /* QualifyServerIsLocalOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QualifyServerIsLocalOperation.swift; sourceTree = "<group>"; };
   9.325  		4341EBD0208A0961004CE6B8 /* QualifyServerIsLocalServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QualifyServerIsLocalServiceProtocol.swift; sourceTree = "<group>"; };
   9.326  		43425EDA1FE3DE6E004A2728 /* OAuth2ProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuth2ProviderProtocol.swift; sourceTree = "<group>"; };
   9.327 @@ -1001,18 +966,10 @@
   9.328  		4356FFE42135448600804089 /* ReplyAllPossibleChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReplyAllPossibleChecker.swift; sourceTree = "<group>"; };
   9.329  		4356FFE621354A4B00804089 /* ReplyAllPossibleCheckerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReplyAllPossibleCheckerProtocol.swift; sourceTree = "<group>"; };
   9.330  		4356FFEB21356CB600804089 /* ReplyAllPossibleCheckerTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReplyAllPossibleCheckerTest.swift; sourceTree = "<group>"; };
   9.331 -		435B42401D211E5900119048 /* MiscUtil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MiscUtil.swift; sourceTree = "<group>"; };
   9.332  		435F7C74215E05DA00F21EFD /* 1364_Mail_missing_attached_image.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = 1364_Mail_missing_attached_image.txt; sourceTree = "<group>"; };
   9.333  		4360282C1ED6F27600C95FC4 /* NetworkError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkError.swift; sourceTree = "<group>"; };
   9.334  		4360282E1ED6F33400C95FC4 /* ImapSyncError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImapSyncError.swift; sourceTree = "<group>"; };
   9.335 -		4362398B1EADD61B00BD2EB9 /* CGSize+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CGSize+Extension.swift"; sourceTree = "<group>"; };
   9.336  		4362398F1EAE08F400BD2EB9 /* PEPSession+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "PEPSession+Extensions.swift"; sourceTree = "<group>"; };
   9.337 -		436239901EAE08F400BD2EB9 /* String+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Extensions.swift"; sourceTree = "<group>"; };
   9.338 -		436239911EAE08F400BD2EB9 /* String+pEp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+pEp.swift"; sourceTree = "<group>"; };
   9.339 -		436239971EAE0CE800BD2EB9 /* Date+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Date+Extension.swift"; sourceTree = "<group>"; };
   9.340 -		436239981EAE0CE800BD2EB9 /* NSRegularExpression+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSRegularExpression+Extension.swift"; sourceTree = "<group>"; };
   9.341 -		436239991EAE0CE800BD2EB9 /* OperationQueue+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "OperationQueue+Extension.swift"; sourceTree = "<group>"; };
   9.342 -		4362399E1EAE2F0A00BD2EB9 /* UITableView+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UITableView+Extension.swift"; sourceTree = "<group>"; };
   9.343  		43628765213D7A5E0066CD03 /* IOS-1300_odt_attachment.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "IOS-1300_odt_attachment.txt"; sourceTree = "<group>"; };
   9.344  		436795F71EE98B9A00B03E23 /* MessageReevalutionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageReevalutionTests.swift; sourceTree = "<group>"; };
   9.345  		436795F91EE98E9900B03E23 /* CommunicationTypeTests_test002@peptest.ch_sec.asc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "CommunicationTypeTests_test002@peptest.ch_sec.asc"; sourceTree = "<group>"; };
   9.346 @@ -1037,10 +994,8 @@
   9.347  		438052881FE3E24400ACF729 /* OAuth2AuthorizationProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuth2AuthorizationProtocol.swift; sourceTree = "<group>"; };
   9.348  		4380528A1FE3E2E800ACF729 /* OAuth2AuthorizationURLHandlerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuth2AuthorizationURLHandlerProtocol.swift; sourceTree = "<group>"; };
   9.349  		4381D0FE1E51A124002743C3 /* NetworkServiceWorker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkServiceWorker.swift; sourceTree = "<group>"; };
   9.350 -		43826F86212FF91D00BF1F7B /* Substring+Email.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Substring+Email.swift"; sourceTree = "<group>"; };
   9.351  		438281821E891B7E00087343 /* DateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateTests.swift; sourceTree = "<group>"; };
   9.352  		4382E6421CC600FF00AA27EA /* PersistentImapFolder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PersistentImapFolder.swift; sourceTree = "<group>"; };
   9.353 -		4384ABAF1F3B5A11006982B8 /* Data+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Data+Extensions.swift"; sourceTree = "<group>"; };
   9.354  		4388A0E02008AF61008CB98D /* public.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = public.xcconfig; sourceTree = "<group>"; };
   9.355  		4388A0E12008F813008CB98D /* OAuth2AccessToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuth2AccessToken.swift; sourceTree = "<group>"; };
   9.356  		4388A0E32008F8F4008CB98D /* OAuth2AccessTokenProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuth2AccessTokenProtocol.swift; sourceTree = "<group>"; };
   9.357 @@ -1052,7 +1007,6 @@
   9.358  		438F4EE0215F9CB300168B5E /* SimplifiedKeyImport_Harry_To_Rick_with_Leon.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SimplifiedKeyImport_Harry_To_Rick_with_Leon.txt; sourceTree = "<group>"; };
   9.359  		438F4EE4215FAD0500168B5E /* Harry Bryant iostest002@peptest.ch (0x5716EA2D9AE32468) pub-sec.asc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "Harry Bryant iostest002@peptest.ch (0x5716EA2D9AE32468) pub-sec.asc"; sourceTree = "<group>"; };
   9.360  		438F4EE8215FB99400168B5E /* Leon Kowalski (19B9EE3B) – Private.asc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "Leon Kowalski (19B9EE3B) – Private.asc"; sourceTree = "<group>"; };
   9.361 -		4395CDEB20AAB2E9003FC5F1 /* UIImage+GIF.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+GIF.swift"; sourceTree = "<group>"; };
   9.362  		4395CDED20AAC909003FC5F1 /* UIImageExtensionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIImageExtensionsTests.swift; sourceTree = "<group>"; };
   9.363  		4395CDEF20AAD0D6003FC5F1 /* icon_001.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = icon_001.gif; sourceTree = "<group>"; };
   9.364  		439680971D1855D400DA31D2 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; };
   9.365 @@ -1066,19 +1020,16 @@
   9.366  		43980E401CBD0BCA00A7FC3C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
   9.367  		43980E451CBD0BCA00A7FC3C /* pEpForiOSUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = pEpForiOSUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
   9.368  		43980E4B1CBD0BCA00A7FC3C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
   9.369 -		43980EDF1CBD24B000A7FC3C /* Log.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Log.swift; sourceTree = "<group>"; };
   9.370  		43980EEA1CBD24F100A7FC3C /* pEpForiOS-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "pEpForiOS-Bridging-Header.h"; sourceTree = "<group>"; };
   9.371  		43980EF91CBD415700A7FC3C /* AppConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppConfig.swift; sourceTree = "<group>"; };
   9.372  		43985D092044296D0080FA9A /* OAuth2AuthViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuth2AuthViewModel.swift; sourceTree = "<group>"; };
   9.373  		43985D0D204438480080FA9A /* AccountSettingsProtocol+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AccountSettingsProtocol+Extension.swift"; sourceTree = "<group>"; };
   9.374 -		439932281FEA7E7A00E92C35 /* String+Email.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Email.swift"; sourceTree = "<group>"; };
   9.375  		439932311FEA9B7200E92C35 /* SwipeCellKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SwipeCellKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
   9.376  		439A23E420B40FAC00417AF5 /* PEP_rating+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PEP_rating+Extension.swift"; sourceTree = "<group>"; };
   9.377  		439AAC551F21D0CC0018A29E /* CdFolder+Pantomime.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CdFolder+Pantomime.swift"; sourceTree = "<group>"; };
   9.378  		439D406F1CC78930009A4E7C /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
   9.379  		439D40711CC78958009A4E7C /* libbz2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libbz2.tbd; path = usr/lib/libbz2.tbd; sourceTree = SDKROOT; };
   9.380  		439D40731CC7897B009A4E7C /* libiconv.2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.2.tbd; path = usr/lib/libiconv.2.tbd; sourceTree = SDKROOT; };
   9.381 -		439D40791CC79423009A4E7C /* GCD.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GCD.swift; sourceTree = "<group>"; };
   9.382  		43A0B2CE214006FC00FB779D /* ReplyUtilTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReplyUtilTests.swift; sourceTree = "<group>"; };
   9.383  		43A26FB91E0408FB00AF0B84 /* ServiceErrorProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceErrorProtocol.swift; sourceTree = "<group>"; };
   9.384  		43A26FBE1E041BF200AF0B84 /* ImapSyncOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImapSyncOperation.swift; sourceTree = "<group>"; };
   9.385 @@ -1087,7 +1038,6 @@
   9.386  		43A5DE371D631D49001153AF /* UnencryptedHTMLMail.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = UnencryptedHTMLMail.txt; sourceTree = "<group>"; };
   9.387  		43A6E04A1E5726C8005BEE69 /* ReevaluateMessageRatingOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReevaluateMessageRatingOperation.swift; sourceTree = "<group>"; };
   9.388  		43A6E0571E57400E005BEE69 /* RatingReEvaluator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RatingReEvaluator.swift; sourceTree = "<group>"; };
   9.389 -		43AA82521E9B925C00ABD5A8 /* UIView+Util.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+Util.swift"; sourceTree = "<group>"; };
   9.390  		43AA825A1E9BC5FF00ABD5A8 /* AttachmentViewContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttachmentViewContainer.swift; sourceTree = "<group>"; };
   9.391  		43AA825C1E9BD60600ABD5A8 /* AttachmentsViewDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttachmentsViewDelegate.swift; sourceTree = "<group>"; };
   9.392  		43AAC2281F7A5AED00F435F4 /* BaseTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseTableViewController.swift; sourceTree = "<group>"; };
   9.393 @@ -1106,15 +1056,9 @@
   9.394  		43BB86931DB4E76D00980267 /* CdAccount+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CdAccount+Extension.swift"; sourceTree = "<group>"; };
   9.395  		43BBB5E61E267A3800104070 /* EncryptAndSendOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EncryptAndSendOperation.swift; sourceTree = "<group>"; };
   9.396  		43C046BE1CF48EA500BD0D9D /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; };
   9.397 -		43C273DA21C8F96D002EB4C8 /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = "<group>"; };
   9.398  		43C273DC21C9024A002EB4C8 /* LoggerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggerTest.swift; sourceTree = "<group>"; };
   9.399  		43C322041EA89EED005073FB /* HandshakePartnerTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HandshakePartnerTableViewCell.swift; sourceTree = "<group>"; };
   9.400 -		43C322061EA8E7AD005073FB /* UIButton+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIButton+Extension.swift"; sourceTree = "<group>"; };
   9.401  		43C322081EA90192005073FB /* PEP+UI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "PEP+UI.swift"; sourceTree = "<group>"; };
   9.402 -		43C3220A1EA915C6005073FB /* CGRect+Util.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CGRect+Util.swift"; sourceTree = "<group>"; };
   9.403 -		43C3220B1EA915C6005073FB /* UIColor+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIColor+Extension.swift"; sourceTree = "<group>"; };
   9.404 -		43C3220E1EA91764005073FB /* UIImage+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Extension.swift"; sourceTree = "<group>"; };
   9.405 -		43C3220F1EA91764005073FB /* UIImageView+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImageView+Extension.swift"; sourceTree = "<group>"; };
   9.406  		43C3B15F2003851100ED48A4 /* DecryptImportedMessagesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecryptImportedMessagesTests.swift; sourceTree = "<group>"; };
   9.407  		43C3B1612003896800ED48A4 /* IOS-884_001_Mail_from_P4A.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "IOS-884_001_Mail_from_P4A.txt"; sourceTree = "<group>"; };
   9.408  		43C3B16520038B2500ED48A4 /* IOS-884_001_test010@peptest.ch.pub.key */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "IOS-884_001_test010@peptest.ch.pub.key"; sourceTree = "<group>"; };
   9.409 @@ -1151,11 +1095,8 @@
   9.410  		43E657E61F3CAB310014CBEC /* HtmlToMarkdownSaxParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HtmlToMarkdownSaxParser.swift; sourceTree = "<group>"; };
   9.411  		43E74C731E38DE2200A2F7A6 /* ImapFlagsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImapFlagsTests.swift; sourceTree = "<group>"; };
   9.412  		43E7B6741DE4A53A0017D707 /* CdIdentity+pEp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CdIdentity+pEp.swift"; sourceTree = "<group>"; };
   9.413 -		43E88BDD1EFA665600E0B224 /* AsyncStateMachineProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsyncStateMachineProtocol.swift; sourceTree = "<group>"; };
   9.414 -		43E88BDF1EFA667600E0B224 /* AsyncStateMachine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsyncStateMachine.swift; sourceTree = "<group>"; };
   9.415  		43E9BC631DB518A700AD2352 /* CdFolder+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CdFolder+Extension.swift"; sourceTree = "<group>"; };
   9.416  		43EC03471F4AE28F0026E152 /* String+Attachment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Attachment.swift"; sourceTree = "<group>"; };
   9.417 -		43EC75A3216498AD00048CFE /* Log+ASL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Log+ASL.swift"; sourceTree = "<group>"; };
   9.418  		43EC75AB2164C26100048CFE /* SetOwnKeyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetOwnKeyViewController.swift; sourceTree = "<group>"; };
   9.419  		43EC75AD2164D03500048CFE /* SetOwnKeyViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetOwnKeyViewModel.swift; sourceTree = "<group>"; };
   9.420  		43EC75B22164E97800048CFE /* DecryptionUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecryptionUtil.swift; sourceTree = "<group>"; };
   9.421 @@ -1172,10 +1113,8 @@
   9.422  		43F6DFD61DEEC752006B526F /* FetchMessagesOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchMessagesOperation.swift; sourceTree = "<group>"; };
   9.423  		43F7F0791F6AD44600BDF151 /* HandshakeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HandshakeTests.swift; sourceTree = "<group>"; };
   9.424  		43F7F07B1F6AD4FD00BDF151 /* HandshakeTests_mail_001.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = HandshakeTests_mail_001.txt; sourceTree = "<group>"; };
   9.425 -		43F848481EAA09AE00DBE460 /* Weak.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Weak.swift; sourceTree = "<group>"; };
   9.426  		43F84CD11CD899760092FCAE /* SyncFoldersFromServerOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SyncFoldersFromServerOperation.swift; sourceTree = "<group>"; };
   9.427  		43F9D9991E92725700F78A1C /* AttachmentsViewHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttachmentsViewHelper.swift; sourceTree = "<group>"; };
   9.428 -		43FAA0D11EC9972B005BFC4B /* Tuple.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tuple.swift; sourceTree = "<group>"; };
   9.429  		43FAA0D31EC9CBC0005BFC4B /* DecryptionTestsInternal.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DecryptionTestsInternal.swift; sourceTree = "<group>"; };
   9.430  		43FC02111F4D913D00273304 /* NSHTML_2017-08-09 15_40_53 +0000.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "NSHTML_2017-08-09 15_40_53 +0000.html"; sourceTree = "<group>"; };
   9.431  		43FE802D209992B800E97AB3 /* QualifyServerIsLocalService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QualifyServerIsLocalService.swift; sourceTree = "<group>"; };
   9.432 @@ -1205,7 +1144,6 @@
   9.433  		49A6114D2179F3A1006BA3C5 /* UnitTestUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnitTestUtils.swift; sourceTree = "<group>"; };
   9.434  		49C2750020C04DDB0075F6FF /* EmailViewController+DisplayedMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EmailViewController+DisplayedMessage.swift"; sourceTree = "<group>"; };
   9.435  		49C34AF520E4F649009D11CC /* CellDetailTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellDetailTransition.swift; sourceTree = "<group>"; };
   9.436 -		49D292A220F3ABA600F33C78 /* CredentialTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CredentialTextField.swift; sourceTree = "<group>"; };
   9.437  		49D3BECB20F8F7330043E05D /* LoginViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewController.swift; sourceTree = "<group>"; };
   9.438  		49D521531E73E1C20097987B /* MessageModel.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MessageModel.framework; sourceTree = BUILT_PRODUCTS_DIR; };
   9.439  		49D521561E73E1C70097987B /* ServerConfig.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = ServerConfig.framework; sourceTree = BUILT_PRODUCTS_DIR; };
   9.440 @@ -1214,8 +1152,10 @@
   9.441  		5D039AA11D0EEA3700AD59EC /* DecryptMessagesOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DecryptMessagesOperation.swift; sourceTree = "<group>"; };
   9.442  		5DEBAA471DE59C3B00FAE12C /* NetworkServiceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkServiceTests.swift; sourceTree = "<group>"; };
   9.443  		8B69E3981E30F80E0022959E /* Appearance.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Appearance.swift; sourceTree = "<group>"; };
   9.444 -		8B81BB8F1E03F73100D38C82 /* SegueHandlerType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SegueHandlerType.swift; sourceTree = "<group>"; };
   9.445  		A1B50A811CD26FF100B1A997 /* Constants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
   9.446 +		B70A3A62220065F500EDCE61 /* String+pEp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+pEp.swift"; sourceTree = "<group>"; };
   9.447 +		B70A3A9122089D5000EDCE61 /* Log+ASL.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Log+ASL.swift"; sourceTree = "<group>"; };
   9.448 +		B70A3A9222089D5000EDCE61 /* Log.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Log.swift; sourceTree = "<group>"; };
   9.449  		B70A3C3F1E817CFA0036876F /* FolderViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FolderViewModel.swift; path = Folder/ViewModel/FolderViewModel.swift; sourceTree = "<group>"; };
   9.450  		B716055F20D3ECC900A733D6 /* MoveToFolderTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoveToFolderTableViewController.swift; sourceTree = "<group>"; };
   9.451  		B71EBBBB1E55E4AE00150177 /* FolderTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FolderTableViewController.swift; path = Folder/FolderTableViewController.swift; sourceTree = "<group>"; };
   9.452 @@ -1223,18 +1163,28 @@
   9.453  		B722EC641E5B49BA00A2B9D5 /* FolderSectionViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FolderSectionViewModel.swift; path = Folder/ViewModel/FolderSectionViewModel.swift; sourceTree = "<group>"; };
   9.454  		B722EC791E5C879000A2B9D5 /* FolderUiProtocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FolderUiProtocols.swift; sourceTree = "<group>"; };
   9.455  		B729BEC51E7C35E200793110 /* FilterUpdateProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FilterUpdateProtocol.swift; path = Filter/ViewModel/FilterUpdateProtocol.swift; sourceTree = "<group>"; };
   9.456 -		B7365CDD1EAF45F30036ECC7 /* UITextField+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UITextField+Extension.swift"; sourceTree = "<group>"; };
   9.457  		B740B75C1E4B1C2D002585E1 /* jsonMimeType.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = jsonMimeType.txt; sourceTree = "<group>"; };
   9.458  		B740B75E1E4B1C46002585E1 /* MimeTypeUtil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MimeTypeUtil.swift; sourceTree = "<group>"; };
   9.459  		B74F81011EB0E20000519FCC /* LoginViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoginViewModel.swift; sourceTree = "<group>"; };
   9.460  		B75FF00A1EFD420F00C57289 /* EmailListViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmailListViewModel.swift; sourceTree = "<group>"; };
   9.461 -		B761A80920F5F0A6000832C2 /* UIBarButtonItem+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIBarButtonItem+Extension.swift"; sourceTree = "<group>"; };
   9.462  		B76CF8B220D2739B002429A8 /* MoveToFolderViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoveToFolderViewModel.swift; sourceTree = "<group>"; };
   9.463 +		B7745838221C191600664282 /* SecretUITestData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretUITestData.swift; sourceTree = "<group>"; };
   9.464  		B78309C71EAA09040051A2E0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/AccountCreation.storyboard; sourceTree = "<group>"; };
   9.465  		B78CF8241E76D706008C1739 /* FilterTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FilterTableViewController.swift; path = Filter/FilterTableViewController.swift; sourceTree = "<group>"; };
   9.466  		B78CF8281E76E0F1008C1739 /* FilterViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FilterViewModel.swift; path = Filter/ViewModel/FilterViewModel.swift; sourceTree = "<group>"; };
   9.467  		B78CF82A1E76E146008C1739 /* FilterCellViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FilterCellViewModel.swift; path = Filter/ViewModel/FilterCellViewModel.swift; sourceTree = "<group>"; };
   9.468  		B7D1EEC71E8BEC8D00F190E3 /* CollapsibleTableViewHeader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CollapsibleTableViewHeader.swift; path = Folder/CollapsibleTableViewHeader.swift; sourceTree = "<group>"; };
   9.469 +		B7DB7FC32215C4FF003968DA /* UINavigationController+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Extensions.swift"; sourceTree = "<group>"; };
   9.470 +		B7DB7FC52215C57F003968DA /* UIView+Autolayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+Autolayout.swift"; sourceTree = "<group>"; };
   9.471 +		B7DB7FC62215C57F003968DA /* UIView+Util.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+Util.swift"; sourceTree = "<group>"; };
   9.472 +		B7DB7FC92215D69C003968DA /* CredentialTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CredentialTextField.swift; sourceTree = "<group>"; };
   9.473 +		B7DB7FD1221AD332003968DA /* SegueHandlerType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SegueHandlerType.swift; sourceTree = "<group>"; };
   9.474 +		B7DB7FD3221AD3BB003968DA /* UITextField+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UITextField+Extension.swift"; sourceTree = "<group>"; };
   9.475 +		B7DB7FD4221AD3BB003968DA /* UIButton+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIButton+Extension.swift"; sourceTree = "<group>"; };
   9.476 +		B7DB7FD5221AD3BB003968DA /* UITableView+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UITableView+Extension.swift"; sourceTree = "<group>"; };
   9.477 +		B7DB7FD9221ADDAF003968DA /* UIBarButtonItem+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIBarButtonItem+Extension.swift"; sourceTree = "<group>"; };
   9.478 +		B7DB7FDB221ADDBD003968DA /* UIImageView+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImageView+Extension.swift"; sourceTree = "<group>"; };
   9.479 +		B7DB7FEA221AFE10003968DA /* pEpIOSToolbox.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = pEpIOSToolbox.framework; sourceTree = BUILT_PRODUCTS_DIR; };
   9.480  		B7F4A792212DDFC500507B76 /* EmailListViewModelTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmailListViewModelTest.swift; sourceTree = "<group>"; };
   9.481  		F73E4F71217F238300CCFFED /* FolderSectionViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FolderSectionViewModelTests.swift; sourceTree = "<group>"; };
   9.482  		F73E4F792180744700CCFFED /* FolderCellViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FolderCellViewModelTests.swift; sourceTree = "<group>"; };
   9.483 @@ -1258,6 +1208,7 @@
   9.484  				439680981D1855D400DA31D2 /* WebKit.framework in Frameworks */,
   9.485  				43800D991D112A2A00821E34 /* libxml2.tbd in Frameworks */,
   9.486  				43C046BF1CF48EA500BD0D9D /* AddressBook.framework in Frameworks */,
   9.487 +				B774583A221C320B00664282 /* pEpIOSToolbox.framework in Frameworks */,
   9.488  				439D40741CC7897B009A4E7C /* libiconv.2.tbd in Frameworks */,
   9.489  				439D40721CC78958009A4E7C /* libbz2.tbd in Frameworks */,
   9.490  				49D521541E73E1C20097987B /* MessageModel.framework in Frameworks */,
   9.491 @@ -1346,6 +1297,7 @@
   9.492  		150DF6D12052A99800A9DCF7 /* SecureWebViewController */ = {
   9.493  			isa = PBXGroup;
   9.494  			children = (
   9.495 +				B7DB7FC92215D69C003968DA /* CredentialTextField.swift */,
   9.496  				150DF6CF2052A13700A9DCF7 /* SecureWebViewController.swift */,
   9.497  				15175CEB205929FB00A8D9D0 /* CidHandler.swift */,
   9.498  			);
   9.499 @@ -2185,34 +2137,23 @@
   9.500  		4362398D1EAE08F400BD2EB9 /* Extensions */ = {
   9.501  			isa = PBXGroup;
   9.502  			children = (
   9.503 -				4384ABAF1F3B5A11006982B8 /* Data+Extensions.swift */,
   9.504 -				436239971EAE0CE800BD2EB9 /* Date+Extension.swift */,
   9.505 -				436239981EAE0CE800BD2EB9 /* NSRegularExpression+Extension.swift */,
   9.506 -				436239991EAE0CE800BD2EB9 /* OperationQueue+Extension.swift */,
   9.507  				4362398F1EAE08F400BD2EB9 /* PEPSession+Extensions.swift */,
   9.508 -				436239901EAE08F400BD2EB9 /* String+Extensions.swift */,
   9.509 -				436239911EAE08F400BD2EB9 /* String+pEp.swift */,
   9.510 +				B70A3A62220065F500EDCE61 /* String+pEp.swift */,
   9.511  				43E657D01F3C33C30014CBEC /* String+HTML.swift */,
   9.512  				43EC03471F4AE28F0026E152 /* String+Attachment.swift */,
   9.513 -				439932281FEA7E7A00E92C35 /* String+Email.swift */,
   9.514 -				43826F86212FF91D00BF1F7B /* Substring+Email.swift */,
   9.515  				430E0BE61EAF5E2600378EC2 /* NSMutableDictionary+pEp.swift */,
   9.516  				432A5E251EB344C3007CB670 /* PEP_color+Extension.swift */,
   9.517  				432AC3051ECB0C44007DC418 /* CWIMAPMessage+pEp.swift */,
   9.518  				1500199C1F2B2C73003E670A /* Notification+CWServiceClientNotificationParsing.swift */,
   9.519  				431C2B181F38888B00D87FFD /* ConnectionTransport+AccountSettings.swift */,
   9.520  				43E0CA291F4AB81600D9BB7E /* Attachment+Extension.swift */,
   9.521 -				432645801F4C26CF002E3EF8 /* NSAttributedString+Parsing.swift */,
   9.522  				43257C871F5067BE00DDC7F0 /* NSAttributedString+pEp.swift */,
   9.523  				1541D7EC1FC81D4200D52A5D /* URL+Extensions.swift */,
   9.524  				1541D7F21FC8292D00D52A5D /* URL+MIME.swift */,
   9.525 -				157455C71FDFD2D4008CA78F /* NSAttributedString+Extensions.swift */,
   9.526  				155050F11FE95D8A009CEAD2 /* UserNotificationTool+pEp.swift */,
   9.527  				4315E4C020120F1600F68763 /* NSSecureCoding+Extension.swift */,
   9.528  				439A23E420B40FAC00417AF5 /* PEP_rating+Extension.swift */,
   9.529  				1574D079211464CC00FEDC93 /* URL+MailTo.swift */,
   9.530 -				15F0F7AE2135984C002BE853 /* Array+SortingAndSearching.swift */,
   9.531 -				4337E52921B68FCA00826CAB /* Thread+Extension.swift */,
   9.532  			);
   9.533  			path = Extensions;
   9.534  			sourceTree = "<group>";
   9.535 @@ -2302,7 +2243,6 @@
   9.536  				151F7202202A06D30057C74D /* Util */,
   9.537  				15F82A072006552B0084F9EA /* Tests from MessageModel in Exile due to Apple Bug */,
   9.538  				43980E401CBD0BCA00A7FC3C /* Info.plist */,
   9.539 -				1508AEA91F862C85001D5230 /* SortedSetTest.swift */,
   9.540  				4336229D1DC76B8100133B3D /* MessageModelTests.swift */,
   9.541  				438D253B1D4B9E7500BFF7AA /* MimeTests.swift */,
   9.542  				43C7B9D01CEC4DDF007A612F /* MiscTests.swift */,
   9.543 @@ -2339,7 +2279,7 @@
   9.544  		43980E481CBD0BCA00A7FC3C /* pEpForiOSUITests */ = {
   9.545  			isa = PBXGroup;
   9.546  			children = (
   9.547 -				008335A0210F28C7006E9306 /* SecretUITestData.swift */,
   9.548 +				B7745838221C191600664282 /* SecretUITestData.swift */,
   9.549  				43B0443A20067D25007BCE3F /* UITestDataProtocol.swift */,
   9.550  				43B0443820067CC7007BCE3F /* UIAccount.swift */,
   9.551  				43980E4B1CBD0BCA00A7FC3C /* Info.plist */,
   9.552 @@ -2363,20 +2303,15 @@
   9.553  		43980EDE1CBD24B000A7FC3C /* Util */ = {
   9.554  			isa = PBXGroup;
   9.555  			children = (
   9.556 -				43D86EA721BE5E5800C18418 /* Log+ASL */,
   9.557 +				B70A3A9022089D3C00EDCE61 /* Log */,
   9.558  				151F71D02029F9F80057C74D /* IMAP */,
   9.559  				4362398D1EAE08F400BD2EB9 /* Extensions */,
   9.560  				B740B7571E4B1B80002585E1 /* MimeTypes */,
   9.561  				43306EBC1FE125950045DD00 /* OAuth2 */,
   9.562  				37A3D6202214333200E11415 /* Reachability */,
   9.563 -				8B81BB8F1E03F73100D38C82 /* SegueHandlerType.swift */,
   9.564  				43980EF91CBD415700A7FC3C /* AppConfig.swift */,
   9.565  				43C6F35A1CBE7496006A2A18 /* ConnectionManager.swift */,
   9.566  				A1B50A811CD26FF100B1A997 /* Constants.swift */,
   9.567 -				439D40791CC79423009A4E7C /* GCD.swift */,
   9.568 -				43980EDF1CBD24B000A7FC3C /* Log.swift */,
   9.569 -				43C273DA21C8F96D002EB4C8 /* Logger.swift */,
   9.570 -				435B42401D211E5900119048 /* MiscUtil.swift */,
   9.571  				5D039A9B1D0EE7F900AD59EC /* PEPUtil.swift */,
   9.572  				431798761CF87FE6007DD655 /* ReferenceCounter.swift */,
   9.573  				433BCD941D5388C100DD98EF /* ReplyUtil.swift */,
   9.574 @@ -2389,13 +2324,8 @@
   9.575  				436C232C1E02A2D900071430 /* KickOffMySelfProtocol.swift */,
   9.576  				436C232E1E02A52D00071430 /* LimitedOperationQueue.swift */,
   9.577  				8B69E3981E30F80E0022959E /* Appearance.swift */,
   9.578 -				43F848481EAA09AE00DBE460 /* Weak.swift */,
   9.579  				434F40931EB0B173002FBF0D /* ObservableValue.swift */,
   9.580 -				43FAA0D11EC9972B005BFC4B /* Tuple.swift */,
   9.581  				43AE48E61EEFC93900B92BB6 /* DebugMergePolicy.swift */,
   9.582 -				43E88BDD1EFA665600E0B224 /* AsyncStateMachineProtocol.swift */,
   9.583 -				43E88BDF1EFA667600E0B224 /* AsyncStateMachine.swift */,
   9.584 -				15C5F2451F823752007DE086 /* SortedSet.swift */,
   9.585  				15255B021F825CD100A2CFC9 /* IdentityImageTool.swift */,
   9.586  				155050EF1FE82356009CEAD2 /* UserNotificationTool.swift */,
   9.587  			);
   9.588 @@ -2424,35 +2354,20 @@
   9.589  		43AA82511E9B925000ABD5A8 /* Util */ = {
   9.590  			isa = PBXGroup;
   9.591  			children = (
   9.592 +				B7DB7FC22215C484003968DA /* Extensions */,
   9.593  				15D43998216E695500EB3933 /* AccountPicker */,
   9.594  				15265973216234C0006A78DF /* SuggestTableViewController */,
   9.595 -				49D292A220F3ABA600F33C78 /* CredentialTextField.swift */,
   9.596  				150DF6D12052A99800A9DCF7 /* SecureWebViewController */,
   9.597  				43AAC2281F7A5AED00F435F4 /* BaseTableViewController.swift */,
   9.598 +				B7DB7FD1221AD332003968DA /* SegueHandlerType.swift */,
   9.599  				43AAC2291F7A5AEE00F435F4 /* BaseViewController.swift */,
   9.600 -				43293EFA1EB9DD6700EEE010 /* UIViewController+Extension.swift */,
   9.601 -				43C3220E1EA91764005073FB /* UIImage+Extension.swift */,
   9.602 -				43C3220F1EA91764005073FB /* UIImageView+Extension.swift */,
   9.603 -				43C3220A1EA915C6005073FB /* CGRect+Util.swift */,
   9.604 -				43C3220B1EA915C6005073FB /* UIColor+Extension.swift */,
   9.605 -				434AC3E220A450D700C11B7F /* UIAlertController+Extension.swift */,
   9.606  				43C322081EA90192005073FB /* PEP+UI.swift */,
   9.607 -				43AA82521E9B925C00ABD5A8 /* UIView+Util.swift */,
   9.608 -				43C322061EA8E7AD005073FB /* UIButton+Extension.swift */,
   9.609 -				4362398B1EADD61B00BD2EB9 /* CGSize+Extension.swift */,
   9.610 -				4362399E1EAE2F0A00BD2EB9 /* UITableView+Extension.swift */,
   9.611 -				B7365CDD1EAF45F30036ECC7 /* UITextField+Extension.swift */,
   9.612 -				1579397A1F4E00AF00A2A6CF /* UINavigationController+Extensions.swift */,
   9.613  				4330278D1F7BABFF00D685F8 /* GradientView.swift */,
   9.614  				15B2204F1FBF5D6E00CA52BA /* InfoPlist.swift */,
   9.615  				15B220511FC2DAE200CA52BA /* InfoPlist+pEpStrings.swift */,
   9.616  				150B8EB21FCEB93D00374438 /* UIUtils.swift */,
   9.617  				43985D0D204438480080FA9A /* AccountSettingsProtocol+Extension.swift */,
   9.618 -				150DF6D22052ED4800A9DCF7 /* UIView+Autolayout.swift */,
   9.619 -				4341980420AB037E0062F7F6 /* CGImageSource+Extension.swift */,
   9.620 -				4395CDEB20AAB2E9003FC5F1 /* UIImage+GIF.swift */,
   9.621  				490CEBA62100EAD500E8579C /* SelfDismissable.swift */,
   9.622 -				B761A80920F5F0A6000832C2 /* UIBarButtonItem+Extension.swift */,
   9.623  				1574D077211356E000FEDC93 /* UrlClickHandlerProtocol.swift */,
   9.624  				1574D09A21186A1D00FEDC93 /* AddToContactsViewController.swift */,
   9.625  				4356FFE621354A4B00804089 /* ReplyAllPossibleCheckerProtocol.swift */,
   9.626 @@ -2524,14 +2439,6 @@
   9.627  			path = AppSettings;
   9.628  			sourceTree = "<group>";
   9.629  		};
   9.630 -		43D86EA721BE5E5800C18418 /* Log+ASL */ = {
   9.631 -			isa = PBXGroup;
   9.632 -			children = (
   9.633 -				43EC75A3216498AD00048CFE /* Log+ASL.swift */,
   9.634 -			);
   9.635 -			path = "Log+ASL";
   9.636 -			sourceTree = "<group>";
   9.637 -		};
   9.638  		43E58EB21CBF8301008AA7A7 /* Models */ = {
   9.639  			isa = PBXGroup;
   9.640  			children = (
   9.641 @@ -2707,6 +2614,7 @@
   9.642  		495560841E7150ED0016579E /* Frameworks */ = {
   9.643  			isa = PBXGroup;
   9.644  			children = (
   9.645 +				B7DB7FEA221AFE10003968DA /* pEpIOSToolbox.framework */,
   9.646  				43D86ECA21BE6C7B00C18418 /* CleanroomASL.framework */,
   9.647  				439932311FEA9B7200E92C35 /* SwipeCellKit.framework */,
   9.648  				43B54F971FE02D02008EC427 /* AppAuth.framework */,
   9.649 @@ -2777,6 +2685,15 @@
   9.650  			path = ..;
   9.651  			sourceTree = "<group>";
   9.652  		};
   9.653 +		B70A3A9022089D3C00EDCE61 /* Log */ = {
   9.654 +			isa = PBXGroup;
   9.655 +			children = (
   9.656 +				B70A3A9122089D5000EDCE61 /* Log+ASL.swift */,
   9.657 +				B70A3A9222089D5000EDCE61 /* Log.swift */,
   9.658 +			);
   9.659 +			path = Log;
   9.660 +			sourceTree = "<group>";
   9.661 +		};
   9.662  		B70D32A5205BCC020094A92A /* ViewModel */ = {
   9.663  			isa = PBXGroup;
   9.664  			children = (
   9.665 @@ -2968,6 +2885,23 @@
   9.666  			name = ViewModel;
   9.667  			sourceTree = "<group>";
   9.668  		};
   9.669 +		B7DB7FC22215C484003968DA /* Extensions */ = {
   9.670 +			isa = PBXGroup;
   9.671 +			children = (
   9.672 +				B7DB7FDB221ADDBD003968DA /* UIImageView+Extension.swift */,
   9.673 +				B7DB7FD9221ADDAF003968DA /* UIBarButtonItem+Extension.swift */,
   9.674 +				B7DB7FD4221AD3BB003968DA /* UIButton+Extension.swift */,
   9.675 +				B7DB7FD5221AD3BB003968DA /* UITableView+Extension.swift */,
   9.676 +				B7DB7FD3221AD3BB003968DA /* UITextField+Extension.swift */,
   9.677 +				B7DB7FC62215C57F003968DA /* UIView+Util.swift */,
   9.678 +				B7DB7FC52215C57F003968DA /* UIView+Autolayout.swift */,
   9.679 +				B7DB7FC32215C4FF003968DA /* UINavigationController+Extensions.swift */,
   9.680 +				43293EFA1EB9DD6700EEE010 /* UIViewController+Extension.swift */,
   9.681 +				434AC3E220A450D700C11B7F /* UIAlertController+Extension.swift */,
   9.682 +			);
   9.683 +			path = Extensions;
   9.684 +			sourceTree = "<group>";
   9.685 +		};
   9.686  		F73E4F7B2180746400CCFFED /* Folder */ = {
   9.687  			isa = PBXGroup;
   9.688  			children = (
   9.689 @@ -3271,6 +3205,7 @@
   9.690  			files = (
   9.691  				002375D420DCF59D00663961 /* MoveToAccountViewController.swift in Sources */,
   9.692  				496C0EEB20BC4B370009B5B9 /* EmailListViewModel+EmailDisplayDelegate.swift in Sources */,
   9.693 +				B70A3A9422089D5000EDCE61 /* Log.swift in Sources */,
   9.694  				4315E4C3201242BB00F68763 /* OAuth2Type+Extension.swift in Sources */,
   9.695  				43264E9B1D76B7110098DCAC /* SyncFlagsToServerOperation.swift in Sources */,
   9.696  				4351C2D11F4441190053381F /* houdini_html_u.c in Sources */,
   9.697 @@ -3279,7 +3214,6 @@
   9.698  				15874BCA2127493E00A3A4A6 /* UnecryptedSubjectViewModel.swift in Sources */,
   9.699  				43EE99481E438E320060EACE /* FlagImages.swift in Sources */,
   9.700  				220DCE341E0AB5CC002FE716 /* MailinglistCell.swift in Sources */,
   9.701 -				436239941EAE08F400BD2EB9 /* String+Extensions.swift in Sources */,
   9.702  				43AA825D1E9BD60600ABD5A8 /* AttachmentsViewDelegate.swift in Sources */,
   9.703  				152A39D821905C3E00D9F8E4 /* BodyCellViewModel.swift in Sources */,
   9.704  				220DCE371E0AB5CC002FE716 /* MessageSubjectCell.swift in Sources */,
   9.705 @@ -3295,15 +3229,14 @@
   9.706  				5D039AA21D0EEA3700AD59EC /* DecryptMessagesOperation.swift in Sources */,
   9.707  				439AAC561F21D0CC0018A29E /* CdFolder+Pantomime.swift in Sources */,
   9.708  				4351C2D51F4441190053381F /* latex.c in Sources */,
   9.709 -				439932291FEA7E7A00E92C35 /* String+Email.swift in Sources */,
   9.710  				37A3D6262215695400E11415 /* ReachabilityUtilsProtocol.swift in Sources */,
   9.711  				43498CDB200CF20F006DC947 /* LoginViewModelLoginErrorDelegate.swift in Sources */,
   9.712  				1560D1721F6FD1F600A75B39 /* FetchOlderImapMessagesService.swift in Sources */,
   9.713  				15874BC42127493E00A3A4A6 /* SettingsCellViewModel.swift in Sources */,
   9.714  				438D5A711EA77CFC001A37E1 /* HandshakeViewController.swift in Sources */,
   9.715 -				4384ABB01F3B5A11006982B8 /* Data+Extensions.swift in Sources */,
   9.716  				B729BEC61E7C35E200793110 /* FilterUpdateProtocol.swift in Sources */,
   9.717  				431798771CF87FE6007DD655 /* ReferenceCounter.swift in Sources */,
   9.718 +				B7DB7FDA221ADDAF003968DA /* UIBarButtonItem+Extension.swift in Sources */,
   9.719  				15874BC62127493E00A3A4A6 /* SettingsTableViewController.swift in Sources */,
   9.720  				B740B75F1E4B1C46002585E1 /* MimeTypeUtil.swift in Sources */,
   9.721  				1555E97C1FD587A300BF8E0E /* Message+IMAP.swift in Sources */,
   9.722 @@ -3312,7 +3245,6 @@
   9.723  				4351C2C91F4441190053381F /* buffer.c in Sources */,
   9.724  				434B5D191DDF67E400BEDEF0 /* CdMessage+Extension.swift in Sources */,
   9.725  				152A39C621905C3E00D9F8E4 /* ComposeViewModelState.swift in Sources */,
   9.726 -				4362399F1EAE2F0A00BD2EB9 /* UITableView+Extension.swift in Sources */,
   9.727  				F7C16A5921A56445004B44F2 /* FolderSyncService.swift in Sources */,
   9.728  				15874BC92127493E00A3A4A6 /* PassiveModeViewModel.swift in Sources */,
   9.729  				4334CF302020CFFE00B3193E /* OAuth2Type+LibAccountSettings.swift in Sources */,
   9.730 @@ -3329,7 +3261,6 @@
   9.731  				150B8EB31FCEB93D00374438 /* UIUtils.swift in Sources */,
   9.732  				43AAC22A1F7A5AEE00F435F4 /* BaseTableViewController.swift in Sources */,
   9.733  				436C232D1E02A2D900071430 /* KickOffMySelfProtocol.swift in Sources */,
   9.734 -				43C322111EA91764005073FB /* UIImageView+Extension.swift in Sources */,
   9.735  				220DCE351E0AB5CC002FE716 /* MessageContentCell.swift in Sources */,
   9.736  				1526597A21623652006A78DF /* SuggestViewModel.swift in Sources */,
   9.737  				4351C2D31F4441190053381F /* inlines.c in Sources */,
   9.738 @@ -3339,8 +3270,6 @@
   9.739  				15484B6A2105D5C500F9D962 /* EmailConnectInfo.swift in Sources */,
   9.740  				15D4399A216E697700EB3933 /* AccountPickerView.swift in Sources */,
   9.741  				1554756C213FE139005A52D0 /* UnifiedFilter.swift in Sources */,
   9.742 -				15F0F7AF2135984C002BE853 /* Array+SortingAndSearching.swift in Sources */,
   9.743 -				49D292A320F3ABA600F33C78 /* CredentialTextField.swift in Sources */,
   9.744  				4341EBCF2089F674004CE6B8 /* QualifyServerIsLocalOperation.swift in Sources */,
   9.745  				15265962216230B1006A78DF /* ContactCell.swift in Sources */,
   9.746  				43425EDF1FE3E052004A2728 /* OAuth2ProviderFactory.swift in Sources */,
   9.747 @@ -3351,16 +3280,13 @@
   9.748  				43425EDD1FE3DF3B004A2728 /* OAuth2Provider.swift in Sources */,
   9.749  				431144B51CC0FCA40007639D /* StoreFolderOperation.swift in Sources */,
   9.750  				152A39E021905C3E00D9F8E4 /* RecipientCell.swift in Sources */,
   9.751 -				439D407A1CC79423009A4E7C /* GCD.swift in Sources */,
   9.752  				152A39C721905C3E00D9F8E4 /* ComposeViewModel.swift in Sources */,
   9.753 -				4362399B1EAE0CE800BD2EB9 /* Date+Extension.swift in Sources */,
   9.754  				43040A531E9776220083DED8 /* AttachmentSummaryView.swift in Sources */,
   9.755  				431D60DB1E93BB2D001266D7 /* AttachmentsView.swift in Sources */,
   9.756  				1569DDB8215395BE007A0398 /* NSAttributedString+Extension.swift in Sources */,
   9.757  				1574D078211356E000FEDC93 /* UrlClickHandlerProtocol.swift in Sources */,
   9.758  				152A39D621905C3E00D9F8E4 /* BodyCell.swift in Sources */,
   9.759  				43ED53791CC77F95006AB156 /* UserInfoTableViewController.swift in Sources */,
   9.760 -				43C322101EA91764005073FB /* UIImage+Extension.swift in Sources */,
   9.761  				15865A8920319ADC00F7A4B5 /* Folder+pEp.swift in Sources */,
   9.762  				1547509A1FE7C0B4000D8004 /* FetchNumberOfNewMailsOperation.swift in Sources */,
   9.763  				43C6F35B1CBE7496006A2A18 /* ConnectionManager.swift in Sources */,
   9.764 @@ -3368,12 +3294,12 @@
   9.765  				43122B1B1DF5B48B00610253 /* SmtpService.swift in Sources */,
   9.766  				43CE63C51DE87FB200FAC505 /* Identity+pEp.swift in Sources */,
   9.767  				220DCE2E1E0AB544002FE716 /* MessageCell.swift in Sources */,
   9.768 +				B7DB7FD8221AD3BB003968DA /* UITableView+Extension.swift in Sources */,
   9.769  				43DB81331E2A56BE00A20902 /* AppendMailsOperation.swift in Sources */,
   9.770  				8B69E3991E30F80E0022959E /* Appearance.swift in Sources */,
   9.771 +				B7DB7FD6221AD3BB003968DA /* UITextField+Extension.swift in Sources */,
   9.772  				1544BCFE215246F30075C5A0 /* AttachmentFilter.swift in Sources */,
   9.773 -				43F848491EAA09AE00DBE460 /* Weak.swift in Sources */,
   9.774  				B716056020D3ECC900A733D6 /* MoveToFolderTableViewController.swift in Sources */,
   9.775 -				4341980520AB037E0062F7F6 /* CGImageSource+Extension.swift in Sources */,
   9.776  				43D755FC1F26382B006F933A /* EmailConnectInfo+Extension.swift in Sources */,
   9.777  				15874BCB2127493E00A3A4A6 /* AccountVerificationResultDelegate.swift in Sources */,
   9.778  				4381D0FF1E51A124002743C3 /* NetworkServiceWorker.swift in Sources */,
   9.779 @@ -3386,7 +3312,7 @@
   9.780  				432DA7461EE027EB00B30BAA /* MessageSyncService.swift in Sources */,
   9.781  				43A26FBA1E0408FB00AF0B84 /* ServiceErrorProtocol.swift in Sources */,
   9.782  				15874BC52127493E00A3A4A6 /* SettingsSectionViewModel.swift in Sources */,
   9.783 -				43C3220C1EA915C6005073FB /* CGRect+Util.swift in Sources */,
   9.784 +				B70A3A63220065F600EDCE61 /* String+pEp.swift in Sources */,
   9.785  				15874BC12127493E00A3A4A6 /* SettingSwitchTableViewCell.swift in Sources */,
   9.786  				152A39E721905C3E00D9F8E4 /* RecipientTextViewModel.swift in Sources */,
   9.787  				43FE802E209992B800E97AB3 /* QualifyServerIsLocalService.swift in Sources */,
   9.788 @@ -3416,28 +3342,24 @@
   9.789  				B78CF8251E76D706008C1739 /* FilterTableViewController.swift in Sources */,
   9.790  				F7C16A5B21A56DBA004B44F2 /* FetchImapFoldersService.swift in Sources */,
   9.791  				222B35581DF96389007A1F82 /* Capability.swift in Sources */,
   9.792 -				4362398C1EADD61B00BD2EB9 /* CGSize+Extension.swift in Sources */,
   9.793  				43CE63D11DE8866C00FAC505 /* Message+pEp.swift in Sources */,
   9.794  				15874BC82127493E00A3A4A6 /* ThreadedSettingViewModel.swift in Sources */,
   9.795  				0033C07F20D7EBD500224E61 /* ThreadedEmailViewModel+UpdateThreadDelegate.swift in Sources */,
   9.796  				43BB86941DB4E76D00980267 /* CdAccount+Extension.swift in Sources */,
   9.797  				15175CEC205929FB00A8D9D0 /* CidHandler.swift in Sources */,
   9.798  				15F0F7AA21358B33002BE853 /* CdMessagePredicateFactory+Imap.swift in Sources */,
   9.799 -				435B42411D211E5900119048 /* MiscUtil.swift in Sources */,
   9.800  				43B2660D1D252C93009D57E8 /* ConcurrentBaseOperation.swift in Sources */,
   9.801  				152A39CB21905C3E00D9F8E4 /* DocumentAttachmentPickerViewModel.swift in Sources */,
   9.802  				436239931EAE08F400BD2EB9 /* PEPSession+Extensions.swift in Sources */,
   9.803  				4382E6431CC600FF00AA27EA /* PersistentImapFolder.swift in Sources */,
   9.804  				43AAC22B1F7A5AEE00F435F4 /* BaseViewController.swift in Sources */,
   9.805  				43B7154D1CECAADA0027861A /* ViewWidthsAligner.swift in Sources */,
   9.806 -				4362399C1EAE0CE800BD2EB9 /* NSRegularExpression+Extension.swift in Sources */,
   9.807  				43C322091EA90192005073FB /* PEP+UI.swift in Sources */,
   9.808  				004A8C552112FDD500203143 /* EmailListView+UITableViewDataSourcePrefetching.swift in Sources */,
   9.809  				1587D1632049BE7D002C2157 /* ImapConnectionDataCache.swift in Sources */,
   9.810  				002375D620DD185100663961 /* TreadedEmailViewModel+DisplayedMessage.swift in Sources */,
   9.811  				431D60DD1E93D580001266D7 /* MessageAttachmentsCell.swift in Sources */,
   9.812  				00AEB2F620DBA7DA00DA185A /* NeedsRefreshDelegate.swift in Sources */,
   9.813 -				8B81BB901E03F73100D38C82 /* SegueHandlerType.swift in Sources */,
   9.814  				15A75CE1202B57BF00C0DA28 /* Folder+VirtualMailbox.swift in Sources */,
   9.815  				43122B1A1DF5B48B00610253 /* ImapService.swift in Sources */,
   9.816  				1526597821623637006A78DF /* SuggestTableViewController.swift in Sources */,
   9.817 @@ -3445,7 +3367,6 @@
   9.818  				1554755F2137F6F8005A52D0 /* SwipeActionDescriptor.swift in Sources */,
   9.819  				43A6E04B1E5726C8005BEE69 /* ReevaluateMessageRatingOperation.swift in Sources */,
   9.820  				15B220521FC2DAE200CA52BA /* InfoPlist+pEpStrings.swift in Sources */,
   9.821 -				15C5F2461F823752007DE086 /* SortedSet.swift in Sources */,
   9.822  				431E2B071F02550C000035FA /* CheckOutgoingMessagesOperation.swift in Sources */,
   9.823  				496355B120ECEA2900AA4387 /* ThreadedEmailViewModel+EmailDisplayDelegate.swift in Sources */,
   9.824  				43D070332133DC500013B120 /* DefaultAppSettings.swift in Sources */,
   9.825 @@ -3455,15 +3376,13 @@
   9.826  				15BBBC6C1FD05F4300B9DCC8 /* DisplayUserError.swift in Sources */,
   9.827  				43A469FA21513B10002E1036 /* PEPSwipeTableViewCell.swift in Sources */,
   9.828  				00BEC89720B85FD300A36E60 /* NoMessagesViewController.swift in Sources */,
   9.829 -				B761A80A20F5F0A6000832C2 /* UIBarButtonItem+Extension.swift in Sources */,
   9.830  				43F84CD21CD899760092FCAE /* SyncFoldersFromServerOperation.swift in Sources */,
   9.831  				431C6E041FE7A85200E23BE0 /* OAuth2ConfigurationProtocol.swift in Sources */,
   9.832  				1541D7ED1FC81D4200D52A5D /* URL+Extensions.swift in Sources */,
   9.833  				152A39D421905C3E00D9F8E4 /* SubjectCell.swift in Sources */,
   9.834 -				43C322071EA8E7AD005073FB /* UIButton+Extension.swift in Sources */,
   9.835 -				4362399D1EAE0CE800BD2EB9 /* OperationQueue+Extension.swift in Sources */,
   9.836  				15F835241F34BE1300FCE887 /* AccountUserInput.swift in Sources */,
   9.837  				43122B191DF5B48B00610253 /* EmailService.swift in Sources */,
   9.838 +				B7DB7FD2221AD332003968DA /* SegueHandlerType.swift in Sources */,
   9.839  				0033C08320D7F41600224E61 /* ThreadedEmailViewModelDelegate.swift in Sources */,
   9.840  				43498CDD200D0790006DC947 /* LoginViewModelOAuth2ErrorDelegate.swift in Sources */,
   9.841  				152A39DF21905C3E00D9F8E4 /* WrappedBccViewModel.swift in Sources */,
   9.842 @@ -3477,16 +3396,15 @@
   9.843  				15D4399C216E698E00EB3933 /* AccountPickerViewModel.swift in Sources */,
   9.844  				43985D0E204438480080FA9A /* AccountSettingsProtocol+Extension.swift in Sources */,
   9.845  				43D755EB1F25D234006F933A /* MatchUidToMsnOperation.swift in Sources */,
   9.846 +				B7DB7FCA2215D69C003968DA /* CredentialTextField.swift in Sources */,
   9.847  				005A21FB20CAA5F50082D19F /* ThreadedEmailViewModel.swift in Sources */,
   9.848  				15874BD12127493E00A3A4A6 /* TrustedServerSettingsViewModel.swift in Sources */,
   9.849  				436C23281E02948400071430 /* BackgroundTaskProtocol.swift in Sources */,
   9.850  				4351C2DC1F4441190053381F /* xml.c in Sources */,
   9.851  				430E0BE71EAF5E2600378EC2 /* NSMutableDictionary+pEp.swift in Sources */,
   9.852  				152A39D921905C3E00D9F8E4 /* NSAttributedString+BodyTextUtils.swift in Sources */,
   9.853 -				436239951EAE08F400BD2EB9 /* String+pEp.swift in Sources */,
   9.854  				152A39E421905C3E00D9F8E4 /* NSAttributedString+RecipientTextUtils.swift in Sources */,
   9.855  				155050F81FEAB57F009CEAD2 /* BackgroundError.swift in Sources */,
   9.856 -				43E88BE01EFA667600E0B224 /* AsyncStateMachine.swift in Sources */,
   9.857  				159F4C9C21BEB9ED00244903 /* Message+FakeMessage.swift in Sources */,
   9.858  				00EB89AD20E3D3C200CDFA0D /* ThreadedEmailViewModel+MoveToFolderDelegate.swift in Sources */,
   9.859  				431B04801DE5774800E40CD3 /* CdMessage+Pantomime.swift in Sources */,
   9.860 @@ -3500,7 +3418,6 @@
   9.861  				150B84C420A44DE100D8B288 /* MoveToFolderOperation.swift in Sources */,
   9.862  				15874BC72127493E00A3A4A6 /* SettingDefaultAccountTableViewController.swift in Sources */,
   9.863  				4388A0E22008F813008CB98D /* OAuth2AccessToken.swift in Sources */,
   9.864 -				43C3220D1EA915C6005073FB /* UIColor+Extension.swift in Sources */,
   9.865  				152A39D021905C3E00D9F8E4 /* AttachmentCell.swift in Sources */,
   9.866  				0033C08120D7F3C600224E61 /* ThreadViewController+ViewModelDelegate.swift in Sources */,
   9.867  				4351C2DB1F4441190053381F /* utf8.c in Sources */,
   9.868 @@ -3512,14 +3429,14 @@
   9.869  				4351C2D01F4441190053381F /* houdini_html_e.c in Sources */,
   9.870  				15D7D992219B154000A1A2B9 /* Attachment+Extensions.swift in Sources */,
   9.871  				15A75CEC202DED2300C0DA28 /* GmailSpecificInformation.swift in Sources */,
   9.872 -				43FAA0D21EC9972B005BFC4B /* Tuple.swift in Sources */,
   9.873  				430A2EEC1E81357A00878837 /* CdImapFlags+Pantomime.swift in Sources */,
   9.874 -				4395CDEC20AAB2E9003FC5F1 /* UIImage+GIF.swift in Sources */,
   9.875  				15874BCC2127493E00A3A4A6 /* AccountSettingsViewModel.swift in Sources */,
   9.876  				436C232F1E02A52D00071430 /* LimitedOperationQueue.swift in Sources */,
   9.877  				434F40941EB0B173002FBF0D /* ObservableValue.swift in Sources */,
   9.878 +				B7DB7FC42215C4FF003968DA /* UINavigationController+Extensions.swift in Sources */,
   9.879  				15F0F7AD213594FC002BE853 /* Folder+Imap.swift in Sources */,
   9.880  				430D73651E9CBD4E00EA6FA9 /* AttachmentsViewOperation.swift in Sources */,
   9.881 +				B7DB7FC82215C57F003968DA /* UIView+Util.swift in Sources */,
   9.882  				495F607C20B564CD00F47BD6 /* EmailViewController+SizeClasses.swift in Sources */,
   9.883  				43313DFC1DEC7F6000C111C8 /* DeleteFoldersOperation.swift in Sources */,
   9.884  				152A39CC21905C3E00D9F8E4 /* MediaAttachmentPickerProvider.swift in Sources */,
   9.885 @@ -3534,7 +3451,7 @@
   9.886  				1500199D1F2B2C73003E670A /* Notification+CWServiceClientNotificationParsing.swift in Sources */,
   9.887  				496C0EE720BC2A880009B5B9 /* EmailDisplayDelegate.swift in Sources */,
   9.888  				152A39DD21905C3E00D9F8E4 /* AccountCell.swift in Sources */,
   9.889 -				1579397B1F4E00AF00A2A6CF /* UINavigationController+Extensions.swift in Sources */,
   9.890 +				B7DB7FDC221ADDBD003968DA /* UIImageView+Extension.swift in Sources */,
   9.891  				43306EC21FE129840045DD00 /* OAuth2Type.swift in Sources */,
   9.892  				43CE63CB1DE8830100FAC505 /* CdAccount+pEp.swift in Sources */,
   9.893  				438052871FE3E1B100ACF729 /* OAuth2AuthorizationFactoryProtocol.swift in Sources */,
   9.894 @@ -3544,9 +3461,7 @@
   9.895  				15255B031F825CD100A2CFC9 /* IdentityImageTool.swift in Sources */,
   9.896  				43BBB5E71E267A3800104070 /* EncryptAndSendOperation.swift in Sources */,
   9.897  				004A8C5B211316E100203143 /* SelfReferencingOperation.swift in Sources */,
   9.898 -				43AA82531E9B925C00ABD5A8 /* UIView+Util.swift in Sources */,
   9.899  				152A39D121905C3E00D9F8E4 /* AttachmentViewModel.swift in Sources */,
   9.900 -				150DF6D32052ED4800A9DCF7 /* UIView+Autolayout.swift in Sources */,
   9.901  				15547568213931BC005A52D0 /* Folder+Threading.swift in Sources */,
   9.902  				4330278E1F7BABFF00D685F8 /* GradientView.swift in Sources */,
   9.903  				4315E4BF2011FD6900F68763 /* AuthMethod.swift in Sources */,
   9.904 @@ -3580,8 +3495,6 @@
   9.905  				15BA536C20A08D270090F126 /* UnifiedInbox.swift in Sources */,
   9.906  				152A39C521905C3E00D9F8E4 /* ComposeTableViewController.swift in Sources */,
   9.907  				150B8E991FCDACBB00374438 /* AccountSettingsUserInputError.swift in Sources */,
   9.908 -				4337E52A21B68FCA00826CAB /* Thread+Extension.swift in Sources */,
   9.909 -				43EC75A4216498AD00048CFE /* Log+ASL.swift in Sources */,
   9.910  				4351C2DE1F4457620053381F /* NSString+Markdown.m in Sources */,
   9.911  				43306EBE1FE125B50045DD00 /* OAuth2Authorization.swift in Sources */,
   9.912  				43980EFA1CBD415700A7FC3C /* AppConfig.swift in Sources */,
   9.913 @@ -3589,7 +3502,6 @@
   9.914  				1574D07A211464CC00FEDC93 /* URL+MailTo.swift in Sources */,
   9.915  				1574D09B21186A1D00FEDC93 /* AddToContactsViewController.swift in Sources */,
   9.916  				15FE1F761FE122D900CC2D97 /* CreditsViewController.swift in Sources */,
   9.917 -				B7365CDE1EAF45F30036ECC7 /* UITextField+Extension.swift in Sources */,
   9.918  				152A39942190587200D9F8E4 /* TextViewInTableViewScrollUtil.swift in Sources */,
   9.919  				154F0A802085FC7D00C77D72 /* CdAttachment+Pantomime.swift in Sources */,
   9.920  				43F9D99A1E92725700F78A1C /* AttachmentsViewHelper.swift in Sources */,
   9.921 @@ -3604,17 +3516,16 @@
   9.922  				492EF92A20C18C6C004EAE14 /* DisplayedMessage.swift in Sources */,
   9.923  				37A3D6222214338300E11415 /* NetworkReachabilityProtocol.swift in Sources */,
   9.924  				15AA6016207CD71D00D57DB4 /* ImapFlags+Pantomime.swift in Sources */,
   9.925 +				B70A3A9322089D5000EDCE61 /* Log+ASL.swift in Sources */,
   9.926  				49228A5520D4035100A51E9D /* DetailCellSegue.swift in Sources */,
   9.927  				43497B38211C62DE00AC42B0 /* MessageIdentitfying.swift in Sources */,
   9.928  				4307C4701ED81F3100A276A4 /* DefaultImapSyncDelegate.swift in Sources */,
   9.929 -				43C273DB21C8F96D002EB4C8 /* Logger.swift in Sources */,
   9.930  				00FD0CE82102014C00BA0C56 /* PrimarySplitViewcontroller+ScreenComposerProtocol.swift in Sources */,
   9.931  				434E5A1B20DB9C4600D7F88A /* EmailListViewModel+MessageFolderDelegate.swift in Sources */,
   9.932  				431E58F61ED57F6500EFA77F /* AccountVerificationServiceProtocol.swift in Sources */,
   9.933  				37FE82E92211D290008F8CF4 /* ReachabilityUtils.swift in Sources */,
   9.934  				152A39E821905C3E00D9F8E4 /* RecipientCellViewModel.swift in Sources */,
   9.935  				43A26FBF1E041BF200AF0B84 /* ImapSyncOperation.swift in Sources */,
   9.936 -				43826F87212FF91D00BF1F7B /* Substring+Email.swift in Sources */,
   9.937  				152A39CE21905C3E00D9F8E4 /* ComposeHelpers.swift in Sources */,
   9.938  				43EC03481F4AE28F0026E152 /* String+Attachment.swift in Sources */,
   9.939  				15BBBC631FD0496800B9DCC8 /* ReportingErrorContainer.swift in Sources */,
   9.940 @@ -3626,9 +3537,7 @@
   9.941  				152A39C821905C3E00D9F8E4 /* ComposeViewModel+InitData.swift in Sources */,
   9.942  				0038494C20D2587F008000EA /* PepPictureComposer.swift in Sources */,
   9.943  				4356FFE721354A4B00804089 /* ReplyAllPossibleCheckerProtocol.swift in Sources */,
   9.944 -				43980EE01CBD24B000A7FC3C /* Log.swift in Sources */,
   9.945  				228038681DC9DE6D00F1CB45 /* TextfieldResponder.swift in Sources */,
   9.946 -				157455C81FDFD2D4008CA78F /* NSAttributedString+Extensions.swift in Sources */,
   9.947  				4360282D1ED6F27600C95FC4 /* NetworkError.swift in Sources */,
   9.948  				433C51D31E66CCA900272E19 /* CreateRequiredFoldersOperation.swift in Sources */,
   9.949  				4323FE861E83D6FF006785E1 /* ImapFolderBuilder.swift in Sources */,
   9.950 @@ -3643,7 +3552,6 @@
   9.951  				00FD0CE62101F7D700BA0C56 /* ScreenComposerProtocol.swift in Sources */,
   9.952  				4351C2D81F4441190053381F /* references.c in Sources */,
   9.953  				152A39DC21905C3E00D9F8E4 /* TextViewContainingTableViewCell.swift in Sources */,
   9.954 -				432645811F4C26CF002E3EF8 /* NSAttributedString+Parsing.swift in Sources */,
   9.955  				000D3C2F20D12BFD006B11B2 /* MessageViewModel.swift in Sources */,
   9.956  				4351C2CB1F4441190053381F /* cmark.c in Sources */,
   9.957  				432A5E261EB344C3007CB670 /* PEP_color+Extension.swift in Sources */,
   9.958 @@ -3655,11 +3563,12 @@
   9.959  				001D366220C576BD002434EB /* EmailViewController+MoveToFolderDelegate.swift in Sources */,
   9.960  				433BCD951D5388C100DD98EF /* ReplyUtil.swift in Sources */,
   9.961  				4351C2DA1F4441190053381F /* scanners.c in Sources */,
   9.962 +				B7DB7FD7221AD3BB003968DA /* UIButton+Extension.swift in Sources */,
   9.963  				4351C2D91F4441190053381F /* render.c in Sources */,
   9.964  				B722EC4D1E5B01B300A2B9D5 /* FolderCellViewModel.swift in Sources */,
   9.965 -				43E88BDE1EFA665600E0B224 /* AsyncStateMachineProtocol.swift in Sources */,
   9.966  				15874BCF2127493E00A3A4A6 /* AccountSettingsTableViewController.swift in Sources */,
   9.967  				43122B3E1DF5BB6600610253 /* MySelfOperation.swift in Sources */,
   9.968 +				B7DB7FC72215C57F003968DA /* UIView+Autolayout.swift in Sources */,
   9.969  				15547572213FEC4B005A52D0 /* CdMessagePredicateFactory+Extension.swift in Sources */,
   9.970  				B71EBBBC1E55E4AE00150177 /* FolderTableViewController.swift in Sources */,
   9.971  				492EF92F20C699D0004EAE14 /* ThreadViewController+TableView.swift in Sources */,
   9.972 @@ -3714,7 +3623,6 @@
   9.973  				1541D7F01FC81ED900D52A5D /* URL+ExtensionsTest.swift in Sources */,
   9.974  				00262056217DCCB200DDAFB5 /* TrustedServerSettingsViewModelTest.swift in Sources */,
   9.975  				15BA536E20A095410090F126 /* UnifiedInboxTest.swift in Sources */,
   9.976 -				15BA537020A0A4350090F126 /* Log.swift in Sources */,
   9.977  				15D7D990219AD38B00A1A2B9 /* MediaAttachmentPickerProviderViewModelTest.swift in Sources */,
   9.978  				15410D222199D83200BBF65F /* AccountCellViewModelTest.swift in Sources */,
   9.979  				15BBBC6B1FD0527200B9DCC8 /* DisplayUserErrorTest.swift in Sources */,
   9.980 @@ -3765,7 +3673,6 @@
   9.981  				37FE82ED22132B23008F8CF4 /* ReachabilityUtilsTests.swift in Sources */,
   9.982  				430C80E01D0EADC200CD4582 /* PepAdapterTests.swift in Sources */,
   9.983  				00DF2C3B2164C53F004EBA6C /* FolderViewModelTest.swift in Sources */,
   9.984 -				43D86EB821BE62DD00C18418 /* Log+ASL.swift in Sources */,
   9.985  				5DEBAA481DE59C3B00FAE12C /* NetworkServiceTests.swift in Sources */,
   9.986  				157C05482180756300E530DE /* DocumentAttachmentPickerViewModelTest.swift in Sources */,
   9.987  				49DCCD2521E8ABA900ABE487 /* SecurePDFScreenshotTest.swift in Sources */,
   9.988 @@ -3773,7 +3680,6 @@
   9.989  				43FE8030209995AD00E97AB3 /* QualifyServerIsLocalServiceTest.swift in Sources */,
   9.990  				15D439A7216FB77600EB3933 /* UnitTestUtils.swift in Sources */,
   9.991  				15410D252199ECD700BBF65F /* AttachmentViewModelTest.swift in Sources */,
   9.992 -				1508AEAA1F862C85001D5230 /* SortedSetTest.swift in Sources */,
   9.993  				152B665C21E508F500FB925F /* Message+FakeMessageTest.swift in Sources */,
   9.994  				43257C861F50659200DDC7F0 /* StringHTMLExtensionTests.swift in Sources */,
   9.995  				43A0B2CF214006FC00FB779D /* ReplyUtilTests.swift in Sources */,
   9.996 @@ -3790,7 +3696,7 @@
   9.997  				434C051B20F8BAB6009B271D /* XCUIElement+Extension.swift in Sources */,
   9.998  				431E65631EEAE65200B8BBFC /* HandshakeUITest.swift in Sources */,
   9.999  				43B0443B20067D25007BCE3F /* UITestDataProtocol.swift in Sources */,
  9.1000 -				008335A1210F28C7006E9306 /* SecretUITestData.swift in Sources */,
  9.1001 +				B7745839221C191600664282 /* SecretUITestData.swift in Sources */,
  9.1002  			);
  9.1003  			runOnlyForDeploymentPostprocessing = 0;
  9.1004  		};
  9.1005 @@ -3958,7 +3864,7 @@
  9.1006  					"$(SRCROOT)/../pEpEngine/src",
  9.1007  					"$(SRCROOT)/pEpForiOS/Markdown/include",
  9.1008  				);
  9.1009 -				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
  9.1010 +				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
  9.1011  				MTL_ENABLE_DEBUG_INFO = YES;
  9.1012  				ONLY_ACTIVE_ARCH = YES;
  9.1013  				OTHER_LDFLAGS = "-ObjC";
  9.1014 @@ -4022,7 +3928,7 @@
  9.1015  					"$(SRCROOT)/../pEpEngine/src",
  9.1016  					"$(SRCROOT)/pEpForiOS/Markdown/include",
  9.1017  				);
  9.1018 -				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
  9.1019 +				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
  9.1020  				MTL_ENABLE_DEBUG_INFO = NO;
  9.1021  				OTHER_LDFLAGS = "-ObjC";
  9.1022  				OTHER_SWIFT_FLAGS = "";
  9.1023 @@ -4058,7 +3964,7 @@
  9.1024  					"$(SRCROOT)/../AppAuth-iOS/Source/iOS",
  9.1025  				);
  9.1026  				INFOPLIST_FILE = pEpForiOS/Info.plist;
  9.1027 -				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
  9.1028 +				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
  9.1029  				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
  9.1030  				ONLY_ACTIVE_ARCH = "$(inherited)";
  9.1031  				OTHER_SWIFT_FLAGS = "-DDEBUG_LOGGING -D DEBUG $(inherited)";
  9.1032 @@ -4099,7 +4005,7 @@
  9.1033  					"$(SRCROOT)/../AppAuth-iOS/Source/iOS",
  9.1034  				);
  9.1035  				INFOPLIST_FILE = pEpForiOS/Info.plist;
  9.1036 -				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
  9.1037 +				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
  9.1038  				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
  9.1039  				ONLY_ACTIVE_ARCH = "$(inherited)";
  9.1040  				PRODUCT_BUNDLE_IDENTIFIER = security.pEp;
    10.1 --- a/pEpForiOS.xcodeproj/xcshareddata/xcschemes/pEp.xcscheme	Wed Feb 20 11:00:07 2019 +0100
    10.2 +++ b/pEpForiOS.xcodeproj/xcshareddata/xcschemes/pEp.xcscheme	Mon Mar 18 10:54:14 2019 +0100
    10.3 @@ -28,20 +28,6 @@
    10.4              buildForAnalyzing = "YES">
    10.5              <BuildableReference
    10.6                 BuildableIdentifier = "primary"
    10.7 -               BlueprintIdentifier = "43980E5A1CBD1B3E00A7FC3C"
    10.8 -               BuildableName = "libPantomimeStatic.a"
    10.9 -               BlueprintName = "PantomimeStatic"
   10.10 -               ReferencedContainer = "container:../pantomime-iOS/Pantomime.xcodeproj">
   10.11 -            </BuildableReference>
   10.12 -         </BuildActionEntry>
   10.13 -         <BuildActionEntry
   10.14 -            buildForTesting = "YES"
   10.15 -            buildForRunning = "YES"
   10.16 -            buildForProfiling = "YES"
   10.17 -            buildForArchiving = "YES"
   10.18 -            buildForAnalyzing = "YES">
   10.19 -            <BuildableReference
   10.20 -               BuildableIdentifier = "primary"
   10.21                 BlueprintIdentifier = "343AAA531E83463400F9D36E"
   10.22                 BuildableName = "AppAuth.framework"
   10.23                 BlueprintName = "AppAuth_iOS"
   10.24 @@ -84,6 +70,48 @@
   10.25              buildForAnalyzing = "YES">
   10.26              <BuildableReference
   10.27                 BuildableIdentifier = "primary"
   10.28 +               BlueprintIdentifier = "B7911EB321F7358500D7F66F"
   10.29 +               BuildableName = "pEpIOSToolbox.framework"
   10.30 +               BlueprintName = "pEpIOSToolbox"
   10.31 +               ReferencedContainer = "container:subModules/pEpIOSToolbox/pEpIOSToolbox.xcodeproj">
   10.32 +            </BuildableReference>
   10.33 +         </BuildActionEntry>
   10.34 +         <BuildActionEntry
   10.35 +            buildForTesting = "YES"
   10.36 +            buildForRunning = "YES"
   10.37 +            buildForProfiling = "YES"
   10.38 +            buildForArchiving = "YES"
   10.39 +            buildForAnalyzing = "YES">
   10.40 +            <BuildableReference
   10.41 +               BuildableIdentifier = "primary"
   10.42 +               BlueprintIdentifier = "43FBB7621FC6D9630057A3BD"
   10.43 +               BuildableName = "ldns_xcode.framework"
   10.44 +               BlueprintName = "ldns-xcode"
   10.45 +               ReferencedContainer = "container:../ldns/xcode/ldns-xcode/ldns-xcode.xcodeproj">
   10.46 +            </BuildableReference>
   10.47 +         </BuildActionEntry>
   10.48 +         <BuildActionEntry
   10.49 +            buildForTesting = "YES"
   10.50 +            buildForRunning = "YES"
   10.51 +            buildForProfiling = "YES"
   10.52 +            buildForArchiving = "YES"
   10.53 +            buildForAnalyzing = "YES">
   10.54 +            <BuildableReference
   10.55 +               BuildableIdentifier = "primary"
   10.56 +               BlueprintIdentifier = "43980E5A1CBD1B3E00A7FC3C"
   10.57 +               BuildableName = "libPantomimeStatic.a"
   10.58 +               BlueprintName = "PantomimeStatic"
   10.59 +               ReferencedContainer = "container:../pantomime-iOS/Pantomime.xcodeproj">
   10.60 +            </BuildableReference>
   10.61 +         </BuildActionEntry>
   10.62 +         <BuildActionEntry
   10.63 +            buildForTesting = "YES"
   10.64 +            buildForRunning = "YES"
   10.65 +            buildForProfiling = "YES"
   10.66 +            buildForArchiving = "YES"
   10.67 +            buildForAnalyzing = "YES">
   10.68 +            <BuildableReference
   10.69 +               BuildableIdentifier = "primary"
   10.70                 BlueprintIdentifier = "352988A91AEF964100FA7E2E"
   10.71                 BuildableName = "libpEpObjCAdapter.a"
   10.72                 BlueprintName = "pEpObjCAdapter"
   10.73 @@ -118,20 +146,6 @@
   10.74                 ReferencedContainer = "container:../libAccountSettings/xcode/AccountSettingsAdapter/AccountSettingsAdapter.xcodeproj">
   10.75              </BuildableReference>
   10.76           </BuildActionEntry>
   10.77 -         <BuildActionEntry
   10.78 -            buildForTesting = "YES"
   10.79 -            buildForRunning = "YES"
   10.80 -            buildForProfiling = "YES"
   10.81 -            buildForArchiving = "YES"
   10.82 -            buildForAnalyzing = "YES">
   10.83 -            <BuildableReference
   10.84 -               BuildableIdentifier = "primary"
   10.85 -               BlueprintIdentifier = "43FBB7621FC6D9630057A3BD"
   10.86 -               BuildableName = "ldns_xcode.framework"
   10.87 -               BlueprintName = "ldns-xcode"
   10.88 -               ReferencedContainer = "container:../ldns/xcode/ldns-xcode/ldns-xcode.xcodeproj">
   10.89 -            </BuildableReference>
   10.90 -         </BuildActionEntry>
   10.91        </BuildActionEntries>
   10.92     </BuildAction>
   10.93     <TestAction
   10.94 @@ -170,26 +184,6 @@
   10.95                 BlueprintIdentifier = "43CB608A1DA4EB4E0015281E"
   10.96                 BuildableName = "MessageModelTests.xctest"
   10.97                 BlueprintName = "MessageModelTests"
   10.98 -               ReferencedContainer = "container:../MailModel/MessageModel/MessageModel.xcodeproj">
   10.99 -            </BuildableReference>
  10.100 -         </TestableReference>
  10.101 -         <TestableReference
  10.102 -            skipped = "NO">
  10.103 -            <BuildableReference
  10.104 -               BuildableIdentifier = "primary"
  10.105 -               BlueprintIdentifier = "64415E161BE94FCB00F6CBB2"
  10.106 -               BuildableName = "iOSTests.xctest"
  10.107 -               BlueprintName = "iOSTests"
  10.108 -               ReferencedContainer = "container:../pEpiOSAdapter/pEpiOSAdapter.xcodeproj">
  10.109 -            </BuildableReference>
  10.110 -         </TestableReference>
  10.111 -         <TestableReference
  10.112 -            skipped = "NO">
  10.113 -            <BuildableReference
  10.114 -               BuildableIdentifier = "primary"
  10.115 -               BlueprintIdentifier = "43CB608A1DA4EB4E0015281E"
  10.116 -               BuildableName = "MessageModelTests.xctest"
  10.117 -               BlueprintName = "MessageModelTests"
  10.118                 ReferencedContainer = "container:../MessageModel/MessageModel/MessageModel.xcodeproj">
  10.119              </BuildableReference>
  10.120           </TestableReference>
  10.121 @@ -217,10 +211,10 @@
  10.122              skipped = "NO">
  10.123              <BuildableReference
  10.124                 BuildableIdentifier = "primary"
  10.125 -               BlueprintIdentifier = "43980E441CBD0BCA00A7FC3C"
  10.126 -               BuildableName = "pEpForiOSUITests.xctest"
  10.127 -               BlueprintName = "pEpForiOSUITests"
  10.128 -               ReferencedContainer = "container:pEpForiOS.xcodeproj">
  10.129 +               BlueprintIdentifier = "B7DB7F56221315BD003968DA"
  10.130 +               BuildableName = "pEpIOSToolboxTests.xctest"
  10.131 +               BlueprintName = "pEpIOSToolboxTests"
  10.132 +               ReferencedContainer = "container:subModules/pEpIOSToolbox/pEpIOSToolbox.xcodeproj">
  10.133              </BuildableReference>
  10.134           </TestableReference>
  10.135        </Testables>
    11.1 --- a/pEpForiOS.xcworkspace/contents.xcworkspacedata	Wed Feb 20 11:00:07 2019 +0100
    11.2 +++ b/pEpForiOS.xcworkspace/contents.xcworkspacedata	Mon Mar 18 10:54:14 2019 +0100
    11.3 @@ -8,6 +8,9 @@
    11.4        location = "container:../MessageModel/MessageModel/MessageModel.xcodeproj">
    11.5     </FileRef>
    11.6     <FileRef
    11.7 +      location = "group:subModules/pEpIOSToolbox/pEpIOSToolbox.xcodeproj">
    11.8 +   </FileRef>
    11.9 +   <FileRef
   11.10        location = "container:../pEpObjCAdapter/pEpObjCAdapter.xcodeproj">
   11.11     </FileRef>
   11.12     <FileRef
    12.1 --- a/pEpForiOS/AppDelegate.swift	Wed Feb 20 11:00:07 2019 +0100
    12.2 +++ b/pEpForiOS/AppDelegate.swift	Mon Mar 18 10:54:14 2019 +0100
    12.3 @@ -7,7 +7,7 @@
    12.4  //
    12.5  
    12.6  import CoreData
    12.7 -
    12.8 +import pEpIOSToolbox
    12.9  import MessageModel
   12.10  
   12.11  @UIApplicationMain
    13.1 --- a/pEpForiOS/Background/AppendMailsOperation.swift	Wed Feb 20 11:00:07 2019 +0100
    13.2 +++ b/pEpForiOS/Background/AppendMailsOperation.swift	Mon Mar 18 10:54:14 2019 +0100
    13.3 @@ -8,7 +8,7 @@
    13.4  
    13.5  import UIKit
    13.6  import CoreData
    13.7 -
    13.8 +import pEpIOSToolbox
    13.9  import MessageModel
   13.10  
   13.11  /// Operation for storing mails in any type of IMAP folder.
    14.1 --- a/pEpForiOS/Background/BaseOperation.swift	Wed Feb 20 11:00:07 2019 +0100
    14.2 +++ b/pEpForiOS/Background/BaseOperation.swift	Mon Mar 18 10:54:14 2019 +0100
    14.3 @@ -6,6 +6,8 @@
    14.4  //  Copyright © 2016 p≡p Security S.A. All rights reserved.
    14.5  //
    14.6  
    14.7 +import pEpIOSToolbox
    14.8 +
    14.9  /**
   14.10   Basic NSOperation that can gather errors.
   14.11   */
    15.1 --- a/pEpForiOS/Background/ConcurrentBaseOperation.swift	Wed Feb 20 11:00:07 2019 +0100
    15.2 +++ b/pEpForiOS/Background/ConcurrentBaseOperation.swift	Mon Mar 18 10:54:14 2019 +0100
    15.3 @@ -7,7 +7,7 @@
    15.4  //
    15.5  
    15.6  import CoreData
    15.7 -
    15.8 +import pEpIOSToolbox
    15.9  import MessageModel
   15.10  
   15.11  /// This is the base for concurrent `NSOperation`s, that is operations that handle asynchronicity
    16.1 --- a/pEpForiOS/Background/CreateRequiredFoldersOperation.swift	Wed Feb 20 11:00:07 2019 +0100
    16.2 +++ b/pEpForiOS/Background/CreateRequiredFoldersOperation.swift	Mon Mar 18 10:54:14 2019 +0100
    16.3 @@ -8,7 +8,7 @@
    16.4  
    16.5  import UIKit
    16.6  import CoreData
    16.7 -
    16.8 +import pEpIOSToolbox
    16.9  import MessageModel
   16.10  
   16.11  /**
    17.1 --- a/pEpForiOS/Background/DecryptMessageOperation.swift	Wed Feb 20 11:00:07 2019 +0100
    17.2 +++ b/pEpForiOS/Background/DecryptMessageOperation.swift	Mon Mar 18 10:54:14 2019 +0100
    17.3 @@ -7,6 +7,7 @@
    17.4  //
    17.5  
    17.6  import Foundation
    17.7 +import pEpIOSToolbox
    17.8  
    17.9  protocol DecryptMessageOperationDelegate: class {
   17.10  
    18.1 --- a/pEpForiOS/Background/DecryptMessagesOperation.swift	Wed Feb 20 11:00:07 2019 +0100
    18.2 +++ b/pEpForiOS/Background/DecryptMessagesOperation.swift	Mon Mar 18 10:54:14 2019 +0100
    18.3 @@ -7,7 +7,7 @@
    18.4  //
    18.5  
    18.6  import MessageModel
    18.7 -
    18.8 +import pEpIOSToolbox
    18.9  import CoreData
   18.10  
   18.11  // Only used in Tests. Maybe refactor out.
   18.12 @@ -233,7 +233,7 @@
   18.13              Logger.backendLogger.errorAndCrash("Error converting CDMesage")
   18.14              return
   18.15          }
   18.16 -        MessageModelConfig.messageFolderDelegate?.didCreate(messageFolder: message)
   18.17 +        MessageModelConfig.messageFolderDelegate?.didCreate(message: message)
   18.18      }
   18.19  
   18.20      // MARK: - Handle DecryptMessageOperationDelegate Calls
    19.1 --- a/pEpForiOS/Background/DeleteFolderOperation.swift	Wed Feb 20 11:00:07 2019 +0100
    19.2 +++ b/pEpForiOS/Background/DeleteFolderOperation.swift	Mon Mar 18 10:54:14 2019 +0100
    19.3 @@ -7,7 +7,7 @@
    19.4  //
    19.5  
    19.6  import CoreData
    19.7 -
    19.8 +import pEpIOSToolbox
    19.9  import MessageModel
   19.10  
   19.11  public class DeleteFolderOperation: ImapSyncOperation {
    20.1 --- a/pEpForiOS/Background/EncryptAndSendOperation.swift	Wed Feb 20 11:00:07 2019 +0100
    20.2 +++ b/pEpForiOS/Background/EncryptAndSendOperation.swift	Mon Mar 18 10:54:14 2019 +0100
    20.3 @@ -7,7 +7,7 @@
    20.4  //
    20.5  
    20.6  import CoreData
    20.7 -
    20.8 +import pEpIOSToolbox
    20.9  import MessageModel
   20.10  
   20.11  /**
   20.12 @@ -118,7 +118,7 @@
   20.13                  return
   20.14          }
   20.15          let rating = message.outgoingMessageRating().rawValue
   20.16 -        MessageModelConfig.messageFolderDelegate?.didDelete(messageFolder: message)
   20.17 +        MessageModelConfig.messageFolderDelegate?.didDelete(message: message)
   20.18          cdMessage.parent = sentFolder
   20.19          cdMessage.imap?.localFlags?.flagSeen = true
   20.20          cdMessage.pEpRating = Int16(rating)
    21.1 --- a/pEpForiOS/Background/FetchNumberOfNewMailsOperation.swift	Wed Feb 20 11:00:07 2019 +0100
    21.2 +++ b/pEpForiOS/Background/FetchNumberOfNewMailsOperation.swift	Mon Mar 18 10:54:14 2019 +0100
    21.3 @@ -8,6 +8,7 @@
    21.4  
    21.5  import CoreData
    21.6  import MessageModel
    21.7 +import pEpIOSToolbox
    21.8  
    21.9  /// Fetches UIDs of  new (to us) messages in a given folder and returns its count.
   21.10  class FetchNumberOfNewMailsOperation: ImapSyncOperation {
    22.1 --- a/pEpForiOS/Background/FixAttachmentsOperation.swift	Wed Feb 20 11:00:07 2019 +0100
    22.2 +++ b/pEpForiOS/Background/FixAttachmentsOperation.swift	Mon Mar 18 10:54:14 2019 +0100
    22.3 @@ -9,7 +9,7 @@
    22.4  import UIKit
    22.5  import CoreData
    22.6  import Photos
    22.7 -
    22.8 +import pEpIOSToolbox
    22.9  import MessageModel
   22.10  
   22.11  /**
    23.1 --- a/pEpForiOS/Background/FolderInfoOperation.swift	Wed Feb 20 11:00:07 2019 +0100
    23.2 +++ b/pEpForiOS/Background/FolderInfoOperation.swift	Mon Mar 18 10:54:14 2019 +0100
    23.3 @@ -8,7 +8,7 @@
    23.4  
    23.5  import Foundation
    23.6  import CoreData
    23.7 -
    23.8 +import pEpIOSToolbox
    23.9  import MessageModel
   23.10  
   23.11  /**
    24.1 --- a/pEpForiOS/Background/ImapFolderBuilder.swift	Wed Feb 20 11:00:07 2019 +0100
    24.2 +++ b/pEpForiOS/Background/ImapFolderBuilder.swift	Mon Mar 18 10:54:14 2019 +0100
    24.3 @@ -7,7 +7,7 @@
    24.4  //
    24.5  
    24.6  import CoreData
    24.7 -
    24.8 +import pEpIOSToolbox
    24.9  import MessageModel
   24.10  
   24.11  open class ImapFolderBuilder: NSObject, CWFolderBuilding {
    25.1 --- a/pEpForiOS/Background/ImapSyncOperation.swift	Wed Feb 20 11:00:07 2019 +0100
    25.2 +++ b/pEpForiOS/Background/ImapSyncOperation.swift	Mon Mar 18 10:54:14 2019 +0100
    25.3 @@ -7,6 +7,7 @@
    25.4  //
    25.5  
    25.6  import MessageModel
    25.7 +import pEpIOSToolbox
    25.8  
    25.9  public class ImapSyncOperation: ConcurrentBaseOperation {
   25.10      let imapSyncData: ImapSyncData
    26.1 --- a/pEpForiOS/Background/MoveToFolderOperation.swift	Wed Feb 20 11:00:07 2019 +0100
    26.2 +++ b/pEpForiOS/Background/MoveToFolderOperation.swift	Mon Mar 18 10:54:14 2019 +0100
    26.3 @@ -7,7 +7,7 @@
    26.4  //
    26.5  
    26.6  import CoreData
    26.7 -
    26.8 +import pEpIOSToolbox
    26.9  import MessageModel
   26.10  
   26.11  /// Moves all messages in the given folder to targetFolder if parent != tagetfolder.
    27.1 --- a/pEpForiOS/Background/MySelfOperation.swift	Wed Feb 20 11:00:07 2019 +0100
    27.2 +++ b/pEpForiOS/Background/MySelfOperation.swift	Mon Mar 18 10:54:14 2019 +0100
    27.3 @@ -8,7 +8,7 @@
    27.4  
    27.5  import UIKit
    27.6  import CoreData
    27.7 -
    27.8 +import pEpIOSToolbox
    27.9  import MessageModel
   27.10  
   27.11  /**
    28.1 --- a/pEpForiOS/Background/PersistentImapFolder.swift	Wed Feb 20 11:00:07 2019 +0100
    28.2 +++ b/pEpForiOS/Background/PersistentImapFolder.swift	Mon Mar 18 10:54:14 2019 +0100
    28.3 @@ -7,7 +7,7 @@
    28.4  //
    28.5  
    28.6  import CoreData
    28.7 -
    28.8 +import pEpIOSToolbox
    28.9  import MessageModel
   28.10  
   28.11  /**
    29.1 --- a/pEpForiOS/Background/StorePrefetchedMailOperation.swift	Wed Feb 20 11:00:07 2019 +0100
    29.2 +++ b/pEpForiOS/Background/StorePrefetchedMailOperation.swift	Mon Mar 18 10:54:14 2019 +0100
    29.3 @@ -7,7 +7,7 @@
    29.4  //
    29.5  
    29.6  import CoreData
    29.7 -
    29.8 +import pEpIOSToolbox
    29.9  import MessageModel
   29.10  
   29.11  /**
    30.1 --- a/pEpForiOS/Background/SyncFlagsToServerOperation.swift	Wed Feb 20 11:00:07 2019 +0100
    30.2 +++ b/pEpForiOS/Background/SyncFlagsToServerOperation.swift	Mon Mar 18 10:54:14 2019 +0100
    30.3 @@ -8,6 +8,7 @@
    30.4  
    30.5  import CoreData
    30.6  import MessageModel
    30.7 +import pEpIOSToolbox
    30.8  
    30.9  protocol SyncFlagsToServerOperationDelegate: class {
   30.10      func flagsUploaded(cdMessage: CdMessage)
    31.1 --- a/pEpForiOS/Background/SyncFoldersFromServerOperation.swift	Wed Feb 20 11:00:07 2019 +0100
    31.2 +++ b/pEpForiOS/Background/SyncFoldersFromServerOperation.swift	Mon Mar 18 10:54:14 2019 +0100
    31.3 @@ -7,7 +7,7 @@
    31.4  //
    31.5  
    31.6  import CoreData
    31.7 -
    31.8 +import pEpIOSToolbox
    31.9  import MessageModel
   31.10  
   31.11  protocol SyncFoldersFromServerOperationDelegate: class {
    32.1 --- a/pEpForiOS/Background/SyncMessagesOperation.swift	Wed Feb 20 11:00:07 2019 +0100
    32.2 +++ b/pEpForiOS/Background/SyncMessagesOperation.swift	Mon Mar 18 10:54:14 2019 +0100
    32.3 @@ -8,7 +8,7 @@
    32.4  
    32.5  import UIKit
    32.6  import CoreData
    32.7 -
    32.8 +import pEpIOSToolbox
    32.9  import MessageModel
   32.10  
   32.11  /**
    33.1 --- a/pEpForiOS/Background/UIDCopyOperation.swift	Wed Feb 20 11:00:07 2019 +0100
    33.2 +++ b/pEpForiOS/Background/UIDCopyOperation.swift	Mon Mar 18 10:54:14 2019 +0100
    33.3 @@ -7,6 +7,7 @@
    33.4  //
    33.5  
    33.6  import MessageModel
    33.7 +import pEpIOSToolbox
    33.8  
    33.9  class UIDCopyOperation: ImapSyncOperation {
   33.10      var syncDelegate: UIDCopyOperationSyncDelegate?
    34.1 --- a/pEpForiOS/Base.lproj/AccountCreation.storyboard	Wed Feb 20 11:00:07 2019 +0100
    34.2 +++ b/pEpForiOS/Base.lproj/AccountCreation.storyboard	Mon Mar 18 10:54:14 2019 +0100
    34.3 @@ -566,7 +566,7 @@
    34.4                                              <view contentMode="scaleToFill" horizontalCompressionResistancePriority="749" verticalCompressionResistancePriority="749" translatesAutoresizingMaskIntoConstraints="NO" id="7IS-Mp-8VB">
    34.5                                                  <rect key="frame" x="243" y="153" width="250" height="152"/>
    34.6                                                  <subviews>
    34.7 -                                                    <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="line" placeholder="Username" textAlignment="center" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="mKi-gF-bu9" customClass="CredentialTextField" customModule="pEpForiOS" customModuleProvider="target">
    34.8 +                                                    <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="line" placeholder="Username" textAlignment="center" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="mKi-gF-bu9" customClass="CredentialTextField" customModule="pEpForiOS">
    34.9                                                          <rect key="frame" x="0.0" y="0.0" width="250" height="28"/>
   34.10                                                          <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
   34.11                                                          <accessibility key="accessibilityConfiguration" identifier="username"/>
   34.12 @@ -591,7 +591,7 @@
   34.13                                                              </userDefinedRuntimeAttribute>
   34.14                                                          </userDefinedRuntimeAttributes>
   34.15                                                      </textField>
   34.16 -                                                    <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="line" placeholder="Email Address" textAlignment="center" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="36s-Iw-b58" customClass="CredentialTextField" customModule="pEpForiOS" customModuleProvider="target">
   34.17 +                                                    <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="line" placeholder="Email Address" textAlignment="center" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="36s-Iw-b58" customClass="CredentialTextField" customModule="pEpForiOS">
   34.18                                                          <rect key="frame" x="0.0" y="62" width="250" height="28"/>
   34.19                                                          <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
   34.20                                                          <accessibility key="accessibilityConfiguration" identifier="email"/>
   34.21 @@ -616,7 +616,7 @@
   34.22                                                              <action selector="emailChanged:" destination="clh-8B-z2B" eventType="editingChanged" id="hsV-YG-JFW"/>
   34.23                                                          </connections>
   34.24                                                      </textField>
   34.25 -                                                    <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="line" placeholder="Password" textAlignment="center" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="3wB-RC-5fz" customClass="CredentialTextField" customModule="pEpForiOS" customModuleProvider="target">
   34.26 +                                                    <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="line" placeholder="Password" textAlignment="center" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="3wB-RC-5fz" customClass="CredentialTextField" customModule="pEpForiOS">
   34.27                                                          <rect key="frame" x="0.0" y="124" width="250" height="28"/>
   34.28                                                          <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
   34.29                                                          <accessibility key="accessibilityConfiguration" identifier="password"/>
    35.1 --- a/pEpForiOS/Base.lproj/Main.storyboard	Wed Feb 20 11:00:07 2019 +0100
    35.2 +++ b/pEpForiOS/Base.lproj/Main.storyboard	Mon Mar 18 10:54:14 2019 +0100
    35.3 @@ -132,7 +132,7 @@
    35.4                                          <constraint firstItem="YqR-ga-Tf9" firstAttribute="centerY" secondItem="jgQ-nZ-h1r" secondAttribute="centerY" id="kzK-1E-vdU"/>
    35.5                                          <constraint firstAttribute="trailing" secondItem="8QD-qP-0hS" secondAttribute="trailing" constant="8" id="n5I-Yb-okr"/>
    35.6                                          <constraint firstItem="BvI-Zi-zU6" firstAttribute="trailing" secondItem="8QD-qP-0hS" secondAttribute="trailing" id="tYc-Ao-foD"/>
    35.7 -                                        <constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="BvI-Zi-zU6" secondAttribute="bottom" constant="5" id="zul-c0-54S"/>
    35.8 +                                        <constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="BvI-Zi-zU6" secondAttribute="bottom" priority="950" constant="5" id="zul-c0-54S"/>
    35.9                                      </constraints>
   35.10                                  </tableViewCellContentView>
   35.11                                  <connections>
    36.1 --- a/pEpForiOS/HTMLParser/Axt/HtmlToMarkdownSaxParser.swift	Wed Feb 20 11:00:07 2019 +0100
    36.2 +++ b/pEpForiOS/HTMLParser/Axt/HtmlToMarkdownSaxParser.swift	Mon Mar 18 10:54:14 2019 +0100
    36.3 @@ -7,7 +7,7 @@
    36.4  //
    36.5  
    36.6  import Foundation
    36.7 -
    36.8 +import pEpIOSToolbox
    36.9  import MessageModel
   36.10  
   36.11  public protocol MarkdownImageDelegate: class {
    37.1 --- a/pEpForiOS/HTMLParser/Axt/HtmlToTextSaxParser.swift	Wed Feb 20 11:00:07 2019 +0100
    37.2 +++ b/pEpForiOS/HTMLParser/Axt/HtmlToTextSaxParser.swift	Mon Mar 18 10:54:14 2019 +0100
    37.3 @@ -7,6 +7,7 @@
    37.4  //
    37.5  
    37.6  import Foundation
    37.7 +import pEpIOSToolbox
    37.8  
    37.9  class HtmlToTextSaxParser: BasicSaxParser {
   37.10      var tagStack = [String]()
    38.1 --- a/pEpForiOS/Info.plist	Wed Feb 20 11:00:07 2019 +0100
    38.2 +++ b/pEpForiOS/Info.plist	Mon Mar 18 10:54:14 2019 +0100
    38.3 @@ -17,7 +17,7 @@
    38.4  	<key>CFBundlePackageType</key>
    38.5  	<string>APPL</string>
    38.6  	<key>CFBundleShortVersionString</key>
    38.7 -	<string>0.0.41</string>
    38.8 +	<string>refactor0.1</string>
    38.9  	<key>CFBundleSignature</key>
   38.10  	<string>????</string>
   38.11  	<key>CFBundleURLTypes</key>
   38.12 @@ -40,7 +40,7 @@
   38.13  		</dict>
   38.14  	</array>
   38.15  	<key>CFBundleVersion</key>
   38.16 -	<string>3</string>
   38.17 +	<string>1</string>
   38.18  	<key>ITSAppUsesNonExemptEncryption</key>
   38.19  	<false/>
   38.20  	<key>LSRequiresIPhoneOS</key>
    39.1 --- a/pEpForiOS/Models/Account+Extentions.swift	Wed Feb 20 11:00:07 2019 +0100
    39.2 +++ b/pEpForiOS/Models/Account+Extentions.swift	Mon Mar 18 10:54:14 2019 +0100
    39.3 @@ -7,6 +7,7 @@
    39.4  //
    39.5  
    39.6  import MessageModel
    39.7 +import pEpIOSToolbox
    39.8  
    39.9  extension Account {
   39.10      /// Returns the account that should be used as deafult when sending a message.
    40.1 --- a/pEpForiOS/Models/CdFolder+Extension.swift	Wed Feb 20 11:00:07 2019 +0100
    40.2 +++ b/pEpForiOS/Models/CdFolder+Extension.swift	Mon Mar 18 10:54:14 2019 +0100
    40.3 @@ -7,7 +7,7 @@
    40.4  //
    40.5  
    40.6  import CoreData
    40.7 -
    40.8 +import pEpIOSToolbox
    40.9  import MessageModel
   40.10  
   40.11  public extension CdFolder {
    41.1 --- a/pEpForiOS/Models/CdIdentity+pEp.swift	Wed Feb 20 11:00:07 2019 +0100
    41.2 +++ b/pEpForiOS/Models/CdIdentity+pEp.swift	Mon Mar 18 10:54:14 2019 +0100
    41.3 @@ -7,6 +7,7 @@
    41.4  //
    41.5  
    41.6  import MessageModel
    41.7 +import pEpIOSToolbox
    41.8  
    41.9  /**
   41.10   pEp extension for CdIdentity
    42.1 --- a/pEpForiOS/Models/CdMessage+Pantomime.swift	Wed Feb 20 11:00:07 2019 +0100
    42.2 +++ b/pEpForiOS/Models/CdMessage+Pantomime.swift	Mon Mar 18 10:54:14 2019 +0100
    42.3 @@ -7,6 +7,7 @@
    42.4  //
    42.5  
    42.6  import MessageModel
    42.7 +import pEpIOSToolbox
    42.8  
    42.9  public typealias ImapStoreCommand = (command: String, pantomimeDict:[AnyHashable: Any])
   42.10  
   42.11 @@ -324,14 +325,13 @@
   42.12       * If there were no local flag changes (in respect to the previous server flags version),
   42.13       the local flags will then be set to the same value.
   42.14       * If there were local changes, then the local flags will not change.
   42.15 -     - Returns: true if the local flags were updated.
   42.16       */
   42.17 -    public func updateFromServer(cwFlags: CWFlags) -> Bool {
   42.18 +    public func updateFromServer(cwFlags: CWFlags) {
   42.19          // Since we frequently sync the flags, don't modify anything
   42.20          // if the version from the server has already been known,
   42.21          // since this could overwrite changes just made by the user.
   42.22          if cwFlags.rawFlagsAsShort() == imap?.serverFlags?.rawFlagsAsShort() {
   42.23 -            return false
   42.24 +            return
   42.25          }
   42.26  
   42.27          let theImap = imapFields()
   42.28 @@ -345,26 +345,23 @@
   42.29          let localFlags = theImap.localFlags ?? CdImapFlags.create()
   42.30          theImap.localFlags = localFlags
   42.31  
   42.32 -        var changedLocalFlags = false
   42.33          if haveLocalChanges {
   42.34 -            changedLocalFlags =  mergeOnConflict(localFlags: localFlags, serverFlags: serverFlags,
   42.35 -                                                 newServerFlags: cwFlags)
   42.36 +            mergeOnConflict(localFlags: localFlags, serverFlags: serverFlags,
   42.37 +                            newServerFlags: cwFlags)
   42.38          } else {
   42.39              localFlags.update(cwFlags: cwFlags)
   42.40 -            changedLocalFlags = true
   42.41          }
   42.42  
   42.43          serverFlags.update(cwFlags: cwFlags)
   42.44 -
   42.45 -        return changedLocalFlags
   42.46      }
   42.47  
   42.48      /**
   42.49       Tries to merge IMAP flags, basically taking into
   42.50       account which flags were changed locally if it makes any difference.
   42.51       */
   42.52 -    func mergeOnConflict(localFlags: CdImapFlags, serverFlags: CdImapFlags,
   42.53 -                         newServerFlags: CWFlags) -> Bool {
   42.54 +    func mergeOnConflict(localFlags: CdImapFlags,
   42.55 +                         serverFlags: CdImapFlags,
   42.56 +                         newServerFlags: CWFlags) {
   42.57          localFlags.flagAnswered = localFlags.flagAnswered || serverFlags.flagAnswered ||
   42.58              newServerFlags.contain(.answered)
   42.59          localFlags.flagDraft = localFlags.flagDraft || serverFlags.flagDraft ||
   42.60 @@ -378,7 +375,6 @@
   42.61          }
   42.62          localFlags.flagDeleted = localFlags.flagDeleted || serverFlags.flagDeleted ||
   42.63              newServerFlags.contain(.deleted)
   42.64 -        return localFlags.rawFlagsAsShort() != newServerFlags.rawFlagsAsShort()
   42.65      }
   42.66  
   42.67      /**
   42.68 @@ -415,11 +411,8 @@
   42.69              return mail
   42.70          }
   42.71          
   42.72 -        if mail.updateFromServer(cwFlags: message.flags()) {
   42.73 -            if mail.pEpRating != pEpRatingNone {
   42.74 -                mail.serialNumber = mail.serialNumber + 1
   42.75 -            }
   42.76 -        }
   42.77 +        mail.updateFromServer(cwFlags: message.flags())
   42.78 +
   42.79          // Bail out quickly if there is only a flag change needed
   42.80          if messageUpdate.isFlagsOnly() {
   42.81              guard isUpdate else {
   42.82 @@ -436,7 +429,6 @@
   42.83          
   42.84          if !moreMessagesThanRequested(mail: mail, messageUpdate: messageUpdate) {
   42.85              mail.parent = folder
   42.86 -            mail.bodyFetched = message.isInitialized()
   42.87              mail.sent = message.originationDate()
   42.88              mail.shortMessage = message.subject()
   42.89              
   42.90 @@ -461,10 +453,9 @@
   42.91              return
   42.92          }
   42.93          if !flags.deleted {
   42.94 -            MessageModelConfig.messageFolderDelegate?.didUpdate(messageFolder: msg)
   42.95 +            MessageModelConfig.messageFolderDelegate?.didUpdate(message: msg)
   42.96          } else {
   42.97 -            MessageModelConfig.messageFolderDelegate?.didDelete(
   42.98 -                messageFolder: msg)
   42.99 +            MessageModelConfig.messageFolderDelegate?.didDelete(message: msg)
  42.100          }
  42.101      }
  42.102  
  42.103 @@ -474,13 +465,11 @@
  42.104       (e.g., parsing of HTML and/or attachments).
  42.105       - Parameter message: The pantomime message to insert.
  42.106       - Parameter account: The account this email is supposed to be stored for.
  42.107 -     - Parameter forceParseAttachments: If true, this will parse the attachments even
  42.108 -     if the pantomime has not been initialized yet (useful for testing).
  42.109       - Returns: The newly created or updated Message
  42.110       */
  42.111 -    public static func insertOrUpdate( pantomimeMessage: CWIMAPMessage, account: CdAccount,
  42.112 -                                       messageUpdate: CWMessageUpdate,
  42.113 -                                       forceParseAttachments: Bool = false) -> CdMessage? {
  42.114 +    public static func insertOrUpdate(pantomimeMessage: CWIMAPMessage,
  42.115 +                                      account: CdAccount,
  42.116 +                                      messageUpdate: CWMessageUpdate) -> CdMessage? {
  42.117          objc_sync_enter(self)
  42.118          defer { objc_sync_exit(self) }
  42.119          
  42.120 @@ -515,8 +504,6 @@
  42.121              mail.from = cdIdentity(pantomimeAddress: from)
  42.122          }
  42.123  
  42.124 -        mail.bodyFetched = pantomimeMessage.isInitialized()
  42.125 -
  42.126          if let addresses = pantomimeMessage.recipients() as? [CWInternetAddress] {
  42.127              let tos: NSMutableOrderedSet = []
  42.128              let ccs: NSMutableOrderedSet = []
  42.129 @@ -562,11 +549,7 @@
  42.130          // accidentally made its way until here.
  42.131          // Do *not* add the attachments again.
  42.132          if !containsAttachments(cdMessage: mail) {
  42.133 -            if forceParseAttachments || mail.bodyFetched {
  42.134 -                // Parsing attachments only makes sense once pantomime has received the
  42.135 -                // mail body. Same goes for the snippet.
  42.136 -                addAttachmentsFromPantomimePart(pantomimeMessage, targetMail: mail)
  42.137 -            }
  42.138 +            addAttachmentsFromPantomimePart(pantomimeMessage, targetMail: mail)
  42.139          }
  42.140  
  42.141          store(headerFieldNames: ["X-pEp-Version", "X-EncStatus", "X-KeyList"],
  42.142 @@ -576,7 +559,7 @@
  42.143          Record.saveAndWait()
  42.144          if mail.pEpRating != PEPUtil.pEpRatingNone,
  42.145              let msg = mail.message() {
  42.146 -            MessageModelConfig.messageFolderDelegate?.didCreate(messageFolder: msg)
  42.147 +            MessageModelConfig.messageFolderDelegate?.didCreate(message: msg)
  42.148          }
  42.149  
  42.150          return mail
  42.151 @@ -708,7 +691,7 @@
  42.152                                                    contentID: part.contentID(),
  42.153                                                    data: data,
  42.154                                                    contentDispositionRawValue: contentDispRawValue)
  42.155 -                targetMail.addAttachment(cdAttachment: attachment)
  42.156 +                targetMail.addToAttachments(attachment)
  42.157              }
  42.158          }
  42.159  
    43.1 --- a/pEpForiOS/Models/CdMessage+pEp.swift	Wed Feb 20 11:00:07 2019 +0100
    43.2 +++ b/pEpForiOS/Models/CdMessage+pEp.swift	Mon Mar 18 10:54:14 2019 +0100
    43.3 @@ -26,8 +26,6 @@
    43.4              update(rating: theRating)
    43.5          }
    43.6  
    43.7 -        bodyFetched = true
    43.8 -
    43.9          shortMessage = (pEpMessageDict[kPepShortMessage] as? String)?.applyingDos2Unix()
   43.10          longMessage = (pEpMessageDict[kPepLongMessage] as? String)?.applyingDos2Unix()
   43.11          longMessageFormatted = (pEpMessageDict[kPepLongMessageFormatted]
    44.1 --- a/pEpForiOS/Models/ContentDispositionType + Conversion.swift	Wed Feb 20 11:00:07 2019 +0100
    44.2 +++ b/pEpForiOS/Models/ContentDispositionType + Conversion.swift	Mon Mar 18 10:54:14 2019 +0100
    44.3 @@ -7,6 +7,7 @@
    44.4  //
    44.5  
    44.6  import MessageModel
    44.7 +import pEpIOSToolbox
    44.8  
    44.9  extension content_disposition_type {
   44.10  
    45.1 --- a/pEpForiOS/Models/Folder+Imap.swift	Wed Feb 20 11:00:07 2019 +0100
    45.2 +++ b/pEpForiOS/Models/Folder+Imap.swift	Mon Mar 18 10:54:14 2019 +0100
    45.3 @@ -7,6 +7,7 @@
    45.4  //
    45.5  
    45.6  import MessageModel
    45.7 +import pEpIOSToolbox
    45.8  
    45.9  /// Logic based on data MessageModel should not know.
   45.10  extension Folder {
    46.1 --- a/pEpForiOS/Models/Message+FakeMessage.swift	Wed Feb 20 11:00:07 2019 +0100
    46.2 +++ b/pEpForiOS/Models/Message+FakeMessage.swift	Mon Mar 18 10:54:14 2019 +0100
    46.3 @@ -29,7 +29,7 @@
    46.4          fakeMsg.uuid = uuid
    46.5          CdMessage.create(withContentOf: fakeMsg)
    46.6          Record.saveAndWait()
    46.7 -        MessageModelConfig.messageFolderDelegate?.didCreate(messageFolder: fakeMsg)
    46.8 +        MessageModelConfig.messageFolderDelegate?.didCreate(message: fakeMsg)
    46.9      }
   46.10  
   46.11      static public func createCdFakeMessage(for msg: Message) {
   46.12 @@ -40,7 +40,7 @@
   46.13          fakeMsg.uuid = msg.uuid
   46.14          CdMessage.create(withContentOf: fakeMsg)
   46.15          Record.saveAndWait()
   46.16 -        MessageModelConfig.messageFolderDelegate?.didCreate(messageFolder: fakeMsg)
   46.17 +        MessageModelConfig.messageFolderDelegate?.didCreate(message: fakeMsg)
   46.18      }
   46.19  
   46.20      func saveFakeMessage(in targetFolder: Folder) {
    47.1 --- a/pEpForiOS/Models/Message+IMAP.swift	Wed Feb 20 11:00:07 2019 +0100
    47.2 +++ b/pEpForiOS/Models/Message+IMAP.swift	Mon Mar 18 10:54:14 2019 +0100
    47.3 @@ -7,6 +7,7 @@
    47.4  //
    47.5  
    47.6  import MessageModel
    47.7 +import pEpIOSToolbox
    47.8  
    47.9  extension Message {
   47.10      static let uidNeedsAppend = 0
    48.1 --- a/pEpForiOS/Models/Message+pEp.swift	Wed Feb 20 11:00:07 2019 +0100
    48.2 +++ b/pEpForiOS/Models/Message+pEp.swift	Mon Mar 18 10:54:14 2019 +0100
    48.3 @@ -7,6 +7,7 @@
    48.4  //
    48.5  
    48.6  import MessageModel
    48.7 +import pEpIOSToolbox
    48.8  
    48.9  extension Message {
   48.10      public var isEncrypted: Bool {
    49.1 --- a/pEpForiOS/Models/Server+Fetching.swift	Wed Feb 20 11:00:07 2019 +0100
    49.2 +++ b/pEpForiOS/Models/Server+Fetching.swift	Mon Mar 18 10:54:14 2019 +0100
    49.3 @@ -7,6 +7,7 @@
    49.4  //
    49.5  
    49.6  import MessageModel
    49.7 +import pEpIOSToolbox
    49.8  
    49.9  extension Server {
   49.10  
    50.1 --- a/pEpForiOS/Models/UnifiedInbox.swift	Wed Feb 20 11:00:07 2019 +0100
    50.2 +++ b/pEpForiOS/Models/UnifiedInbox.swift	Mon Mar 18 10:54:14 2019 +0100
    50.3 @@ -6,6 +6,7 @@
    50.4  //
    50.5  
    50.6  import MessageModel
    50.7 +import pEpIOSToolbox
    50.8  
    50.9  public class UnifiedInbox: Folder {
   50.10      static public let defaultUnifiedInboxName = "Unified Inbox"
   50.11 @@ -85,7 +86,7 @@
   50.12              return theFilter.fulfillsFilter(message: message)
   50.13          }
   50.14  
   50.15 -        var result = !message.isGhost && message.parent.folderType == .inbox
   50.16 +        var result = !(message.imapFlags?.deleted ?? false) && message.parent.folderType == .inbox
   50.17          if !markedForMoveToFolderAreContained {
   50.18              result =
   50.19                  result && (message.targetFolder == nil || message.targetFolder == message.parent)
    51.1 --- a/pEpForiOS/Network/ConnectInfo/ConnectInfo.swift	Wed Feb 20 11:00:07 2019 +0100
    51.2 +++ b/pEpForiOS/Network/ConnectInfo/ConnectInfo.swift	Mon Mar 18 10:54:14 2019 +0100
    51.3 @@ -7,6 +7,7 @@
    51.4  //
    51.5  
    51.6  import MessageModel
    51.7 +import pEpIOSToolbox
    51.8  
    51.9  enum NetworkAddressType: String {
   51.10      case ipv4 = "IPv4"
    52.1 --- a/pEpForiOS/Network/ConnectInfo/EmailConnectInfo+Extension.swift	Wed Feb 20 11:00:07 2019 +0100
    52.2 +++ b/pEpForiOS/Network/ConnectInfo/EmailConnectInfo+Extension.swift	Mon Mar 18 10:54:14 2019 +0100
    52.3 @@ -8,7 +8,7 @@
    52.4  
    52.5  import Foundation
    52.6  import CoreData
    52.7 -
    52.8 +import pEpIOSToolbox
    52.9  import MessageModel
   52.10  
   52.11  extension EmailConnectInfo {
    53.1 --- a/pEpForiOS/Network/ConnectInfo/deprecated/LegacyConnectInfoProvider.swift	Wed Feb 20 11:00:07 2019 +0100
    53.2 +++ b/pEpForiOS/Network/ConnectInfo/deprecated/LegacyConnectInfoProvider.swift	Mon Mar 18 10:54:14 2019 +0100
    53.3 @@ -8,6 +8,7 @@
    53.4  
    53.5  import MessageModel
    53.6  import CoreData
    53.7 +import pEpIOSToolbox
    53.8  
    53.9  /// Supports usage of deprecated EmailConnectInfo.
   53.10  extension ConnectInfo {
    54.1 --- a/pEpForiOS/Network/DefaultImapSyncDelegate.swift	Wed Feb 20 11:00:07 2019 +0100
    54.2 +++ b/pEpForiOS/Network/DefaultImapSyncDelegate.swift	Mon Mar 18 10:54:14 2019 +0100
    54.3 @@ -6,6 +6,8 @@
    54.4  //  Copyright © 2017 p≡p Security S.A. All rights reserved.
    54.5  //
    54.6  
    54.7 +import pEpIOSToolbox
    54.8 +
    54.9  protocol ImapSyncDelegateErrorHandlerProtocol: class {
   54.10      func handle(error: Error)
   54.11  }
    55.1 --- a/pEpForiOS/Network/EmailService.swift	Wed Feb 20 11:00:07 2019 +0100
    55.2 +++ b/pEpForiOS/Network/EmailService.swift	Mon Mar 18 10:54:14 2019 +0100
    55.3 @@ -6,6 +6,8 @@
    55.4  //  Copyright © 2016 p≡p Security S.A. All rights reserved.
    55.5  //
    55.6  
    55.7 +import pEpIOSToolbox
    55.8 +
    55.9  protocol IEmailService {
   55.10      func start()
   55.11  }
    56.1 --- a/pEpForiOS/Network/ImapService.swift	Wed Feb 20 11:00:07 2019 +0100
    56.2 +++ b/pEpForiOS/Network/ImapService.swift	Mon Mar 18 10:54:14 2019 +0100
    56.3 @@ -7,6 +7,7 @@
    56.4  //
    56.5  
    56.6  import MessageModel
    56.7 +import pEpIOSToolbox
    56.8  
    56.9  public protocol ImapSyncDelegate: class {
   56.10      func authenticationCompleted(_ sync: ImapSync, notification: Notification?)
    57.1 --- a/pEpForiOS/Network/Service/AccountVerificationService/AccountVerificationService.swift	Wed Feb 20 11:00:07 2019 +0100
    57.2 +++ b/pEpForiOS/Network/Service/AccountVerificationService/AccountVerificationService.swift	Mon Mar 18 10:54:14 2019 +0100
    57.3 @@ -7,6 +7,7 @@
    57.4  //
    57.5  
    57.6  import MessageModel
    57.7 +import pEpIOSToolbox
    57.8  
    57.9  class AccountVerificationService: AccountVerificationServiceProtocol {
   57.10      weak var delegate: AccountVerificationServiceDelegate?
    58.1 --- a/pEpForiOS/Network/Service/FetchOlderImapMessagesService.swift	Wed Feb 20 11:00:07 2019 +0100
    58.2 +++ b/pEpForiOS/Network/Service/FetchOlderImapMessagesService.swift	Mon Mar 18 10:54:14 2019 +0100
    58.3 @@ -7,6 +7,7 @@
    58.4  //
    58.5  
    58.6  import MessageModel
    58.7 +import pEpIOSToolbox
    58.8  
    58.9  public class FetchOlderImapMessagesService {
   58.10      var runningOperations = [Folder:BaseOperation]()
    59.1 --- a/pEpForiOS/Network/Service/MessageSyncService/MessageSyncService.swift	Wed Feb 20 11:00:07 2019 +0100
    59.2 +++ b/pEpForiOS/Network/Service/MessageSyncService/MessageSyncService.swift	Mon Mar 18 10:54:14 2019 +0100
    59.3 @@ -8,7 +8,7 @@
    59.4  
    59.5  import Foundation
    59.6  import CoreData
    59.7 -
    59.8 +import pEpIOSToolbox
    59.9  import MessageModel
   59.10  
   59.11  class MessageSyncService: MessageSyncServiceProtocol {
    60.1 --- a/pEpForiOS/Network/Service/NetworkService.swift	Wed Feb 20 11:00:07 2019 +0100
    60.2 +++ b/pEpForiOS/Network/Service/NetworkService.swift	Mon Mar 18 10:54:14 2019 +0100
    60.3 @@ -7,7 +7,7 @@
    60.4  //
    60.5  
    60.6  import Foundation
    60.7 -
    60.8 +import pEpIOSToolbox
    60.9  import MessageModel
   60.10  
   60.11  public protocol NetworkServiceDelegate: class {
    61.1 --- a/pEpForiOS/Network/Service/NetworkServiceWorker.swift	Wed Feb 20 11:00:07 2019 +0100
    61.2 +++ b/pEpForiOS/Network/Service/NetworkServiceWorker.swift	Mon Mar 18 10:54:14 2019 +0100
    61.3 @@ -8,7 +8,7 @@
    61.4  
    61.5  import UIKit
    61.6  import CoreData
    61.7 -
    61.8 +import pEpIOSToolbox
    61.9  import MessageModel
   61.10  
   61.11  public protocol NetworkServiceWorkerDelegate: class {
    62.1 --- a/pEpForiOS/Network/Service/QualifyServerIsLocalOperation.swift	Wed Feb 20 11:00:07 2019 +0100
    62.2 +++ b/pEpForiOS/Network/Service/QualifyServerIsLocalOperation.swift	Mon Mar 18 10:54:14 2019 +0100
    62.3 @@ -7,6 +7,7 @@
    62.4  //
    62.5  
    62.6  import Foundation
    62.7 +import pEpIOSToolbox
    62.8  
    62.9  /**
   62.10   Qualifies the given server name re trusted or untrusted, depending on
    63.1 --- a/pEpForiOS/Network/SmtpService.swift	Wed Feb 20 11:00:07 2019 +0100
    63.2 +++ b/pEpForiOS/Network/SmtpService.swift	Mon Mar 18 10:54:14 2019 +0100
    63.3 @@ -6,6 +6,8 @@
    63.4  //  Copyright © 2016 p≡p Security S.A. All rights reserved.
    63.5  //
    63.6  
    63.7 +import pEpIOSToolbox
    63.8 +
    63.9  public protocol SmtpSendDelegate: class {
   63.10      func messageSent(_ smtp: SmtpSend, theNotification: Notification?)
   63.11      func messageNotSent(_ smtp: SmtpSend, theNotification: Notification?)
    64.1 --- a/pEpForiOS/UI/Background/ReevaluateMessageRatingOperation.swift	Wed Feb 20 11:00:07 2019 +0100
    64.2 +++ b/pEpForiOS/UI/Background/ReevaluateMessageRatingOperation.swift	Mon Mar 18 10:54:14 2019 +0100
    64.3 @@ -8,7 +8,7 @@
    64.4  
    64.5  import UIKit
    64.6  import CoreData
    64.7 -
    64.8 +import pEpIOSToolbox
    64.9  import MessageModel
   64.10  
   64.11  /**
    65.1 --- a/pEpForiOS/UI/Compose/Cells/AccountCell/AccountCell.swift	Wed Feb 20 11:00:07 2019 +0100
    65.2 +++ b/pEpForiOS/UI/Compose/Cells/AccountCell/AccountCell.swift	Mon Mar 18 10:54:14 2019 +0100
    65.3 @@ -7,6 +7,7 @@
    65.4  //
    65.5  
    65.6  import UIKit
    65.7 +import pEpIOSToolbox
    65.8  
    65.9  class AccountCell: TextViewContainingTableViewCell {
   65.10      static let reuseId = "AccountCell"
    66.1 --- a/pEpForiOS/UI/Compose/Cells/BodyCell/BodyCell.swift	Wed Feb 20 11:00:07 2019 +0100
    66.2 +++ b/pEpForiOS/UI/Compose/Cells/BodyCell/BodyCell.swift	Mon Mar 18 10:54:14 2019 +0100
    66.3 @@ -7,6 +7,7 @@
    66.4  //
    66.5  
    66.6  import UIKit
    66.7 +import pEpIOSToolbox
    66.8  
    66.9  class BodyCell: TextViewContainingTableViewCell {
   66.10      static let reuseId = "BodyCell"
    67.1 --- a/pEpForiOS/UI/Compose/Cells/BodyCell/BodyCellViewModel.swift	Wed Feb 20 11:00:07 2019 +0100
    67.2 +++ b/pEpForiOS/UI/Compose/Cells/BodyCell/BodyCellViewModel.swift	Mon Mar 18 10:54:14 2019 +0100
    67.3 @@ -7,6 +7,7 @@
    67.4  //
    67.5  
    67.6  import MessageModel
    67.7 +import pEpIOSToolbox
    67.8  
    67.9  protocol BodyCellViewModelResultDelegate: class {
   67.10  
    68.1 --- a/pEpForiOS/UI/Compose/Cells/BodyCell/NSAttributedString+BodyTextUtils.swift	Wed Feb 20 11:00:07 2019 +0100
    68.2 +++ b/pEpForiOS/UI/Compose/Cells/BodyCell/NSAttributedString+BodyTextUtils.swift	Mon Mar 18 10:54:14 2019 +0100
    68.3 @@ -7,6 +7,7 @@
    68.4  //
    68.5  
    68.6  import MessageModel
    68.7 +import pEpIOSToolbox
    68.8  
    68.9  // MARK: - BodyTextUtils
   68.10  
    69.1 --- a/pEpForiOS/UI/Compose/Cells/RecipientCell/RecipientTextView/RecipientTextView.swift	Wed Feb 20 11:00:07 2019 +0100
    69.2 +++ b/pEpForiOS/UI/Compose/Cells/RecipientCell/RecipientTextView/RecipientTextView.swift	Mon Mar 18 10:54:14 2019 +0100
    69.3 @@ -7,6 +7,7 @@
    69.4  //
    69.5  
    69.6  import UIKit
    69.7 +import pEpIOSToolbox
    69.8  
    69.9  class RecipientTextView: UITextView {
   69.10      public var viewModel: RecipientTextViewModel?{
    70.1 --- a/pEpForiOS/UI/Compose/Cells/RecipientCell/RecipientTextView/RecipientTextViewModel+TextAttachment.swift	Wed Feb 20 11:00:07 2019 +0100
    70.2 +++ b/pEpForiOS/UI/Compose/Cells/RecipientCell/RecipientTextView/RecipientTextViewModel+TextAttachment.swift	Mon Mar 18 10:54:14 2019 +0100
    70.3 @@ -7,6 +7,7 @@
    70.4  //
    70.5  
    70.6  import MessageModel
    70.7 +import pEpIOSToolbox
    70.8  
    70.9  extension RecipientTextViewModel {
   70.10  
    71.1 --- a/pEpForiOS/UI/Compose/ComposeTableViewController.swift	Wed Feb 20 11:00:07 2019 +0100
    71.2 +++ b/pEpForiOS/UI/Compose/ComposeTableViewController.swift	Mon Mar 18 10:54:14 2019 +0100
    71.3 @@ -10,6 +10,7 @@
    71.4  import MessageModel
    71.5  import SwipeCellKit
    71.6  import Photos
    71.7 +import pEpIOSToolbox
    71.8  
    71.9  class ComposeTableViewController: BaseTableViewController {
   71.10      @IBOutlet var sendButton: UIBarButtonItem!
    72.1 --- a/pEpForiOS/UI/Compose/Util/ComposeUtil.swift	Wed Feb 20 11:00:07 2019 +0100
    72.2 +++ b/pEpForiOS/UI/Compose/Util/ComposeUtil.swift	Mon Mar 18 10:54:14 2019 +0100
    72.3 @@ -7,6 +7,7 @@
    72.4  //
    72.5  
    72.6  import MessageModel
    72.7 +import pEpIOSToolbox
    72.8  
    72.9  /// Utils for composing a message. Helps finding out values depending on the original message
   72.10  /// (the correct recipients, cancle actions ...).
    73.1 --- a/pEpForiOS/UI/Compose/Util/DocumentAttachmentPickerViewController/DocumentAttachmentPickerViewModel.swift	Wed Feb 20 11:00:07 2019 +0100
    73.2 +++ b/pEpForiOS/UI/Compose/Util/DocumentAttachmentPickerViewController/DocumentAttachmentPickerViewModel.swift	Mon Mar 18 10:54:14 2019 +0100
    73.3 @@ -7,6 +7,7 @@
    73.4  //
    73.5  
    73.6  import MessageModel
    73.7 +import pEpIOSToolbox
    73.8  
    73.9  protocol DocumentAttachmentPickerViewModelResultDelegate: class {
   73.10      func documentAttachmentPickerViewModel(_ vm: DocumentAttachmentPickerViewModel,
    74.1 --- a/pEpForiOS/UI/Compose/Util/MediaAttachmentPickerProvider/MediaAttachmentPickerProviderViewModel.swift	Wed Feb 20 11:00:07 2019 +0100
    74.2 +++ b/pEpForiOS/UI/Compose/Util/MediaAttachmentPickerProvider/MediaAttachmentPickerProviderViewModel.swift	Mon Mar 18 10:54:14 2019 +0100
    74.3 @@ -7,6 +7,7 @@
    74.4  //
    74.5  
    74.6  import MessageModel
    74.7 +import pEpIOSToolbox
    74.8  
    74.9  protocol MediaAttachmentPickerProviderViewModelResultDelegate: class {
   74.10      func mediaAttachmentPickerProviderViewModel(_ vm: MediaAttachmentPickerProviderViewModel,
    75.1 --- a/pEpForiOS/UI/Compose/ViewModel/ComposeViewModel+InitData.swift	Wed Feb 20 11:00:07 2019 +0100
    75.2 +++ b/pEpForiOS/UI/Compose/ViewModel/ComposeViewModel+InitData.swift	Mon Mar 18 10:54:14 2019 +0100
    75.3 @@ -7,6 +7,7 @@
    75.4  //
    75.5  
    75.6  import MessageModel
    75.7 +import pEpIOSToolbox
    75.8  
    75.9  // MARK: - InitData
   75.10  
    76.1 --- a/pEpForiOS/UI/Compose/ViewModel/ComposeViewModel.swift	Wed Feb 20 11:00:07 2019 +0100
    76.2 +++ b/pEpForiOS/UI/Compose/ViewModel/ComposeViewModel.swift	Mon Mar 18 10:54:14 2019 +0100
    76.3 @@ -7,6 +7,7 @@
    76.4  //
    76.5  
    76.6  import MessageModel
    76.7 +import pEpIOSToolbox
    76.8  
    76.9  /// Informs the one that triggered the segued to here.
   76.10  protocol ComposeViewModelResultDelegate: class {
    77.1 --- a/pEpForiOS/UI/Compose/ViewModel/ComposeViewModelState.swift	Wed Feb 20 11:00:07 2019 +0100
    77.2 +++ b/pEpForiOS/UI/Compose/ViewModel/ComposeViewModelState.swift	Mon Mar 18 10:54:14 2019 +0100
    77.3 @@ -7,6 +7,7 @@
    77.4  //
    77.5  
    77.6  import MessageModel
    77.7 +import pEpIOSToolbox
    77.8  
    77.9  protocol ComposeViewModelStateDelegate: class {
   77.10      func composeViewModelState(_ composeViewModelState: ComposeViewModel.ComposeViewModelState,
    78.1 --- a/pEpForiOS/UI/EmailDisplay/Background/AttachmentToLocalURLOperation.swift	Wed Feb 20 11:00:07 2019 +0100
    78.2 +++ b/pEpForiOS/UI/EmailDisplay/Background/AttachmentToLocalURLOperation.swift	Mon Mar 18 10:54:14 2019 +0100
    78.3 @@ -7,7 +7,7 @@
    78.4  //
    78.5  
    78.6  import Foundation
    78.7 -
    78.8 +import pEpIOSToolbox
    78.9  import MessageModel
   78.10  
   78.11  class AttachmentToLocalURLOperation: Operation {
    79.1 --- a/pEpForiOS/UI/EmailDisplay/CellAndSections/MessageSubjectCell.swift	Wed Feb 20 11:00:07 2019 +0100
    79.2 +++ b/pEpForiOS/UI/EmailDisplay/CellAndSections/MessageSubjectCell.swift	Mon Mar 18 10:54:14 2019 +0100
    79.3 @@ -7,6 +7,7 @@
    79.4  
    79.5  import UIKit
    79.6  import MessageModel
    79.7 +import pEpIOSToolbox
    79.8  
    79.9  open class MessageSubjectCell: MessageCell {
   79.10      public override func updateCell(model: ComposeFieldModel, message: Message) {
    80.1 --- a/pEpForiOS/UI/EmailDisplay/EmailViewController.swift	Wed Feb 20 11:00:07 2019 +0100
    80.2 +++ b/pEpForiOS/UI/EmailDisplay/EmailViewController.swift	Mon Mar 18 10:54:14 2019 +0100
    80.3 @@ -8,6 +8,7 @@
    80.4  
    80.5  import Foundation
    80.6  import UIKit
    80.7 +import pEpIOSToolbox
    80.8  import QuickLook
    80.9  
   80.10  import MessageModel
    81.1 --- a/pEpForiOS/UI/EmailDisplay/Stuff that is named Compose but is used only in EmailView/ComposeDataSource.swift	Wed Feb 20 11:00:07 2019 +0100
    81.2 +++ b/pEpForiOS/UI/EmailDisplay/Stuff that is named Compose but is used only in EmailView/ComposeDataSource.swift	Mon Mar 18 10:54:14 2019 +0100
    81.3 @@ -8,7 +8,7 @@
    81.4  
    81.5  import Foundation
    81.6  import UIKit
    81.7 -
    81.8 +import pEpIOSToolbox
    81.9  import MessageModel
   81.10  
   81.11  class ComposeDataSource: NSObject {
    82.1 --- a/pEpForiOS/UI/EmailDisplay/Util/AttachmentSummaryView.swift	Wed Feb 20 11:00:07 2019 +0100
    82.2 +++ b/pEpForiOS/UI/EmailDisplay/Util/AttachmentSummaryView.swift	Mon Mar 18 10:54:14 2019 +0100
    82.3 @@ -7,6 +7,7 @@
    82.4  //
    82.5  
    82.6  import Foundation
    82.7 +import pEpIOSToolbox
    82.8  
    82.9  class AttachmentSummaryView: UIView {
   82.10      /**
    83.1 --- a/pEpForiOS/UI/EmailDisplay/Util/AttachmentsViewHelper.swift	Wed Feb 20 11:00:07 2019 +0100
    83.2 +++ b/pEpForiOS/UI/EmailDisplay/Util/AttachmentsViewHelper.swift	Mon Mar 18 10:54:14 2019 +0100
    83.3 @@ -7,7 +7,7 @@
    83.4  //
    83.5  
    83.6  import Foundation
    83.7 -
    83.8 +import pEpIOSToolbox
    83.9  import MessageModel
   83.10  
   83.11  protocol AttachmentsViewHelperDelegate: class {
    84.1 --- a/pEpForiOS/UI/EmailDisplayList/EmailListViewController.swift	Wed Feb 20 11:00:07 2019 +0100
    84.2 +++ b/pEpForiOS/UI/EmailDisplayList/EmailListViewController.swift	Mon Mar 18 10:54:14 2019 +0100
    84.3 @@ -8,6 +8,7 @@
    84.4  
    84.5  import UIKit
    84.6  import SwipeCellKit
    84.7 +import pEpIOSToolbox
    84.8  
    84.9  class EmailListViewController: BaseTableViewController, SwipeTableViewCellDelegate {
   84.10      static let FILTER_TITLE_MAX_XAR = 20
    85.1 --- a/pEpForiOS/UI/EmailDisplayList/EmailListViewModel+EmailDisplayDelegate.swift	Wed Feb 20 11:00:07 2019 +0100
    85.2 +++ b/pEpForiOS/UI/EmailDisplayList/EmailListViewModel+EmailDisplayDelegate.swift	Mon Mar 18 10:54:14 2019 +0100
    85.3 @@ -7,7 +7,7 @@
    85.4  //
    85.5  
    85.6  import Foundation
    85.7 -
    85.8 +import pEpIOSToolbox
    85.9  import MessageModel
   85.10  
   85.11  extension EmailListViewModel: EmailDisplayDelegate {
   85.12 @@ -26,7 +26,7 @@
   85.13                  Logger.frontendLogger.lostMySelf()
   85.14                  return
   85.15              }
   85.16 -            me.didDelete(messageFolder: message)
   85.17 +            me.didDelete(message: message)
   85.18          }
   85.19      }
   85.20  
    86.1 --- a/pEpForiOS/UI/EmailDisplayList/EmailListViewModel+MessageFolderDelegate.swift	Wed Feb 20 11:00:07 2019 +0100
    86.2 +++ b/pEpForiOS/UI/EmailDisplayList/EmailListViewModel+MessageFolderDelegate.swift	Mon Mar 18 10:54:14 2019 +0100
    86.3 @@ -7,41 +7,40 @@
    86.4  //
    86.5  
    86.6  import Foundation
    86.7 -
    86.8 +import pEpIOSToolbox
    86.9  import MessageModel
   86.10  
   86.11  extension EmailListViewModel: MessageFolderDelegate {
   86.12  
   86.13      // MARK: - MessageFolderDelegate (public)
   86.14  
   86.15 -    func didCreate(messageFolder: MessageFolder) {
   86.16 +    func didCreate(message: Message) {
   86.17          DispatchQueue.main.async { [weak self] in
   86.18              guard let me = self else {
   86.19                  Logger.frontendLogger.lostMySelf()
   86.20                  return
   86.21              }
   86.22 -            me.didCreateInternal(messageFolder: messageFolder)
   86.23 +            me.didCreateInternal(message: message)
   86.24          }
   86.25      }
   86.26  
   86.27 -    func didUpdate(messageFolder: MessageFolder) {
   86.28 +    func didUpdate(message: Message) {
   86.29          DispatchQueue.main.async { [weak self] in
   86.30              guard let me = self else {
   86.31                  Logger.frontendLogger.lostMySelf()
   86.32                  return
   86.33              }
   86.34 -            me.didUpdateInternal(messageFolder: messageFolder)
   86.35 +            me.didUpdateInternal(message: message)
   86.36          }
   86.37      }
   86.38  
   86.39 -    func didDelete(messageFolder: MessageFolder) {
   86.40 +    func didDelete(message: Message) {
   86.41          DispatchQueue.main.async { [weak self] in
   86.42              guard let me = self else {
   86.43                  Logger.frontendLogger.lostMySelf()
   86.44                  return
   86.45              }
   86.46 -            me.didDeleteInternal(
   86.47 -                messageFolder: messageFolder)
   86.48 +            me.didDeleteInternal(message: message)
   86.49          }
   86.50      }
   86.51  
   86.52 @@ -57,11 +56,7 @@
   86.53          return existingIndex != nil
   86.54      }
   86.55  
   86.56 -    private func didCreateInternal(messageFolder: MessageFolder) {
   86.57 -        guard let message = messageFolder as? Message else {
   86.58 -            // The createe is no message. Ignore.
   86.59 -            return
   86.60 -        }
   86.61 +    private func didCreateInternal(message: Message) {
   86.62          if !shouldBeDisplayed(message: message) {
   86.63              return
   86.64          }
   86.65 @@ -109,13 +104,7 @@
   86.66          insertAsTopMessage()
   86.67      }
   86.68  
   86.69 -    private func didDeleteInternal(messageFolder: MessageFolder) {
   86.70 -        // Make sure it is a Message (not a Folder). Flag must have changed
   86.71 -        guard let message = messageFolder as? Message else {
   86.72 -            // It is not a Message (probably it is a Folder).
   86.73 -            return
   86.74 -        }
   86.75 -
   86.76 +    private func didDeleteInternal(message: Message) {
   86.77          if !shouldBeDisplayed(message: message) {
   86.78              return
   86.79          }
   86.80 @@ -137,12 +126,7 @@
   86.81              didRemoveDataAt: [indexPath])
   86.82      }
   86.83  
   86.84 -    private func didUpdateInternal(messageFolder: MessageFolder) {
   86.85 -        // Make sure it is a Message (not a Folder). Flag must have changed
   86.86 -        guard let message = messageFolder as? Message else {
   86.87 -            // It is not a Message (probably it is a Folder).
   86.88 -            return
   86.89 -        }
   86.90 +    private func didUpdateInternal(message: Message) {
   86.91          if !shouldBeDisplayed(message: message) {
   86.92              return
   86.93          }
    87.1 --- a/pEpForiOS/UI/EmailDisplayList/EmailListViewModel.swift	Wed Feb 20 11:00:07 2019 +0100
    87.2 +++ b/pEpForiOS/UI/EmailDisplayList/EmailListViewModel.swift	Mon Mar 18 10:54:14 2019 +0100
    87.3 @@ -7,7 +7,7 @@
    87.4  //
    87.5  
    87.6  import Foundation
    87.7 -
    87.8 +import pEpIOSToolbox
    87.9  import MessageModel
   87.10  
   87.11  protocol EmailListViewModelDelegate: TableViewUpdate {
   87.12 @@ -106,7 +106,7 @@
   87.13              return false
   87.14          }
   87.15      }
   87.16 -    
   87.17 +
   87.18      //check if there are some important settings that have changed to force a reload
   87.19      func checkIfSettingsChanged() -> Bool {
   87.20          if AppSettings.threadedViewEnabled != oldThreadSetting {
   87.21 @@ -336,7 +336,7 @@
   87.22                  "Not sure if this is a valid case. Remove this log if so.")
   87.23              return
   87.24          }
   87.25 -        didDelete(messageFolder: deletedMessage)
   87.26 +        didDelete(message: deletedMessage)
   87.27      }
   87.28  
   87.29      private func deleteMessage(at indexPath: IndexPath) -> Message? {
    88.1 --- a/pEpForiOS/UI/EmailDisplayList/MessageViewModel.swift	Wed Feb 20 11:00:07 2019 +0100
    88.2 +++ b/pEpForiOS/UI/EmailDisplayList/MessageViewModel.swift	Mon Mar 18 10:54:14 2019 +0100
    88.3 @@ -8,6 +8,7 @@
    88.4  
    88.5  import Foundation
    88.6  import MessageModel
    88.7 +import pEpIOSToolbox
    88.8  
    88.9  class MessageViewModel: CustomDebugStringConvertible {
   88.10  
    89.1 --- a/pEpForiOS/UI/Filter/ViewModel/FilterViewModel.swift	Wed Feb 20 11:00:07 2019 +0100
    89.2 +++ b/pEpForiOS/UI/Filter/ViewModel/FilterViewModel.swift	Mon Mar 18 10:54:14 2019 +0100
    89.3 @@ -8,6 +8,7 @@
    89.4  
    89.5  import Foundation
    89.6  import MessageModel
    89.7 +import pEpIOSToolbox
    89.8  
    89.9  public enum FilterSectionType {
   89.10      case accouts, include, other
    90.1 --- a/pEpForiOS/UI/Folder/FolderTableViewController.swift	Wed Feb 20 11:00:07 2019 +0100
    90.2 +++ b/pEpForiOS/UI/Folder/FolderTableViewController.swift	Mon Mar 18 10:54:14 2019 +0100
    90.3 @@ -7,6 +7,7 @@
    90.4  //
    90.5  
    90.6  import UIKit
    90.7 +import pEpIOSToolbox
    90.8  
    90.9  class FolderTableViewController: BaseTableViewController, FolderViewModelDelegate {
   90.10      var folderVM: FolderViewModel?
    91.1 --- a/pEpForiOS/UI/Folder/ViewModel/FolderSectionViewModel.swift	Wed Feb 20 11:00:07 2019 +0100
    91.2 +++ b/pEpForiOS/UI/Folder/ViewModel/FolderSectionViewModel.swift	Mon Mar 18 10:54:14 2019 +0100
    91.3 @@ -8,6 +8,7 @@
    91.4  
    91.5  import Foundation
    91.6  import MessageModel
    91.7 +import pEpIOSToolbox
    91.8  
    91.9  public class FolderSectionViewModel {
   91.10      public var collapsed = false
    92.1 --- a/pEpForiOS/UI/Handshake/CellsAndSections/HandshakePartnerTableViewCell.swift	Wed Feb 20 11:00:07 2019 +0100
    92.2 +++ b/pEpForiOS/UI/Handshake/CellsAndSections/HandshakePartnerTableViewCell.swift	Mon Mar 18 10:54:14 2019 +0100
    92.3 @@ -7,7 +7,7 @@
    92.4  //
    92.5  
    92.6  import UIKit
    92.7 -
    92.8 +import pEpIOSToolbox
    92.9  import MessageModel
   92.10  
   92.11  /**
    93.1 --- a/pEpForiOS/UI/Handshake/HandshakeViewController.swift	Wed Feb 20 11:00:07 2019 +0100
    93.2 +++ b/pEpForiOS/UI/Handshake/HandshakeViewController.swift	Mon Mar 18 10:54:14 2019 +0100
    93.3 @@ -7,7 +7,7 @@
    93.4  //
    93.5  
    93.6  import UIKit
    93.7 -
    93.8 +import pEpIOSToolbox
    93.9  import MessageModel
   93.10  
   93.11  class HandshakeViewController: BaseTableViewController {
    94.1 --- a/pEpForiOS/UI/Handshake/LanguageList/LanguageListViewController.swift	Wed Feb 20 11:00:07 2019 +0100
    94.2 +++ b/pEpForiOS/UI/Handshake/LanguageList/LanguageListViewController.swift	Mon Mar 18 10:54:14 2019 +0100
    94.3 @@ -7,6 +7,7 @@
    94.4  //
    94.5  
    94.6  import UIKit
    94.7 +import pEpIOSToolbox
    94.8  
    94.9  class LanguageListViewController: BaseTableViewController {
   94.10      let defaultCellReuseIdentifier = "LanguageListCell"
    95.1 --- a/pEpForiOS/UI/Handshake/ViewModel/HandshakePartnerTableViewCellViewModel.swift	Wed Feb 20 11:00:07 2019 +0100
    95.2 +++ b/pEpForiOS/UI/Handshake/ViewModel/HandshakePartnerTableViewCellViewModel.swift	Mon Mar 18 10:54:14 2019 +0100
    95.3 @@ -7,7 +7,7 @@
    95.4  //
    95.5  
    95.6  import Foundation
    95.7 -
    95.8 +import pEpIOSToolbox
    95.9  import MessageModel
   95.10  
   95.11  class HandshakePartnerTableViewCellViewModel {
    96.1 --- a/pEpForiOS/UI/Login/LoginViewController.swift	Wed Feb 20 11:00:07 2019 +0100
    96.2 +++ b/pEpForiOS/UI/Login/LoginViewController.swift	Mon Mar 18 10:54:14 2019 +0100
    96.3 @@ -7,6 +7,7 @@
    96.4  //
    96.5  
    96.6  import UIKit
    96.7 +import pEpIOSToolbox
    96.8  
    96.9  extension LoginViewController {
   96.10      enum LoginError: Error {
    97.1 --- a/pEpForiOS/UI/Login/ViewModel/LoginViewModel.swift	Wed Feb 20 11:00:07 2019 +0100
    97.2 +++ b/pEpForiOS/UI/Login/ViewModel/LoginViewModel.swift	Mon Mar 18 10:54:14 2019 +0100
    97.3 @@ -8,6 +8,7 @@
    97.4  
    97.5  import Foundation
    97.6  import MessageModel
    97.7 +import pEpIOSToolbox
    97.8  
    97.9  enum LoginCellType {
   97.10      case Text, Button
    98.1 --- a/pEpForiOS/UI/ManualLogin/ImapSetup/IMAPSettingsTableViewController.swift	Wed Feb 20 11:00:07 2019 +0100
    98.2 +++ b/pEpForiOS/UI/ManualLogin/ImapSetup/IMAPSettingsTableViewController.swift	Mon Mar 18 10:54:14 2019 +0100
    98.3 @@ -7,6 +7,7 @@
    98.4  //
    98.5  
    98.6  import UIKit
    98.7 +import pEpIOSToolbox
    98.8  
    98.9  extension UIAlertController {
   98.10      func setupActionFromConnectionTransport(_ transport: ConnectionTransport,
    99.1 --- a/pEpForiOS/UI/ManualLogin/InfoUserSettup/UserInfoTableViewController.swift	Wed Feb 20 11:00:07 2019 +0100
    99.2 +++ b/pEpForiOS/UI/ManualLogin/InfoUserSettup/UserInfoTableViewController.swift	Mon Mar 18 10:54:14 2019 +0100
    99.3 @@ -7,7 +7,7 @@
    99.4  //
    99.5  
    99.6  import UIKit
    99.7 -
    99.8 +import pEpIOSToolbox
    99.9  import MessageModel
   99.10  
   99.11  class UserInfoTableViewController: BaseTableViewController, TextfieldResponder, UITextFieldDelegate {
   100.1 --- a/pEpForiOS/UI/ManualLogin/SMTPSetup/SMTPSettingsTableViewController.swift	Wed Feb 20 11:00:07 2019 +0100
   100.2 +++ b/pEpForiOS/UI/ManualLogin/SMTPSetup/SMTPSettingsTableViewController.swift	Mon Mar 18 10:54:14 2019 +0100
   100.3 @@ -7,7 +7,7 @@
   100.4  //
   100.5  
   100.6  import UIKit
   100.7 -
   100.8 +import pEpIOSToolbox
   100.9  import MessageModel
  100.10  
  100.11  class SMTPSettingsTableViewController: BaseTableViewController, TextfieldResponder {
   101.1 --- a/pEpForiOS/UI/MoveToFolder/ViewModel/MoveToFolderViewModel.swift	Wed Feb 20 11:00:07 2019 +0100
   101.2 +++ b/pEpForiOS/UI/MoveToFolder/ViewModel/MoveToFolderViewModel.swift	Mon Mar 18 10:54:14 2019 +0100
   101.3 @@ -7,6 +7,7 @@
   101.4  //
   101.5  
   101.6  import Foundation
   101.7 +import pEpIOSToolbox
   101.8  import MessageModel
   101.9  
  101.10  let folderTypesNotAllowedToMoveTo = [FolderType.drafts, .sent]
   102.1 --- a/pEpForiOS/UI/Settings/Setting/AccountSettings/AccountSettingsTableViewController.swift	Wed Feb 20 11:00:07 2019 +0100
   102.2 +++ b/pEpForiOS/UI/Settings/Setting/AccountSettings/AccountSettingsTableViewController.swift	Mon Mar 18 10:54:14 2019 +0100
   102.3 @@ -8,6 +8,7 @@
   102.4  
   102.5  import UIKit
   102.6  import MessageModel
   102.7 +import pEpIOSToolbox
   102.8  
   102.9  class AccountSettingsTableViewController: BaseTableViewController, UIPickerViewDelegate,
  102.10  UIPickerViewDataSource, UITextFieldDelegate {
   103.1 --- a/pEpForiOS/UI/Settings/Setting/AccountSettings/ViewModel/AccountSettingsViewModel.swift	Wed Feb 20 11:00:07 2019 +0100
   103.2 +++ b/pEpForiOS/UI/Settings/Setting/AccountSettings/ViewModel/AccountSettingsViewModel.swift	Mon Mar 18 10:54:14 2019 +0100
   103.3 @@ -8,6 +8,7 @@
   103.4  
   103.5  import Foundation
   103.6  import MessageModel
   103.7 +import pEpIOSToolbox
   103.8  
   103.9  public class AccountSettingsViewModel {
  103.10      public struct ServerViewModel {
   104.1 --- a/pEpForiOS/UI/Settings/Setting/LogViewController.swift	Wed Feb 20 11:00:07 2019 +0100
   104.2 +++ b/pEpForiOS/UI/Settings/Setting/LogViewController.swift	Mon Mar 18 10:54:14 2019 +0100
   104.3 @@ -7,6 +7,7 @@
   104.4  //
   104.5  
   104.6  import UIKit
   104.7 +import pEpIOSToolbox
   104.8  
   104.9  class LogViewController: BaseViewController {
  104.10  
   105.1 --- a/pEpForiOS/UI/Settings/Setting/TrustedServerSetting/TrustedServerSettingsViewController.swift	Wed Feb 20 11:00:07 2019 +0100
   105.2 +++ b/pEpForiOS/UI/Settings/Setting/TrustedServerSetting/TrustedServerSettingsViewController.swift	Mon Mar 18 10:54:14 2019 +0100
   105.3 @@ -7,6 +7,7 @@
   105.4  //
   105.5  
   105.6  import UIKit
   105.7 +import pEpIOSToolbox
   105.8  
   105.9  class TrustedServerSettingsViewController: BaseTableViewController {
  105.10      var viewModel = TrustedServerSettingsViewModel()
   106.1 --- a/pEpForiOS/UI/Settings/Setting/TrustedServerSetting/TrustedServerSettingsViewModel.swift	Wed Feb 20 11:00:07 2019 +0100
   106.2 +++ b/pEpForiOS/UI/Settings/Setting/TrustedServerSetting/TrustedServerSettingsViewModel.swift	Mon Mar 18 10:54:14 2019 +0100
   106.3 @@ -8,6 +8,7 @@
   106.4  
   106.5  import Foundation
   106.6  import MessageModel
   106.7 +import pEpIOSToolbox
   106.8  
   106.9  struct TrustedServerSettingsViewModel {
  106.10      struct Row: Equatable {
   107.1 --- a/pEpForiOS/UI/Settings/SettingsTableViewController.swift	Wed Feb 20 11:00:07 2019 +0100
   107.2 +++ b/pEpForiOS/UI/Settings/SettingsTableViewController.swift	Mon Mar 18 10:54:14 2019 +0100
   107.3 @@ -7,6 +7,7 @@
   107.4  //
   107.5  
   107.6  import SwipeCellKit
   107.7 +import pEpIOSToolbox
   107.8  
   107.9  class SettingsTableViewController: BaseTableViewController, SwipeTableViewCellDelegate {
  107.10      static let storyboardId = "SettingsTableViewController"
   108.1 --- a/pEpForiOS/UI/Settings/ViewModel/SettingsCellViewModel.swift	Wed Feb 20 11:00:07 2019 +0100
   108.2 +++ b/pEpForiOS/UI/Settings/ViewModel/SettingsCellViewModel.swift	Mon Mar 18 10:54:14 2019 +0100
   108.3 @@ -8,6 +8,7 @@
   108.4  
   108.5  import Foundation
   108.6  import MessageModel
   108.7 +import pEpIOSToolbox
   108.8  
   108.9  extension SettingsCellViewModel {
  108.10      public enum SettingType {
   109.1 --- a/pEpForiOS/UI/SplitView/PrimarySplitViewController.swift	Wed Feb 20 11:00:07 2019 +0100
   109.2 +++ b/pEpForiOS/UI/SplitView/PrimarySplitViewController.swift	Mon Mar 18 10:54:14 2019 +0100
   109.3 @@ -7,6 +7,7 @@
   109.4  //
   109.5  
   109.6  import UIKit
   109.7 +import pEpIOSToolbox
   109.8  
   109.9  class PrimarySplitViewController: UISplitViewController, UISplitViewControllerDelegate {
  109.10      override func viewDidLoad() {
   110.1 --- a/pEpForiOS/UI/SplitView/PrimarySplitViewcontroller+ScreenComposerProtocol.swift	Wed Feb 20 11:00:07 2019 +0100
   110.2 +++ b/pEpForiOS/UI/SplitView/PrimarySplitViewcontroller+ScreenComposerProtocol.swift	Mon Mar 18 10:54:14 2019 +0100
   110.3 @@ -8,6 +8,7 @@
   110.4  
   110.5  import Foundation
   110.6  import MessageModel
   110.7 +import pEpIOSToolbox
   110.8  
   110.9  extension PrimarySplitViewController: ScreenComposerProtocol {
  110.10      func emailListViewModel(_ emailListViewModel: EmailListViewModel,
   111.1 --- a/pEpForiOS/UI/Thread/Cells/FullMessageCell.swift	Wed Feb 20 11:00:07 2019 +0100
   111.2 +++ b/pEpForiOS/UI/Thread/Cells/FullMessageCell.swift	Mon Mar 18 10:54:14 2019 +0100
   111.3 @@ -9,6 +9,7 @@
   111.4  import UIKit
   111.5  import MessageModel
   111.6  import SwipeCellKit
   111.7 +import pEpIOSToolbox
   111.8  
   111.9  class FullMessageCell: SwipeTableViewCell,
  111.10      MessageViewModelConfigurable,
   112.1 --- a/pEpForiOS/UI/Thread/ThreadViewController+SegueHandlerType.swift	Wed Feb 20 11:00:07 2019 +0100
   112.2 +++ b/pEpForiOS/UI/Thread/ThreadViewController+SegueHandlerType.swift	Mon Mar 18 10:54:14 2019 +0100
   112.3 @@ -7,6 +7,8 @@
   112.4  //
   112.5  
   112.6  import Foundation
   112.7 +import pEpIOSToolbox
   112.8 +
   112.9  extension ThreadViewController: SegueHandlerType {
  112.10  
  112.11      enum SegueIdentifier: String {
   113.1 --- a/pEpForiOS/UI/Thread/ThreadViewController.swift	Wed Feb 20 11:00:07 2019 +0100
   113.2 +++ b/pEpForiOS/UI/Thread/ThreadViewController.swift	Mon Mar 18 10:54:14 2019 +0100
   113.3 @@ -7,6 +7,7 @@
   113.4  //
   113.5  
   113.6  import UIKit
   113.7 +import pEpIOSToolbox
   113.8  
   113.9  class ThreadViewController: BaseViewController {
  113.10      var barItems: [UIBarButtonItem]?
   114.1 --- a/pEpForiOS/UI/Thread/Transitions/DetailCellSegue.swift	Wed Feb 20 11:00:07 2019 +0100
   114.2 +++ b/pEpForiOS/UI/Thread/Transitions/DetailCellSegue.swift	Mon Mar 18 10:54:14 2019 +0100
   114.3 @@ -7,6 +7,7 @@
   114.4  //
   114.5  
   114.6  import UIKit
   114.7 +import pEpIOSToolbox
   114.8  
   114.9  class DetailCellSegue: UIStoryboardSegue {
  114.10  
   115.1 --- a/pEpForiOS/UI/Thread/ViewModel/ThreadedEmailViewModelDelegate.swift	Wed Feb 20 11:00:07 2019 +0100
   115.2 +++ b/pEpForiOS/UI/Thread/ViewModel/ThreadedEmailViewModelDelegate.swift	Mon Mar 18 10:54:14 2019 +0100
   115.3 @@ -7,6 +7,8 @@
   115.4  //
   115.5  
   115.6  import Foundation
   115.7 +import pEpIOSToolbox
   115.8 +
   115.9  protocol ThreadedEmailViewModelDelegate: class, TableViewUpdate {
  115.10      func emailViewModel(viewModel: ThreadedEmailViewModel, didInsertDataAt index: Int)
  115.11      func emailViewModel(viewModel: ThreadedEmailViewModel, didUpdateDataAt index: Int)
   116.1 --- a/pEpForiOS/UI/Util/AddToContactsViewController/AddToContactsViewController.swift	Wed Feb 20 11:00:07 2019 +0100
   116.2 +++ b/pEpForiOS/UI/Util/AddToContactsViewController/AddToContactsViewController.swift	Mon Mar 18 10:54:14 2019 +0100
   116.3 @@ -8,6 +8,7 @@
   116.4  
   116.5  import Foundation
   116.6  import ContactsUI
   116.7 +import pEpIOSToolbox
   116.8  
   116.9  /// Represents ContactsUI for "add a contact" to the system address book
  116.10  class AddToContactsViewController: BaseViewController {
   117.1 --- a/pEpForiOS/UI/Util/BaseTableViewController.swift	Wed Feb 20 11:00:07 2019 +0100
   117.2 +++ b/pEpForiOS/UI/Util/BaseTableViewController.swift	Mon Mar 18 10:54:14 2019 +0100
   117.3 @@ -7,6 +7,7 @@
   117.4  //
   117.5  
   117.6  import UIKit
   117.7 +import pEpIOSToolbox
   117.8  
   117.9  class BaseTableViewController: UITableViewController, ErrorPropagatorSubscriber {
  117.10      private var _appConfig: AppConfig?
   118.1 --- a/pEpForiOS/UI/Util/BaseViewController.swift	Wed Feb 20 11:00:07 2019 +0100
   118.2 +++ b/pEpForiOS/UI/Util/BaseViewController.swift	Mon Mar 18 10:54:14 2019 +0100
   118.3 @@ -7,6 +7,7 @@
   118.4  //
   118.5  
   118.6  import UIKit
   118.7 +import pEpIOSToolbox
   118.8  
   118.9  class BaseViewController: UIViewController, ErrorPropagatorSubscriber {
  118.10      private var _appConfig: AppConfig?
   119.1 --- a/pEpForiOS/UI/Util/CGImageSource+Extension.swift	Wed Feb 20 11:00:07 2019 +0100
   119.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   119.3 @@ -1,130 +0,0 @@
   119.4 -//
   119.5 -//  CGImageSource+Extension.swift
   119.6 -//  pEp
   119.7 -//
   119.8 -//  Created by Dirk Zimmermann on 15.05.18.
   119.9 -//  Copyright © 2018 p≡p Security S.A. All rights reserved.
  119.10 -//
  119.11 -
  119.12 -import Foundation
  119.13 -
  119.14 -extension CGImageSource {
  119.15 -    /**
  119.16 -     Every image contained in this source interpreted as animation frame,
  119.17 -     together with its duration.
  119.18 -     */
  119.19 -    struct AnimationFrame {
  119.20 -        /** The image representing this frame */
  119.21 -        let cgImage: CGImage
  119.22 -
  119.23 -        /** The duration of that frame, in seconds */
  119.24 -        let durationSeconds: Double
  119.25 -
  119.26 -        /** The duration of that frame, in deciseconds */
  119.27 -        let durationDecis: Int64
  119.28 -
  119.29 -        /**
  119.30 -         Greatest common denominator of two `Int64`s.
  119.31 -         */
  119.32 -        static func gcd(int641: Int64, int642: Int64) -> Int64 {
  119.33 -            if int641 < int642 {
  119.34 -                return gcd(int641: int642, int642: int641)
  119.35 -            }
  119.36 -            var num1 = int641
  119.37 -            var num2 = int642
  119.38 -            while true {
  119.39 -                let r = num1 % num2
  119.40 -                if r == 0 {
  119.41 -                    return num2
  119.42 -                }
  119.43 -                num1 = num2
  119.44 -                num2 = r
  119.45 -            }
  119.46 -        }
  119.47 -
  119.48 -        /**
  119.49 -         Greatest common denominator of an array of `Int64`s.
  119.50 -         */
  119.51 -        static func gcd(int64s: [Int64]) -> Int64? {
  119.52 -            if int64s.isEmpty || int64s.count < 2 {
  119.53 -                return nil
  119.54 -            }
  119.55 -
  119.56 -            var theGcd = int64s[0]
  119.57 -            for value in int64s {
  119.58 -                theGcd = gcd(int641: value, int642: theGcd)
  119.59 -            }
  119.60 -
  119.61 -            return theGcd
  119.62 -        }
  119.63 -
  119.64 -        /**
  119.65 -         Greatest common denominator of an array of `Int64`s.
  119.66 -         */
  119.67 -        static func gcdDurationDecis(animationFrames: [AnimationFrame]) -> Int64? {
  119.68 -            let theInts = animationFrames.map { return $0.durationDecis }
  119.69 -            return gcd(int64s: theInts)
  119.70 -        }
  119.71 -    }
  119.72 -
  119.73 -    /**
  119.74 -     Determines the time of a contained frame, in seconds.
  119.75 -     - Returns: The time the image at the given index should be shown, in milliseconds.
  119.76 -     - Note: The index is not checked for validity.
  119.77 -     */
  119.78 -    func frameTimeSeconds(cgImageSource: CGImageSource, atIndex index: Int) -> Double {
  119.79 -        var theFrameTimeSeconds: Double = 0
  119.80 -
  119.81 -        if
  119.82 -            let properties: NSDictionary = CGImageSourceCopyPropertiesAtIndex(
  119.83 -                cgImageSource, index, nil),
  119.84 -            let gifProperties = properties.object(forKey: kCGImagePropertyGIFDictionary)
  119.85 -                as? NSDictionary
  119.86 -        {
  119.87 -            if let numDelayUnclamped = gifProperties.object(
  119.88 -                forKey: kCGImagePropertyGIFUnclampedDelayTime) as? NSNumber {
  119.89 -                theFrameTimeSeconds = numDelayUnclamped.doubleValue
  119.90 -            }
  119.91 -
  119.92 -            if theFrameTimeSeconds == 0,
  119.93 -                let numDelayClamped = gifProperties.object(forKey: kCGImagePropertyGIFDelayTime)
  119.94 -                    as? NSNumber {
  119.95 -                theFrameTimeSeconds = numDelayClamped.doubleValue
  119.96 -                if theFrameTimeSeconds <= 0.050 { // 50 milliseconds or less?
  119.97 -                    theFrameTimeSeconds = 0.1 // clamp to 100 milliseconds
  119.98 -                }
  119.99 -            }
 119.100 -        }
 119.101 -
 119.102 -        return theFrameTimeSeconds
 119.103 -    }
 119.104 -
 119.105 -    /**
 119.106 -     Looks up the image at the given index.
 119.107 -     - Returns: The `CGImage` contained at the given index.
 119.108 -     - Note: The index is not checked for validity.
 119.109 -     */
 119.110 -    func cgImage(atIndex: Int) -> CGImage? {
 119.111 -        return CGImageSourceCreateImageAtIndex(self, atIndex, nil)
 119.112 -    }
 119.113 -
 119.114 -    /**
 119.115 -     Delivers the `AnimationFrame`s.
 119.116 -     - Returns: All contained `AnimationFrame`s
 119.117 -     */
 119.118 -    func animationFrames() -> [AnimationFrame] {
 119.119 -        var animationFrames = [AnimationFrame]()
 119.120 -        let imgCount = CGImageSourceGetCount(self)
 119.121 -        for index in 0..<imgCount {
 119.122 -            if let cgImg = cgImage(atIndex: index) {
 119.123 -                let frameDurationSeconds = frameTimeSeconds(cgImageSource: self, atIndex: index)
 119.124 -                let frameDurationDecis = Int64((frameDurationSeconds * 100).rounded())
 119.125 -                animationFrames.append(AnimationFrame(
 119.126 -                    cgImage: cgImg,
 119.127 -                    durationSeconds: frameDurationSeconds,
 119.128 -                    durationDecis: frameDurationDecis))
 119.129 -            }
 119.130 -        }
 119.131 -        return animationFrames
 119.132 -    }
 119.133 -}
   120.1 --- a/pEpForiOS/UI/Util/CGRect+Util.swift	Wed Feb 20 11:00:07 2019 +0100
   120.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   120.3 @@ -1,47 +0,0 @@
   120.4 -//
   120.5 -//  CGRect+Util.swift
   120.6 -//  pEpForiOS
   120.7 -//
   120.8 -//  Created by Dirk Zimmermann on 11.04.17.
   120.9 -//  Copyright © 2017 p≡p Security S.A. All rights reserved.
  120.10 -//
  120.11 -
  120.12 -import UIKit
  120.13 -
  120.14 -extension CGRect {
  120.15 -    static func rectAround(center: CGPoint, width: CGFloat, height: CGFloat) -> CGRect {
  120.16 -        let origin = CGPoint(x: round(center.x - width / 2), y: round(center.y - height / 2))
  120.17 -        return CGRect(origin: origin, size: CGSize(width: width, height: height))
  120.18 -    }
  120.19 -
  120.20 -    /**
  120.21 -     - Returns: A CGRect in the center of the receiver,
  120.22 -     with (width, height) <= (maxWidth, maxWidth).
  120.23 -     */
  120.24 -    func centerRect(maxWidth: CGFloat) -> CGRect {
  120.25 -        let r = standardized
  120.26 -        var theWidth = maxWidth
  120.27 -        theWidth = min(theWidth, min(r.width, r.height))
  120.28 -
  120.29 -        let widthR = round(r.width / 2)
  120.30 -        let centerX = r.origin.x + widthR
  120.31 -
  120.32 -        let heightR = round(r.height / 2)
  120.33 -        let centerY = r.origin.y + heightR
  120.34 -
  120.35 -        let center = CGPoint(x: centerX, y: centerY)
  120.36 -
  120.37 -        let width2 = round(theWidth / 2)
  120.38 -        let origX = center.x - width2
  120.39 -        let origY = center.y - width2
  120.40 -        let orig = CGPoint(x: origX, y: origY)
  120.41 -
  120.42 -        return CGRect(origin: orig, size: CGSize(width: theWidth, height: theWidth))
  120.43 -    }
  120.44 -
  120.45 -    static public func rect(withWidth width: CGFloat, ratioOf size: CGSize) -> CGRect {
  120.46 -        let fixRatio = size.width / size.height
  120.47 -        let newHeight = width / fixRatio
  120.48 -        return CGRect(x: 0, y: 0, width: width, height: newHeight)
  120.49 -    }
  120.50 -}
   121.1 --- a/pEpForiOS/UI/Util/CGSize+Extension.swift	Wed Feb 20 11:00:07 2019 +0100
   121.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   121.3 @@ -1,23 +0,0 @@
   121.4 -//
   121.5 -//  CGSize+Extension.swift
   121.6 -//  pEpForiOS
   121.7 -//
   121.8 -//  Created by Dirk Zimmermann on 24.04.17.
   121.9 -//  Copyright © 2017 p≡p Security S.A. All rights reserved.
  121.10 -//
  121.11 -
  121.12 -import UIKit
  121.13 -
  121.14 -extension CGSize {
  121.15 -    /**
  121.16 -     Default size for avatar images. Should also match storyboard sizes.
  121.17 -     */
  121.18 -    public static let defaultAvatarSize = CGSize(width: 48, height: 48)
  121.19 -
  121.20 -    /**
  121.21 -     Default size for pEp rating image in avatar images.
  121.22 -     Related with `defaultAvatarSize`, and should be smaller.
  121.23 -     Should also match storyboard sizes.
  121.24 -     */
  121.25 -    public static let defaultAvatarPEPStatusSize = CGSize(width: 20, height: 20)
  121.26 -}
   122.1 --- a/pEpForiOS/UI/Util/CredentialTextField.swift	Wed Feb 20 11:00:07 2019 +0100
   122.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   122.3 @@ -1,35 +0,0 @@
   122.4 -//
   122.5 -//  CredentialTextField.swift
   122.6 -//
   122.7 -//
   122.8 -//  Created by Miguel Berrocal Gómez on 09/07/2018.
   122.9 -//
  122.10 -
  122.11 -import UIKit
  122.12 -
  122.13 -@IBDesignable
  122.14 -class CredentialTextField: UITextField {
  122.15 -
  122.16 -    @IBInspectable var borderColor: UIColor? {
  122.17 -        didSet {
  122.18 -            layer.borderColor = borderColor?.cgColor
  122.19 -        }
  122.20 -    }
  122.21 -
  122.22 -    @IBInspectable var borderWidth: CGFloat = 0 {
  122.23 -        didSet {
  122.24 -            layer.borderWidth = borderWidth
  122.25 -        }
  122.26 -    }
  122.27 -
  122.28 -    @IBInspectable var placeholderColor: UIColor {
  122.29 -        get {
  122.30 -            return attributedPlaceholder?.attribute(.foregroundColor, at: 0, effectiveRange: nil) as? UIColor ?? .clear
  122.31 -        }
  122.32 -        set {
  122.33 -            guard let attributedPlaceholder = attributedPlaceholder else { return }
  122.34 -            let attributes: [NSAttributedStringKey: UIColor] = [.foregroundColor: newValue]
  122.35 -            self.attributedPlaceholder = NSAttributedString(string: attributedPlaceholder.string, attributes: attributes)
  122.36 -        }
  122.37 -    }
  122.38 -}
   123.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   123.2 +++ b/pEpForiOS/UI/Util/Extensions/UIAlertController+Extension.swift	Mon Mar 18 10:54:14 2019 +0100
   123.3 @@ -0,0 +1,33 @@
   123.4 +//
   123.5 +//  UIAlertController+Extension.swift
   123.6 +//  pEp
   123.7 +//
   123.8 +//  Created by Dirk Zimmermann on 10.05.18.
   123.9 +//  Copyright © 2018 p≡p Security S.A. All rights reserved.
  123.10 +//
  123.11 +
  123.12 +import Foundation
  123.13 +
  123.14 +import MessageModel
  123.15 +
  123.16 +extension UIAlertController {
  123.17 +    public func action(_ title: String,
  123.18 +                       _ style: UIAlertActionStyle = .default,
  123.19 +                       _ closure: (() -> ())? = nil) ->  UIAlertAction {
  123.20 +        return UIAlertAction(title: title, style: style) { (action) in
  123.21 +            if let clos = closure {
  123.22 +                clos()
  123.23 +            }
  123.24 +        }
  123.25 +    }
  123.26 +
  123.27 +    public static func pEpAlertController(
  123.28 +        title: String? = nil,
  123.29 +        message: String? = nil,
  123.30 +        preferredStyle: UIAlertControllerStyle = .actionSheet) -> UIAlertController {
  123.31 +        let alertCtrl = UIAlertController(title: title, message: message,
  123.32 +                                          preferredStyle: preferredStyle)
  123.33 +        alertCtrl.view.tintColor = .pEpGreen
  123.34 +        return alertCtrl
  123.35 +    }
  123.36 +}
   124.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   124.2 +++ b/pEpForiOS/UI/Util/Extensions/UIBarButtonItem+Extension.swift	Mon Mar 18 10:54:14 2019 +0100
   124.3 @@ -0,0 +1,18 @@
   124.4 +//
   124.5 +//  UIBarButtonItem+Extension.swift
   124.6 +//  pEp
   124.7 +//
   124.8 +//  Created by Xavier Algarra on 11/07/2018.
   124.9 +//  Copyright © 2018 p≡p Security S.A. All rights reserved.
  124.10 +//
  124.11 +
  124.12 +import Foundation
  124.13 +import UIKit
  124.14 +
  124.15 +extension UIBarButtonItem {
  124.16 +    public static func getPEPButton(action: Selector, target: Any) -> UIBarButtonItem {
  124.17 +        let img = UIImage(named: "icon-settings")
  124.18 +        let pEpButton = UIBarButtonItem(image: img, style: .plain, target: target, action: action)
  124.19 +        return pEpButton
  124.20 +    }
  124.21 +}
   125.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   125.2 +++ b/pEpForiOS/UI/Util/Extensions/UIButton+Extension.swift	Mon Mar 18 10:54:14 2019 +0100
   125.3 @@ -0,0 +1,59 @@
   125.4 +//
   125.5 +//  UIButton+Extension.swift
   125.6 +//  pEpForiOS
   125.7 +//
   125.8 +//  Created by Dirk Zimmermann on 20.04.17.
   125.9 +//  Copyright © 2017 p≡p Security S.A. All rights reserved.
  125.10 +//
  125.11 +
  125.12 +import UIKit
  125.13 +
  125.14 +extension UIButton {
  125.15 +    /**
  125.16 +     Makes the button the typical look for a pEp button used in the handshake dialogs.
  125.17 +     */
  125.18 +    public func pEpIfyForTrust(backgroundColor: UIColor, textColor: UIColor) {
  125.19 +        titleLabel?.numberOfLines = 0
  125.20 +        titleLabel?.lineBreakMode = .byWordWrapping
  125.21 +        titleLabel?.textAlignment = .center
  125.22 +
  125.23 +        self.backgroundColor = backgroundColor
  125.24 +        setTitleColor(textColor, for: .normal)
  125.25 +        layer.cornerRadius = 2
  125.26 +        let insetV: CGFloat = 15
  125.27 +        let insetH: CGFloat = 15
  125.28 +        contentEdgeInsets = UIEdgeInsets(top: insetV, left: insetH, bottom: insetV, right: insetH)
  125.29 +    }
  125.30 +
  125.31 +    public func convertToLoginButton(placeholder: String) {
  125.32 +        self.backgroundColor = UIColor.clear
  125.33 +        self.tintColor = UIColor.pEpGreen
  125.34 +        self.setTitle(placeholder, for: .normal)
  125.35 +    }
  125.36 +
  125.37 +    /**
  125.38 +     Does the content fit the button bounds?
  125.39 +     */
  125.40 +    public func contentFitsWidth() -> Bool {
  125.41 +        let iSize = intrinsicContentSize
  125.42 +        let actSize = bounds.size
  125.43 +        return iSize.width < actSize.width
  125.44 +    }
  125.45 +}
  125.46 +
  125.47 +public class HandshakeButton: UIButton {
  125.48 +
  125.49 +    public func roundCorners(corners: UIRectCorner, radius: CGFloat){
  125.50 +        clipsToBounds = true
  125.51 +        layer.cornerRadius = 0
  125.52 +        let maskPath = UIBezierPath(roundedRect: bounds,
  125.53 +                                    byRoundingCorners: corners,
  125.54 +                                    cornerRadii: CGSize(width: radius, height: radius))
  125.55 +        let maskLayer = CAShapeLayer()
  125.56 +        maskLayer.bounds = frame
  125.57 +        maskLayer.position = center
  125.58 +        maskLayer.path = maskPath.cgPath
  125.59 +
  125.60 +        layer.mask = maskLayer
  125.61 +    }
  125.62 +}
   126.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   126.2 +++ b/pEpForiOS/UI/Util/Extensions/UIImageView+Extension.swift	Mon Mar 18 10:54:14 2019 +0100
   126.3 @@ -0,0 +1,37 @@
   126.4 +//
   126.5 +//  UIImageView+Extension.swift
   126.6 +//  pEpForiOS
   126.7 +//
   126.8 +//  Created by Dirk Zimmermann on 18.04.17.
   126.9 +//  Copyright © 2017 p≡p Security S.A. All rights reserved.
  126.10 +//
  126.11 +
  126.12 +import UIKit
  126.13 +
  126.14 +extension UIImageView {
  126.15 +    /**
  126.16 +     - Returns: The aspect ratio, like 16:9, as a float. That is the factor you
  126.17 +     have to multiply the height and receive the width.
  126.18 +     */
  126.19 +    public func aspectRatio() -> CGFloat {
  126.20 +        return bounds.width / bounds.height
  126.21 +    }
  126.22 +
  126.23 +    /**
  126.24 +     Sets up the necessary constraints to have the height always adopt to the width,
  126.25 +     while maintaining the correct aspect ratio.
  126.26 +     */
  126.27 +    public func activateAspectRatioConstraint() {
  126.28 +        let factor = 1 / aspectRatio()
  126.29 +        heightAnchor.constraint(equalTo: widthAnchor, multiplier: factor).isActive = true
  126.30 +    }
  126.31 +
  126.32 +    /**
  126.33 +     Gives the image the uniform look of a contact image.
  126.34 +     */
  126.35 +    public func applyContactImageCornerRadius() {
  126.36 +        let theWidth = bounds.size.width
  126.37 +        layer.cornerRadius = round(theWidth / 10)
  126.38 +        layer.masksToBounds = true
  126.39 +    }
  126.40 +}
   127.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   127.2 +++ b/pEpForiOS/UI/Util/Extensions/UINavigationController+Extensions.swift	Mon Mar 18 10:54:14 2019 +0100
   127.3 @@ -0,0 +1,15 @@
   127.4 +//
   127.5 +//  UINavigationController+Extensions.swift
   127.6 +//  pEpForiOS
   127.7 +//
   127.8 +//  Created by Andreas Buff on 23.08.17.
   127.9 +//  Copyright © 2017 p≡p Security S.A. All rights reserved.
  127.10 +//
  127.11 +
  127.12 +import UIKit
  127.13 +
  127.14 +extension UINavigationController {
  127.15 +    public var rootViewController : UIViewController? {
  127.16 +        return viewControllers.first
  127.17 +    }
  127.18 +}
   128.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   128.2 +++ b/pEpForiOS/UI/Util/Extensions/UITableView+Extension.swift	Mon Mar 18 10:54:14 2019 +0100
   128.3 @@ -0,0 +1,33 @@
   128.4 +//
   128.5 +//  UITableView+Extension.swift
   128.6 +//  pEpForiOS
   128.7 +//
   128.8 +//  Created by Dirk Zimmermann on 24.04.17.
   128.9 +//  Copyright © 2017 p≡p Security S.A. All rights reserved.
  128.10 +//
  128.11 +
  128.12 +import UIKit
  128.13 +import pEpIOSToolbox
  128.14 +
  128.15 +extension UITableView {
  128.16 +    /**
  128.17 +     This magic code should trigger a height refresh for table cells,
  128.18 +     with an optional block to execute after the size got updated, but outside of
  128.19 +     the no-animation block.
  128.20 +     */
  128.21 +    public final func updateSize(andExecuteBlock: (() -> Void)? = nil) {
  128.22 +        UIView.performWithoutAnimation {
  128.23 +            beginUpdates()
  128.24 +            endUpdates()
  128.25 +            if let theBlock = andExecuteBlock {
  128.26 +                GCD.onMain {
  128.27 +                    theBlock()
  128.28 +                }
  128.29 +            }
  128.30 +        }
  128.31 +    }
  128.32 +}
  128.33 +
  128.34 +public protocol TableViewUpdate {
  128.35 +    func updateView()
  128.36 +}
   129.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   129.2 +++ b/pEpForiOS/UI/Util/Extensions/UITextField+Extension.swift	Mon Mar 18 10:54:14 2019 +0100
   129.3 @@ -0,0 +1,41 @@
   129.4 +//
   129.5 +//  UITextField+Extension.swift
   129.6 +//  pEpForiOS
   129.7 +//
   129.8 +//  Created by Xavier Algarra on 25/04/2017.
   129.9 +//  Copyright © 2017 p≡p Security S.A. All rights reserved.
  129.10 +//
  129.11 +
  129.12 +import UIKit
  129.13 +
  129.14 +extension UITextField {
  129.15 +    public func convertToLoginField(placeholder: String, delegate: UITextFieldDelegate) {
  129.16 +        // common properties
  129.17 +        self.delegate = delegate
  129.18 +        self.placeholder = placeholder
  129.19 +
  129.20 +        // properties divided between enabled/disabled
  129.21 +        if isEnabled {
  129.22 +            enableLoginField()
  129.23 +        } else {
  129.24 +            disableLoginField()
  129.25 +        }
  129.26 +    }
  129.27 +
  129.28 +    public func disableLoginField() {
  129.29 +        enableOrDisableLoginField(enable: false)
  129.30 +    }
  129.31 +
  129.32 +    public func enableLoginField() {
  129.33 +        enableOrDisableLoginField(enable: true)
  129.34 +    }
  129.35 +
  129.36 +    public func enableOrDisableLoginField(enable: Bool) {
  129.37 +        let theColor = enable ? UIColor.white : UIColor.gray
  129.38 +        self.textColor = theColor
  129.39 +        if let ph = placeholder {
  129.40 +            self.attributedPlaceholder = NSAttributedString(
  129.41 +                string: ph, attributes: [NSAttributedString.Key.foregroundColor: theColor])
  129.42 +        }
  129.43 +    }
  129.44 +}
   130.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   130.2 +++ b/pEpForiOS/UI/Util/Extensions/UIView+Autolayout.swift	Mon Mar 18 10:54:14 2019 +0100
   130.3 @@ -0,0 +1,32 @@
   130.4 +//
   130.5 +//  UIView+Autolayout.swift
   130.6 +//  pEp
   130.7 +//
   130.8 +//  Created by Andreas Buff on 09.03.18.
   130.9 +//  Copyright © 2018 p≡p Security S.A. All rights reserved.
  130.10 +//
  130.11 +
  130.12 +import UIKit
  130.13 +import pEpIOSToolbox
  130.14 +
  130.15 +extension UIView {
  130.16 +    /// Sets up constraints to always stay the same size as the superview.
  130.17 +    public func fullSizeInSuperView() {
  130.18 +        guard let superview = self.superview else {
  130.19 +            Logger.frontendLogger.errorAndCrash("No superview")
  130.20 +            return
  130.21 +        }
  130.22 +
  130.23 +        self.translatesAutoresizingMaskIntoConstraints = false
  130.24 +        superview.addConstraints(NSLayoutConstraint.constraints(
  130.25 +            withVisualFormat: "H:|-0-[subview]-0-|",
  130.26 +            options: .directionLeadingToTrailing,
  130.27 +            metrics: nil,
  130.28 +            views: ["subview": self]))
  130.29 +        superview.addConstraints(NSLayoutConstraint.constraints(
  130.30 +            withVisualFormat: "V:|-0-[subview]-0-|",
  130.31 +            options: .directionLeadingToTrailing,
  130.32 +            metrics: nil,
  130.33 +            views: ["subview": self]))
  130.34 +    }
  130.35 +}
   131.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   131.2 +++ b/pEpForiOS/UI/Util/Extensions/UIView+Util.swift	Mon Mar 18 10:54:14 2019 +0100
   131.3 @@ -0,0 +1,61 @@
   131.4 +//
   131.5 +//  UIView+Util.swift
   131.6 +//  pEpForiOS
   131.7 +//
   131.8 +//  Created by Dirk Zimmermann on 10.04.17.
   131.9 +//  Copyright © 2017 p≡p Security S.A. All rights reserved.
  131.10 +//
  131.11 +
  131.12 +import UIKit
  131.13 +
  131.14 +/**
  131.15 + A piece of data for tracking the "busyness" of a view.
  131.16 + */
  131.17 +public struct ViewBusyState {
  131.18 +    let views: [UIView]
  131.19 +}
  131.20 +
  131.21 +extension UIView {
  131.22 +    func dumpConstraints(axis: NSLayoutConstraint.Axis) {
  131.23 +        let constrs = constraintsAffectingLayout(for: axis)
  131.24 +        if constrs.isEmpty {
  131.25 +            print("no constraints")
  131.26 +        }
  131.27 +        for con in constrs {
  131.28 +            print("\(con)")
  131.29 +        }
  131.30 +    }
  131.31 +
  131.32 +    /**
  131.33 +     Marks the view as busy, e.g. by adding some spinning animation view.
  131.34 +     */
  131.35 +    public func displayAsBusy() -> ViewBusyState {
  131.36 +        let darkView = UIView()
  131.37 +        darkView.translatesAutoresizingMaskIntoConstraints = false
  131.38 +        darkView.backgroundColor = .black
  131.39 +        darkView.alpha = 0.5
  131.40 +        addSubview(darkView)
  131.41 +        darkView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
  131.42 +        darkView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
  131.43 +        darkView.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
  131.44 +        darkView.heightAnchor.constraint(equalTo: heightAnchor).isActive = true
  131.45 +
  131.46 +        let activityView = UIActivityIndicatorView()
  131.47 +        activityView.activityIndicatorViewStyle = .whiteLarge
  131.48 +        activityView.translatesAutoresizingMaskIntoConstraints = false
  131.49 +        darkView.addSubview(activityView)
  131.50 +        activityView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
  131.51 +        activityView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
  131.52 +        activityView.startAnimating()
  131.53 +        return ViewBusyState(views: [darkView])
  131.54 +    }
  131.55 +
  131.56 +    /**
  131.57 +     Marks the given view as not busy anymore.
  131.58 +     */
  131.59 +    public func stopDisplayingAsBusy(viewBusyState: ViewBusyState) {
  131.60 +        for v in viewBusyState.views {
  131.61 +            v.removeFromSuperview()
  131.62 +        }
  131.63 +    }
  131.64 +}
   132.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   132.2 +++ b/pEpForiOS/UI/Util/Extensions/UIViewController+Extension.swift	Mon Mar 18 10:54:14 2019 +0100
   132.3 @@ -0,0 +1,42 @@
   132.4 +//
   132.5 +//  UIViewController+Extension.swift
   132.6 +//  pEpForiOS
   132.7 +//
   132.8 +//  Created by Dirk Zimmermann on 17/02/2017.
   132.9 +//  Copyright © 2017 p≡p Security S.A. All rights reserved.
  132.10 +//
  132.11 +
  132.12 +import Foundation
  132.13 +import UIKit
  132.14 +
  132.15 +extension UIViewController {
  132.16 +    var isModalViewCurrentlyShown: Bool {
  132.17 +        return presentedViewController != nil
  132.18 +    }
  132.19 +
  132.20 +    @discardableResult func showPepRating(pEpRating: PEP_rating?, pEpProtection: Bool = true) -> UIView? {
  132.21 +        if let img = pEpRating?.pEpColor().statusIcon(enabled: pEpProtection) {
  132.22 +            // according to apple's design guidelines ('Hit Targets'):
  132.23 +            // https://developer.apple.com/design/tips/
  132.24 +            let minimumHittestDimension: CGFloat = 44
  132.25 +
  132.26 +            let minimumImageWidth = max(minimumHittestDimension / 2, img.size.width)
  132.27 +            let img2 = img.resized(newWidth: minimumImageWidth)
  132.28 +            let v = UIImageView(image: img2)
  132.29 +            v.contentMode = .center // DON'T stretch the image, leave it at original size
  132.30 +
  132.31 +            // try to make the hit area of the icon a minimum of 44x44
  132.32 +            let desiredHittestDimension: CGFloat = min(
  132.33 +                minimumHittestDimension,
  132.34 +                navigationController?.navigationBar.frame.size.height ?? minimumHittestDimension)
  132.35 +            v.bounds.size = CGSize(width: desiredHittestDimension, height: desiredHittestDimension)
  132.36 +
  132.37 +            navigationItem.titleView = v
  132.38 +            v.isUserInteractionEnabled = true
  132.39 +            return v
  132.40 +        } else {
  132.41 +            navigationItem.titleView = nil
  132.42 +            return nil
  132.43 +        }
  132.44 +    }
  132.45 +}
   133.1 --- a/pEpForiOS/UI/Util/InfoPlist.swift	Wed Feb 20 11:00:07 2019 +0100
   133.2 +++ b/pEpForiOS/UI/Util/InfoPlist.swift	Mon Mar 18 10:54:14 2019 +0100
   133.3 @@ -7,6 +7,7 @@
   133.4  //
   133.5  
   133.6  import Foundation
   133.7 +import pEpIOSToolbox
   133.8  
   133.9  struct InfoPlist {
  133.10      static private var infoDictMainBundle: [String:Any]? {
   134.1 --- a/pEpForiOS/UI/Util/SecureWebViewController/CidHandler.swift	Wed Feb 20 11:00:07 2019 +0100
   134.2 +++ b/pEpForiOS/UI/Util/SecureWebViewController/CidHandler.swift	Mon Mar 18 10:54:14 2019 +0100
   134.3 @@ -8,6 +8,7 @@
   134.4  
   134.5  import WebKit
   134.6  import MessageModel
   134.7 +import pEpIOSToolbox
   134.8  
   134.9  @available(iOS, introduced: 11.0)
  134.10  
   135.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   135.2 +++ b/pEpForiOS/UI/Util/SecureWebViewController/CredentialTextField.swift	Mon Mar 18 10:54:14 2019 +0100
   135.3 @@ -0,0 +1,35 @@
   135.4 +//
   135.5 +//  CredentialTextField.swift
   135.6 +//
   135.7 +//
   135.8 +//  Created by Miguel Berrocal Gómez on 09/07/2018.
   135.9 +//
  135.10 +
  135.11 +import UIKit
  135.12 +
  135.13 +@IBDesignable
  135.14 +class CredentialTextField: UITextField {
  135.15 +
  135.16 +    @IBInspectable var borderColor: UIColor? {
  135.17 +        didSet {
  135.18 +            layer.borderColor = borderColor?.cgColor
  135.19 +        }
  135.20 +    }
  135.21 +
  135.22 +    @IBInspectable var borderWidth: CGFloat = 0 {
  135.23 +        didSet {
  135.24 +            layer.borderWidth = borderWidth
  135.25 +        }
  135.26 +    }
  135.27 +
  135.28 +    @IBInspectable var placeholderColor: UIColor {
  135.29 +        get {
  135.30 +            return attributedPlaceholder?.attribute(.foregroundColor, at: 0, effectiveRange: nil) as? UIColor ?? .clear
  135.31 +        }
  135.32 +        set {
  135.33 +            guard let attributedPlaceholder = attributedPlaceholder else { return }
  135.34 +            let attributes: [NSAttributedString.Key: UIColor] = [.foregroundColor: newValue]
  135.35 +            self.attributedPlaceholder = NSAttributedString(string: attributedPlaceholder.string, attributes: attributes)
  135.36 +        }
  135.37 +    }
  135.38 +}
   136.1 --- a/pEpForiOS/UI/Util/SecureWebViewController/SecureWebViewController.swift	Wed Feb 20 11:00:07 2019 +0100
   136.2 +++ b/pEpForiOS/UI/Util/SecureWebViewController/SecureWebViewController.swift	Mon Mar 18 10:54:14 2019 +0100
   136.3 @@ -7,6 +7,7 @@
   136.4  //
   136.5  
   136.6  import WebKit
   136.7 +import pEpIOSToolbox
   136.8  
   136.9  protocol SecureWebViewControllerDelegate: class {
  136.10      /// Called on content size changes while within loading time.
   137.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   137.2 +++ b/pEpForiOS/UI/Util/SegueHandlerType.swift	Mon Mar 18 10:54:14 2019 +0100
   137.3 @@ -0,0 +1,32 @@
   137.4 +//
   137.5 +//  SegueHandlerType.swift
   137.6 +//
   137.7 +//  Pattern for using segues via enumeration.
   137.8 +//  see: https://developer.apple.com/videos/wwdc/2015/?id=411
   137.9 +//
  137.10 +//  Created by Marko Tadic on 8/25/15.
  137.11 +//  Copyright © 2015 AE. All rights reserved.
  137.12 +//
  137.13 +
  137.14 +import UIKit
  137.15 +
  137.16 +public protocol SegueHandlerType {
  137.17 +    associatedtype SegueIdentifier: RawRepresentable
  137.18 +}
  137.19 +
  137.20 +public extension SegueHandlerType where Self: UIViewController, SegueIdentifier.RawValue == String {
  137.21 +    
  137.22 +    public func performSegue(withIdentifier identifier: SegueIdentifier, sender: Any?) {
  137.23 +        performSegue(withIdentifier: identifier.rawValue, sender: sender)
  137.24 +    }
  137.25 +    
  137.26 +    public func segueIdentifier(for segue: UIStoryboardSegue) -> SegueIdentifier {
  137.27 +        guard let
  137.28 +            identifier = segue.identifier,
  137.29 +            let segueIdentifier = SegueIdentifier(rawValue: identifier)
  137.30 +        else {
  137.31 +            return SegueIdentifier(rawValue: "noSegue")!
  137.32 +        }
  137.33 +        return segueIdentifier
  137.34 +    }
  137.35 +}
   138.1 --- a/pEpForiOS/UI/Util/SuggestTableViewController/SuggestTableViewController.swift	Wed Feb 20 11:00:07 2019 +0100
   138.2 +++ b/pEpForiOS/UI/Util/SuggestTableViewController/SuggestTableViewController.swift	Mon Mar 18 10:54:14 2019 +0100
   138.3 @@ -7,6 +7,7 @@
   138.4  //
   138.5  
   138.6  import Foundation
   138.7 +import pEpIOSToolbox
   138.8  
   138.9  /// Suggests a list of Identities that fit to a given sarch string
  138.10  class SuggestTableViewController: BaseTableViewController {
   139.1 --- a/pEpForiOS/UI/Util/SuggestTableViewController/SuggestViewModel.swift	Wed Feb 20 11:00:07 2019 +0100
   139.2 +++ b/pEpForiOS/UI/Util/SuggestTableViewController/SuggestViewModel.swift	Mon Mar 18 10:54:14 2019 +0100
   139.3 @@ -7,6 +7,7 @@
   139.4  //
   139.5  
   139.6  import MessageModel
   139.7 +import pEpIOSToolbox
   139.8  
   139.9  protocol SuggestViewModelResultDelegate: class {
  139.10      /// Will be called whenever the user selects an Identity.
   140.1 --- a/pEpForiOS/UI/Util/UIAlertController+Extension.swift	Wed Feb 20 11:00:07 2019 +0100
   140.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   140.3 @@ -1,33 +0,0 @@
   140.4 -//
   140.5 -//  UIAlertController+Extension.swift
   140.6 -//  pEp
   140.7 -//
   140.8 -//  Created by Dirk Zimmermann on 10.05.18.
   140.9 -//  Copyright © 2018 p≡p Security S.A. All rights reserved.
  140.10 -//
  140.11 -
  140.12 -import Foundation
  140.13 -
  140.14 -import MessageModel
  140.15 -
  140.16 -extension UIAlertController {
  140.17 -    public func action(_ title: String,
  140.18 -                       _ style: UIAlertActionStyle = .default,
  140.19 -                       _ closure: Tasks.simple? = nil) ->  UIAlertAction {
  140.20 -        return UIAlertAction(title: title, style: style) { (action) in
  140.21 -            if let clos = closure {
  140.22 -                clos()
  140.23 -            }
  140.24 -        }
  140.25 -    }
  140.26 -
  140.27 -    public static func pEpAlertController(
  140.28 -        title: String? = nil,
  140.29 -        message: String? = nil,
  140.30 -        preferredStyle: UIAlertControllerStyle = .actionSheet) -> UIAlertController {
  140.31 -        let alertCtrl = UIAlertController(title: title, message: message,
  140.32 -                                          preferredStyle: preferredStyle)
  140.33 -        alertCtrl.view.tintColor = .pEpGreen
  140.34 -        return alertCtrl
  140.35 -    }
  140.36 -}
   141.1 --- a/pEpForiOS/UI/Util/UIBarButtonItem+Extension.swift	Wed Feb 20 11:00:07 2019 +0100
   141.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   141.3 @@ -1,17 +0,0 @@
   141.4 -//
   141.5 -//  UIBarButtonItem+Extension.swift
   141.6 -//  pEp
   141.7 -//
   141.8 -//  Created by Xavier Algarra on 11/07/2018.
   141.9 -//  Copyright © 2018 p≡p Security S.A. All rights reserved.
  141.10 -//
  141.11 -
  141.12 -import Foundation
  141.13 -
  141.14 -extension UIBarButtonItem {
  141.15 -    public static func getPEPButton(action: Selector, target: Any) -> UIBarButtonItem {
  141.16 -        let img = UIImage(named: "icon-settings")
  141.17 -        let pEpButton = UIBarButtonItem(image: img, style: .plain, target: target, action: action)
  141.18 -        return pEpButton
  141.19 -    }
  141.20 -}
   142.1 --- a/pEpForiOS/UI/Util/UIButton+Extension.swift	Wed Feb 20 11:00:07 2019 +0100
   142.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   142.3 @@ -1,59 +0,0 @@
   142.4 -//
   142.5 -//  UIButton+Extension.swift
   142.6 -//  pEpForiOS
   142.7 -//
   142.8 -//  Created by Dirk Zimmermann on 20.04.17.
   142.9 -//  Copyright © 2017 p≡p Security S.A. All rights reserved.
  142.10 -//
  142.11 -
  142.12 -import UIKit
  142.13 -
  142.14 -extension UIButton {
  142.15 -    /**
  142.16 -     Makes the button the typical look for a pEp button used in the handshake dialogs.
  142.17 -     */
  142.18 -    func pEpIfyForTrust(backgroundColor: UIColor, textColor: UIColor) {
  142.19 -        titleLabel?.numberOfLines = 0
  142.20 -        titleLabel?.lineBreakMode = .byWordWrapping
  142.21 -        titleLabel?.textAlignment = .center
  142.22 -
  142.23 -        self.backgroundColor = backgroundColor
  142.24 -        setTitleColor(textColor, for: .normal)
  142.25 -        layer.cornerRadius = 2
  142.26 -        let insetV: CGFloat = 15
  142.27 -        let insetH: CGFloat = 15
  142.28 -        contentEdgeInsets = UIEdgeInsetsMake(insetV, insetH, insetV, insetH)
  142.29 -    }
  142.30 -
  142.31 -    func convertToLoginButton(placeholder: String) {
  142.32 -        self.backgroundColor = UIColor.clear
  142.33 -        self.tintColor = UIColor.pEpGreen
  142.34 -        self.setTitle(placeholder, for: .normal)
  142.35 -    }
  142.36 -
  142.37 -    /**
  142.38 -     Does the content fit the button bounds?
  142.39 -     */
  142.40 -    func contentFitsWidth() -> Bool {
  142.41 -        let iSize = intrinsicContentSize
  142.42 -        let actSize = bounds.size
  142.43 -        return iSize.width < actSize.width
  142.44 -    }
  142.45 -}
  142.46 -
  142.47 -public class HandshakeButton: UIButton {
  142.48 -
  142.49 -    public func roundCorners(corners: UIRectCorner, radius: CGFloat){
  142.50 -        clipsToBounds = true
  142.51 -        layer.cornerRadius = 0
  142.52 -        let maskPath = UIBezierPath(roundedRect: bounds,
  142.53 -                                    byRoundingCorners: corners,
  142.54 -                                    cornerRadii: CGSize(width: radius, height: radius))
  142.55 -        let maskLayer = CAShapeLayer()
  142.56 -        maskLayer.bounds = frame
  142.57 -        maskLayer.position = center
  142.58 -        maskLayer.path = maskPath.cgPath
  142.59 -
  142.60 -        layer.mask = maskLayer
  142.61 -    }
  142.62 -}
   143.1 --- a/pEpForiOS/UI/Util/UIColor+Extension.swift	Wed Feb 20 11:00:07 2019 +0100
   143.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   143.3 @@ -1,63 +0,0 @@
   143.4 -//
   143.5 -//  UIColor+Extension.swift
   143.6 -//  pEpForiOS
   143.7 -//
   143.8 -//  Created by Dirk Zimmermann on 23/03/2017.
   143.9 -//  Copyright © 2017 p≡p Security S.A. All rights reserved.
  143.10 -//
  143.11 -
  143.12 -import UIKit
  143.13 -
  143.14 -extension UIColor {
  143.15 -    static let pEpGreenHex = "#03AA4B"
  143.16 -    static let pEpDarkGreenHex = "#1AAA50"
  143.17 -    static let pEpRedHex = "#FF3B30"
  143.18 -    static let pEpGreyHex = "#8e8e93"
  143.19 -    static let pEpYellowHex = "#FFCC00"
  143.20 -    static let pEpLightBackgroundHex = "#F2F2F2"
  143.21 -    static let pEpNavigationBarColor = "#f7f7f7"
  143.22 -
  143.23 -    public static var pEpGreen = UIColor(hexString: pEpGreenHex)
  143.24 -    public static var pEpDarkGreen = UIColor(hexString: pEpDarkGreenHex)
  143.25 -    public static var pEpRed = UIColor(hexString: pEpRedHex)
  143.26 -    public static var pEpGray = UIColor(hexString: pEpGreyHex)
  143.27 -    public static var pEpYellow = UIColor(hexString: pEpYellowHex)
  143.28 -    public static var pEpNavigation = UIColor(hexString: pEpNavigationBarColor)
  143.29 -
  143.30 -    /**
  143.31 -     Example use: In trustwords table view cells.
  143.32 -     */
  143.33 -    public static var pEpLightBackground = UIColor(hexString: pEpLightBackgroundHex)
  143.34 -
  143.35 -    convenience init(redInt: Int, greenInt: Int, blueInt: Int, alpha: CGFloat = 1.0) {
  143.36 -        self.init(red: CGFloat(redInt) / 255.0,
  143.37 -                  green: CGFloat(greenInt) / 255.0,
  143.38 -                  blue: CGFloat(blueInt) / 255.0,
  143.39 -                  alpha: alpha)
  143.40 -    }
  143.41 -
  143.42 -    convenience init(hexString: String, alpha: CGFloat = 1.0) {
  143.43 -        var theHexString = hexString
  143.44 -        if theHexString.hasPrefix("#") {
  143.45 -            theHexString = String(theHexString.dropFirst())
  143.46 -        }
  143.47 -
  143.48 -        var rgbValue: UInt32 = 0
  143.49 -        Scanner(string: theHexString).scanHexInt32(&rgbValue)
  143.50 -
  143.51 -        let r = CGFloat((rgbValue >> 16) & 0xff) / 255.0
  143.52 -        let g = CGFloat((rgbValue >> 08) & 0xff) / 255.0
  143.53 -        let b = CGFloat((rgbValue >> 00) & 0xff) / 255.0
  143.54 -
  143.55 -        self.init(red: r, green: g, blue: b, alpha: alpha)
  143.56 -    }
  143.57 -
  143.58 -    convenience init(intValue32: Int, alpha: CGFloat = 1.0) {
  143.59 -        self.init(
  143.60 -            red: CGFloat((intValue32 & 0xFF0000) >> 16) / 255.0,
  143.61 -            green: CGFloat((intValue32 & 0x00FF00) >> 8) / 255.0,
  143.62 -            blue: CGFloat((intValue32 & 0x0000FF) >> 0) / 255.0,
  143.63 -            alpha: alpha
  143.64 -        )
  143.65 -    }
  143.66 -}
   144.1 --- a/pEpForiOS/UI/Util/UIImage+Extension.swift	Wed Feb 20 11:00:07 2019 +0100
   144.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   144.3 @@ -1,64 +0,0 @@
   144.4 -//
   144.5 -//  UIImage+Extension.swift
   144.6 -//  pEpForiOS
   144.7 -//
   144.8 -//  Created by Dirk Zimmermann on 24/03/2017.
   144.9 -//  Copyright © 2017 p≡p Security S.A. All rights reserved.
  144.10 -//
  144.11 -
  144.12 -import UIKit
  144.13 -
  144.14 -extension UIImage {
  144.15 -    public static func generate(size: CGSize, block: (CGContext, CGSize) -> ()) -> UIImage? {
  144.16 -        var theImage: UIImage?
  144.17 -        UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
  144.18 -        if let ctx = UIGraphicsGetCurrentContext() {
  144.19 -            block(ctx, size)
  144.20 -            theImage = UIGraphicsGetImageFromCurrentImageContext()
  144.21 -        }
  144.22 -        UIGraphicsEndImageContext()
  144.23 -        return theImage
  144.24 -    }
  144.25 -
  144.26 -    /**
  144.27 -     - Create a 1x1 pixel image of the given color.
  144.28 -     - Note: Retina-displays are taken into account.
  144.29 -     - Returns: An image that contains exactly one pixel of the given color.
  144.30 -     */
  144.31 -    public static func pixel(color: UIColor) -> UIImage? {
  144.32 -        let pixelScale = UIScreen.main.scale
  144.33 -        let pixelSize = 1 / pixelScale
  144.34 -        let fillSize = CGSize(width: pixelSize, height: pixelSize)
  144.35 -        return generate(size: fillSize) { context, size in
  144.36 -            let fillRect = CGRect(origin: CGPoint.zero, size: size)
  144.37 -            context.setFillColor(color.cgColor)
  144.38 -            context.fill(fillRect)
  144.39 -        }
  144.40 -    }
  144.41 -
  144.42 -    /// Returns the image resized to the given width, using scaleToFit behaviour.
  144.43 -    ///
  144.44 -    /// - Parameters:
  144.45 -    ///   - newWidth:   target width the image should be resized to
  144.46 -    ///   - useAlpha:   A Boolean flag indicating whether the bitmap must include an alpha channel
  144.47 -    ///                 (to handle any partially transparent pixels). If you know the bitmap is
  144.48 -    ///                 fully opaque, specify false to ignore the alpha channel and optimize the
  144.49 -    ///                 bitmap’s storage.
  144.50 -    ///   - scale:      The scale factor to apply to the bitmap.
  144.51 -    ///                 If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen.
  144.52 -    /// - Returns: resized image
  144.53 -    public func resized(newWidth: CGFloat, useAlpha: Bool = true, scale: CGFloat = 0.0) -> UIImage? {
  144.54 -        let factor = self.size.width / newWidth
  144.55 -        let size = CGSize(width: self.size.width / factor, height: self.size.height / factor)
  144.56 -        let opaque = !useAlpha
  144.57 -        let scale: CGFloat = 0.0
  144.58 -        UIGraphicsBeginImageContextWithOptions(size, opaque, scale)
  144.59 -        self.draw(in: CGRect(origin: CGPoint.zero, size: size))
  144.60 -
  144.61 -        guard let newImage = UIGraphicsGetImageFromCurrentImageContext() else {
  144.62 -            return nil
  144.63 -        }
  144.64 -        UIGraphicsEndImageContext()
  144.65 -        return newImage
  144.66 -    }
  144.67 -}
   145.1 --- a/pEpForiOS/UI/Util/UIImage+GIF.swift	Wed Feb 20 11:00:07 2019 +0100
   145.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   145.3 @@ -1,68 +0,0 @@
   145.4 -//
   145.5 -//  UIImage+GIF.swift
   145.6 -//  pEp
   145.7 -//
   145.8 -//  Created by Dirk Zimmermann on 15.05.18.
   145.9 -//  Copyright © 2018 p≡p Security S.A. All rights reserved.
  145.10 -//
  145.11 -
  145.12 -import Foundation
  145.13 -
  145.14 -extension UIImage {
  145.15 -    static func image(animationFrames: [CGImageSource.AnimationFrame]) -> UIImage? {
  145.16 -        if animationFrames.isEmpty {
  145.17 -            return nil
  145.18 -        }
  145.19 -
  145.20 -        let totalSeconds = animationFrames.reduce(0) { acc, next in
  145.21 -            return acc + next.durationSeconds
  145.22 -        }
  145.23 -
  145.24 -        guard let gcdDecis = CGImageSource.AnimationFrame.gcdDurationDecis(
  145.25 -            animationFrames: animationFrames) else {
  145.26 -                return nil
  145.27 -        }
  145.28 -
  145.29 -        let parts = animationFrames.map { $0.durationDecis / gcdDecis }
  145.30 -
  145.31 -        var images = [UIImage]()
  145.32 -        for iPart in 0..<parts.count {
  145.33 -            let frameImage = UIImage(cgImage: animationFrames[iPart].cgImage)
  145.34 -            let numberOfImagesNeeded = parts[iPart]
  145.35 -            for _ in 0..<numberOfImagesNeeded {
  145.36 -                images.append(frameImage)
  145.37 -            }
  145.38 -        }
  145.39 -
  145.40 -        return UIImage.animatedImage(with: images, duration: totalSeconds)
  145.41 -    }
  145.42 -
  145.43 -    /**
  145.44 -     Tries to create a gif from the given core foundation image source,
  145.45 -     that could possibly be animated.
  145.46 -     */
  145.47 -    public static func image(cgImageSource: CGImageSource) -> UIImage? {
  145.48 -        let animationFrames = cgImageSource.animationFrames()
  145.49 -
  145.50 -        if animationFrames.count == 1 {
  145.51 -            let frame1 = animationFrames[0]
  145.52 -            return UIImage(cgImage: frame1.cgImage)
  145.53 -        } else if animationFrames.count > 1 {
  145.54 -            return image(animationFrames: animationFrames)
  145.55 -        } else {
  145.56 -            return nil
  145.57 -        }
  145.58 -    }
  145.59 -
  145.60 -    /**
  145.61 -     Tries to create a gif from the given data, that could possibly
  145.62 -     be animated.
  145.63 -     */
  145.64 -    public static func image(gifData: Data) -> UIImage? {
  145.65 -        if let cgImgSource = CGImageSourceCreateWithData(gifData as CFData, nil) {
  145.66 -            return image(cgImageSource: cgImgSource)
  145.67 -        } else {
  145.68 -            return nil
  145.69 -        }
  145.70 -    }
  145.71 -}
   146.1 --- a/pEpForiOS/UI/Util/UIImageView+Extension.swift	Wed Feb 20 11:00:07 2019 +0100
   146.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   146.3 @@ -1,37 +0,0 @@
   146.4 -//
   146.5 -//  UIImageView+Extension.swift
   146.6 -//  pEpForiOS
   146.7 -//
   146.8 -//  Created by Dirk Zimmermann on 18.04.17.
   146.9 -//  Copyright © 2017 p≡p Security S.A. All rights reserved.
  146.10 -//
  146.11 -
  146.12 -import UIKit
  146.13 -
  146.14 -extension UIImageView {
  146.15 -    /**
  146.16 -     - Returns: The aspect ratio, like 16:9, as a float. That is the factor you
  146.17 -     have to multiply the height and receive the width.
  146.18 -     */
  146.19 -    func aspectRatio() -> CGFloat {
  146.20 -        return bounds.width / bounds.height
  146.21 -    }
  146.22 -
  146.23 -    /**
  146.24 -     Sets up the necessary constraints to have the height always adopt to the width,
  146.25 -     while maintaining the correct aspect ratio.
  146.26 -     */
  146.27 -    func activateAspectRatioConstraint() {
  146.28 -        let factor = 1 / aspectRatio()
  146.29 -        heightAnchor.constraint(equalTo: widthAnchor, multiplier: factor).isActive = true
  146.30 -    }
  146.31 -
  146.32 -    /**
  146.33 -     Gives the image the uniform look of a contact image.
  146.34 -     */
  146.35 -    func applyContactImageCornerRadius() {
  146.36 -        let theWidth = bounds.size.width
  146.37 -        layer.cornerRadius = round(theWidth / 10)
  146.38 -        layer.masksToBounds = true
  146.39 -    }
  146.40 -}
   147.1 --- a/pEpForiOS/UI/Util/UINavigationController+Extensions.swift	Wed Feb 20 11:00:07 2019 +0100
   147.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   147.3 @@ -1,15 +0,0 @@
   147.4 -//
   147.5 -//  UINavigationController+Extensions.swift
   147.6 -//  pEpForiOS
   147.7 -//
   147.8 -//  Created by Andreas Buff on 23.08.17.
   147.9 -//  Copyright © 2017 p≡p Security S.A. All rights reserved.
  147.10 -//
  147.11 -
  147.12 -import UIKit
  147.13 -
  147.14 -extension UINavigationController {
  147.15 -    var rootViewController : UIViewController? {
  147.16 -        return viewControllers.first
  147.17 -    }
  147.18 -}
   148.1 --- a/pEpForiOS/UI/Util/UITableView+Extension.swift	Wed Feb 20 11:00:07 2019 +0100
   148.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   148.3 @@ -1,32 +0,0 @@
   148.4 -//
   148.5 -//  UITableView+Extension.swift
   148.6 -//  pEpForiOS
   148.7 -//
   148.8 -//  Created by Dirk Zimmermann on 24.04.17.
   148.9 -//  Copyright © 2017 p≡p Security S.A. All rights reserved.
  148.10 -//
  148.11 -
  148.12 -import UIKit
  148.13 -
  148.14 -extension UITableView {
  148.15 -    /**
  148.16 -     This magic code should trigger a height refresh for table cells,
  148.17 -     with an optional block to execute after the size got updated, but outside of
  148.18 -     the no-animation block.
  148.19 -     */
  148.20 -    public final func updateSize(andExecuteBlock: (() -> Void)? = nil) {
  148.21 -        UIView.performWithoutAnimation {
  148.22 -            beginUpdates()
  148.23 -            endUpdates()
  148.24 -            if let theBlock = andExecuteBlock {
  148.25 -                GCD.onMain {
  148.26 -                    theBlock()
  148.27 -                }
  148.28 -            }
  148.29 -        }
  148.30 -    }
  148.31 -}
  148.32 -
  148.33 -protocol TableViewUpdate {
  148.34 -    func updateView()
  148.35 -}
   149.1 --- a/pEpForiOS/UI/Util/UITextField+Extension.swift	Wed Feb 20 11:00:07 2019 +0100
   149.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   149.3 @@ -1,41 +0,0 @@
   149.4 -//
   149.5 -//  UITextField+Extension.swift
   149.6 -//  pEpForiOS
   149.7 -//
   149.8 -//  Created by Xavier Algarra on 25/04/2017.
   149.9 -//  Copyright © 2017 p≡p Security S.A. All rights reserved.
  149.10 -//
  149.11 -
  149.12 -import UIKit
  149.13 -
  149.14 -extension UITextField {
  149.15 -    func convertToLoginField(placeholder: String, delegate: UITextFieldDelegate) {
  149.16 -        // common properties
  149.17 -        self.delegate = delegate
  149.18 -        self.placeholder = placeholder
  149.19 -
  149.20 -        // properties divided between enabled/disabled
  149.21 -        if isEnabled {
  149.22 -            enableLoginField()
  149.23 -        } else {
  149.24 -            disableLoginField()
  149.25 -        }
  149.26 -    }
  149.27 -
  149.28 -    func disableLoginField() {
  149.29 -        enableOrDisableLoginField(enable: false)
  149.30 -    }
  149.31 -
  149.32 -    func enableLoginField() {
  149.33 -        enableOrDisableLoginField(enable: true)
  149.34 -    }
  149.35 -
  149.36 -    func enableOrDisableLoginField(enable: Bool) {
  149.37 -        let theColor = enable ? UIColor.white : UIColor.gray
  149.38 -        self.textColor = theColor
  149.39 -        if let ph = placeholder {
  149.40 -            self.attributedPlaceholder = NSAttributedString(
  149.41 -                string: ph, attributes: [NSAttributedStringKey.foregroundColor: theColor])
  149.42 -        }
  149.43 -    }
  149.44 -}
   150.1 --- a/pEpForiOS/UI/Util/UIUtils.swift	Wed Feb 20 11:00:07 2019 +0100
   150.2 +++ b/pEpForiOS/UI/Util/UIUtils.swift	Mon Mar 18 10:54:14 2019 +0100
   150.3 @@ -9,6 +9,7 @@
   150.4  import UIKit
   150.5  import MessageModel
   150.6  import ContactsUI
   150.7 +import pEpIOSToolbox
   150.8  
   150.9  struct UIUtils {
  150.10  
   151.1 --- a/pEpForiOS/UI/Util/UIView+Autolayout.swift	Wed Feb 20 11:00:07 2019 +0100
   151.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   151.3 @@ -1,31 +0,0 @@
   151.4 -//
   151.5 -//  UIView+Autolayout.swift
   151.6 -//  pEp
   151.7 -//
   151.8 -//  Created by Andreas Buff on 09.03.18.
   151.9 -//  Copyright © 2018 p≡p Security S.A. All rights reserved.
  151.10 -//
  151.11 -
  151.12 -import UIKit
  151.13 -
  151.14 -extension UIView {
  151.15 -    /// Sets up constraints to always stay the same size as the superview.
  151.16 -    func fullSizeInSuperView() {
  151.17 -        guard let superview = self.superview else {
  151.18 -            Logger.frontendLogger.errorAndCrash("No superview")
  151.19 -            return
  151.20 -        }
  151.21 -
  151.22 -        self.translatesAutoresizingMaskIntoConstraints = false
  151.23 -        superview.addConstraints(NSLayoutConstraint.constraints(
  151.24 -            withVisualFormat: "H:|-0-[subview]-0-|",
  151.25 -            options: .directionLeadingToTrailing,
  151.26 -            metrics: nil,
  151.27 -            views: ["subview": self]))
  151.28 -        superview.addConstraints(NSLayoutConstraint.constraints(
  151.29 -            withVisualFormat: "V:|-0-[subview]-0-|",
  151.30 -            options: .directionLeadingToTrailing,
  151.31 -            metrics: nil,
  151.32 -            views: ["subview": self]))
  151.33 -    }
  151.34 -}
   152.1 --- a/pEpForiOS/UI/Util/UIView+Util.swift	Wed Feb 20 11:00:07 2019 +0100
   152.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   152.3 @@ -1,61 +0,0 @@
   152.4 -//
   152.5 -//  UIView+Util.swift
   152.6 -//  pEpForiOS
   152.7 -//
   152.8 -//  Created by Dirk Zimmermann on 10.04.17.
   152.9 -//  Copyright © 2017 p≡p Security S.A. All rights reserved.
  152.10 -//
  152.11 -
  152.12 -import UIKit
  152.13 -
  152.14 -/**
  152.15 - A piece of data for tracking the "busyness" of a view.
  152.16 - */
  152.17 -struct ViewBusyState {
  152.18 -    let views: [UIView]
  152.19 -}
  152.20 -
  152.21 -extension UIView {
  152.22 -    func dumpConstraints(axis: UILayoutConstraintAxis) {
  152.23 -        let constrs = constraintsAffectingLayout(for: axis)
  152.24 -        if constrs.isEmpty {
  152.25 -            print("no constraints")
  152.26 -        }
  152.27 -        for con in constrs {
  152.28 -            print("\(con)")
  152.29 -        }
  152.30 -    }
  152.31 -
  152.32 -    /**
  152.33 -     Marks the view as busy, e.g. by adding some spinning animation view.
  152.34 -     */
  152.35 -    func displayAsBusy() -> ViewBusyState {
  152.36 -        let darkView = UIView()
  152.37 -        darkView.translatesAutoresizingMaskIntoConstraints = false
  152.38 -        darkView.backgroundColor = .black
  152.39 -        darkView.alpha = 0.5
  152.40 -        addSubview(darkView)
  152.41 -        darkView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
  152.42 -        darkView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
  152.43 -        darkView.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
  152.44 -        darkView.heightAnchor.constraint(equalTo: heightAnchor).isActive = true
  152.45 -
  152.46 -        let activityView = UIActivityIndicatorView()
  152.47 -        activityView.activityIndicatorViewStyle = .whiteLarge
  152.48 -        activityView.translatesAutoresizingMaskIntoConstraints = false
  152.49 -        darkView.addSubview(activityView)
  152.50 -        activityView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
  152.51 -        activityView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
  152.52 -        activityView.startAnimating()
  152.53 -        return ViewBusyState(views: [darkView])
  152.54 -    }
  152.55 -
  152.56 -    /**
  152.57 -     Marks the given view as not busy anymore.
  152.58 -     */
  152.59 -    func stopDisplayingAsBusy(viewBusyState: ViewBusyState) {
  152.60 -        for v in viewBusyState.views {
  152.61 -            v.removeFromSuperview()
  152.62 -        }
  152.63 -    }
  152.64 -}
   153.1 --- a/pEpForiOS/UI/Util/UIViewController+Extension.swift	Wed Feb 20 11:00:07 2019 +0100
   153.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   153.3 @@ -1,42 +0,0 @@
   153.4 -//
   153.5 -//  UIViewController+Extension.swift
   153.6 -//  pEpForiOS
   153.7 -//
   153.8 -//  Created by Dirk Zimmermann on 17/02/2017.
   153.9 -//  Copyright © 2017 p≡p Security S.A. All rights reserved.
  153.10 -//
  153.11 -
  153.12 -import Foundation
  153.13 -import UIKit
  153.14 -
  153.15 -extension UIViewController {
  153.16 -    var isModalViewCurrentlyShown: Bool {
  153.17 -        return presentedViewController != nil
  153.18 -    }
  153.19 -
  153.20 -    @discardableResult func showPepRating(pEpRating: PEP_rating?, pEpProtection: Bool = true) -> UIView? {
  153.21 -        if let img = pEpRating?.pEpColor().statusIcon(enabled: pEpProtection) {
  153.22 -            // according to apple's design guidelines ('Hit Targets'):
  153.23 -            // https://developer.apple.com/design/tips/
  153.24 -            let minimumHittestDimension: CGFloat = 44
  153.25 -
  153.26 -            let minimumImageWidth = max(minimumHittestDimension / 2, img.size.width)
  153.27 -            let img2 = img.resized(newWidth: minimumImageWidth)
  153.28 -            let v = UIImageView(image: img2)
  153.29 -            v.contentMode = .center // DON'T stretch the image, leave it at original size
  153.30 -
  153.31 -            // try to make the hit area of the icon a minimum of 44x44
  153.32 -            let desiredHittestDimension: CGFloat = min(
  153.33 -                minimumHittestDimension,
  153.34 -                navigationController?.navigationBar.frame.size.height ?? minimumHittestDimension)
  153.35 -            v.bounds.size = CGSize(width: desiredHittestDimension, height: desiredHittestDimension)
  153.36 -
  153.37 -            navigationItem.titleView = v
  153.38 -            v.isUserInteractionEnabled = true
  153.39 -            return v
  153.40 -        } else {
  153.41 -            navigationItem.titleView = nil
  153.42 -            return nil
  153.43 -        }
  153.44 -    }
  153.45 -}
   154.1 --- a/pEpForiOS/Util/AsyncStateMachine.swift	Wed Feb 20 11:00:07 2019 +0100
   154.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   154.3 @@ -1,96 +0,0 @@
   154.4 -//
   154.5 -//  AsyncStateMachine.swift
   154.6 -//  pEpForiOS
   154.7 -//
   154.8 -//  Created by Dirk Zimmermann on 21.06.17.
   154.9 -//  Copyright © 2017 p≡p Security S.A. All rights reserved.
  154.10 -//
  154.11 -
  154.12 -import Foundation
  154.13 -
  154.14 -public class AsyncStateMachine<S: Hashable, E: Hashable, M>: AsyncStateMachineProtocol {
  154.15 -    enum StateMachineError: Error {
  154.16 -        /** The state/event combination is not handled */
  154.17 -        case unhandledStateEvent(S, E)
  154.18 -    }
  154.19 -
  154.20 -    private(set) public var state: S
  154.21 -    public var model: M
  154.22 -
  154.23 -    public typealias MyStateHandler = (_ state: S, _ model: M) -> M
  154.24 -    public typealias MyEventHandler = (_ state: S, _ model: M, _ event: E) -> M
  154.25 -
  154.26 -    var transitions = Dictionary<Tuple<S, E>, S>()
  154.27 -    var stateEnterHandlers = Dictionary<S, MyStateHandler>()
  154.28 -    var eventHandlers = Dictionary<E, (S, MyEventHandler)>()
  154.29 -
  154.30 -    private let managementQueue = DispatchQueue(
  154.31 -        label: "AsyncStateMachine.managementQueue", qos: .utility, target: nil)
  154.32 -
  154.33 -    public init(state: S, model: M) {
  154.34 -        self.state = state
  154.35 -        self.model = model
  154.36 -    }
  154.37 -
  154.38 -    public func addTransition(srcState: S, event: E, targetState: S) {
  154.39 -        managementQueue.async { [weak self] in
  154.40 -            let tuple = Tuple(values: (srcState, event))
  154.41 -            self?.transitions[tuple] = targetState
  154.42 -        }
  154.43 -    }
  154.44 -
  154.45 -    public func addTransition(event: E, targetState: S, handler: @escaping MyEventHandler) {
  154.46 -        managementQueue.async { [weak self] in
  154.47 -            guard let theSelf = self else {
  154.48 -                return
  154.49 -            }
  154.50 -            theSelf.eventHandlers[event] = (targetState, handler)
  154.51 -        }
  154.52 -    }
  154.53 -
  154.54 -    public func send(event: E, onError: @escaping ErrorHandler) {
  154.55 -        managementQueue.async { [weak self] in
  154.56 -            self?.sendInternal(event: event, onError: onError)
  154.57 -        }
  154.58 -    }
  154.59 -
  154.60 -    func sendInternal(event: E, onError: @escaping ErrorHandler) {
  154.61 -        let tuple = Tuple(values: (state, event))
  154.62 -        if let targetState = transitions[tuple] {
  154.63 -            model = handleTransition(
  154.64 -                targetState: targetState, model: model)
  154.65 -        } else {
  154.66 -            if let (targetState, eh) = eventHandlers[event] {
  154.67 -                model = eh(state, model, event)
  154.68 -                model = handleTransition(
  154.69 -                    targetState: targetState, model: model)
  154.70 -            } else {
  154.71 -                onError(StateMachineError.unhandledStateEvent(state, event))
  154.72 -            }
  154.73 -        }
  154.74 -    }
  154.75 -
  154.76 -    func handleTransition(targetState: S, model: M) -> M {
  154.77 -        state = targetState
  154.78 -        if let handler = stateEnterHandlers[targetState] {
  154.79 -            return handler(targetState, model)
  154.80 -        } else {
  154.81 -            Logger.utilLogger.warn("Entered state %{public}@, but no handler",
  154.82 -                                               "\(targetState)")
  154.83 -        }
  154.84 -        return model
  154.85 -    }
  154.86 -
  154.87 -    public func handleEntering(state: S, handler: @escaping MyStateHandler) {
  154.88 -        managementQueue.async { [weak self] in
  154.89 -            guard let theSelf = self else {
  154.90 -                return
  154.91 -            }
  154.92 -            theSelf.stateEnterHandlers[state] = handler
  154.93 -        }
  154.94 -    }
  154.95 -
  154.96 -    public func async(block: @escaping () -> ()) {
  154.97 -        managementQueue.async(execute: block)
  154.98 -    }
  154.99 -}
   155.1 --- a/pEpForiOS/Util/AsyncStateMachineProtocol.swift	Wed Feb 20 11:00:07 2019 +0100
   155.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   155.3 @@ -1,74 +0,0 @@
   155.4 -//
   155.5 -//  AsyncStateMachineProtocol.swift
   155.6 -//  pEpForiOS
   155.7 -//
   155.8 -//  Created by Dirk Zimmermann on 21.06.17.
   155.9 -//  Copyright © 2017 p≡p Security S.A. All rights reserved.
  155.10 -//
  155.11 -
  155.12 -import Foundation
  155.13 -
  155.14 -/**
  155.15 - This is a finite state machine (FSM) with an additional internal model. So every transition is
  155.16 - dependent on the current state (S), the incoming Event (E), and the current model (M).
  155.17 - The model is an extension to the traditional concept of an FSM.
  155.18 - You can install handlers (closures) for every state/event combination. The handler then
  155.19 - is responsible for checking/changing the model, and can asynchronously send further events
  155.20 - the the state machine.
  155.21 - See also `async` for executing blocks on the state machine management queue, if you want
  155.22 - to serialize operations and don't have your own queue.
  155.23 - */
  155.24 -public protocol AsyncStateMachineProtocol {
  155.25 -    /** The type for states, typically an enum. A state is a finite state machine state. */
  155.26 -    associatedtype S: Hashable
  155.27 -
  155.28 -    /** The type for events, typically an enum */
  155.29 -    associatedtype E: Hashable
  155.30 -
  155.31 -    /** The model type */
  155.32 -    associatedtype M
  155.33 -
  155.34 -    typealias ErrorHandler = (_ error: Error) -> ()
  155.35 -
  155.36 -    /**
  155.37 -     This handler is called when a state is reached.
  155.38 -     It's expected to return a modified model M.
  155.39 -     */
  155.40 -    typealias StateEnterHandler = (_ state: S, _ model: M) -> M
  155.41 -
  155.42 -    /**
  155.43 -     A handler like this is called when an event comes in, and there is no transition defined.
  155.44 -     */
  155.45 -    typealias EventHandler = (_ state: S, _ model: M, _ event: E) -> M
  155.46 -
  155.47 -    var state: S { get }
  155.48 -    var model: M { get set }
  155.49 -
  155.50 -    /**
  155.51 -     Marks the given State -> Event as a legal combination, and sets the target state.
  155.52 -     */
  155.53 -    func addTransition(srcState: S, event: E, targetState: S)
  155.54 -
  155.55 -    /**
  155.56 -     Adds a wildcard transition, that can be activated from any state. Those handlers
  155.57 -     are only considered if there is no "normal" transition defined.
  155.58 -     */
  155.59 -    func addTransition(event: E, targetState: S, handler: @escaping EventHandler)
  155.60 -
  155.61 -    /**
  155.62 -     Sends `event` to the state machine. If the state/event combination is invalid,
  155.63 -     the error handler is invoked with an error.
  155.64 -     */
  155.65 -    func send(event: E, onError: @escaping ErrorHandler)
  155.66 -
  155.67 -    /**
  155.68 -     Might throw an exception if the handlers are ambigious, e.g. there is already a
  155.69 -     handler for a given state.
  155.70 -     */
  155.71 -    func handleEntering(state: S, handler: @escaping StateEnterHandler) throws
  155.72 -
  155.73 -    /**
  155.74 -     Executes a block on the management queue.
  155.75 -     */
  155.76 -    func async(block: @escaping () -> ())
  155.77 -}
   156.1 --- a/pEpForiOS/Util/Capability.swift	Wed Feb 20 11:00:07 2019 +0100
   156.2 +++ b/pEpForiOS/Util/Capability.swift	Mon Mar 18 10:54:14 2019 +0100
   156.3 @@ -8,6 +8,7 @@
   156.4  import Foundation
   156.5  import Contacts
   156.6  import Photos
   156.7 +import pEpIOSToolbox
   156.8  
   156.9  
  156.10  public struct Capability {
   157.1 --- a/pEpForiOS/Util/DebugMergePolicy.swift	Wed Feb 20 11:00:07 2019 +0100
   157.2 +++ b/pEpForiOS/Util/DebugMergePolicy.swift	Mon Mar 18 10:54:14 2019 +0100
   157.3 @@ -8,6 +8,7 @@
   157.4  
   157.5  import Foundation
   157.6  import CoreData
   157.7 +import pEpIOSToolbox
   157.8  
   157.9  class DebugMergePolicy: NSMergePolicy {
  157.10      override func resolve(mergeConflicts list: [Any]) throws {
   158.1 --- a/pEpForiOS/Util/Extensions/Array+SortingAndSearching.swift	Wed Feb 20 11:00:07 2019 +0100
   158.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   158.3 @@ -1,109 +0,0 @@
   158.4 -//
   158.5 -//  Array+SortingAndSearching.swift
   158.6 -//  pEp
   158.7 -//
   158.8 -//  Created by Andreas Buff on 28.08.18.
   158.9 -//  Copyright © 2018 p≡p Security S.A. All rights reserved.
  158.10 -//
  158.11 -
  158.12 -import Foundation
  158.13 -
  158.14 -extension Array {
  158.15 -
  158.16 -    /*
  158.17 -     Should `true` if the first element should be inserted before the second one,
  158.18 -     `false` otherwise.
  158.19 -     */
  158.20 -    public typealias ShouldInsertFunc = (Element, Element) -> Bool
  158.21 -
  158.22 -    typealias Comparator = (Element, Element) -> ComparisonResult
  158.23 -
  158.24 -    /**
  158.25 -     At which position should the given item be added in order to maintain the sorting?
  158.26 -     Binary version.
  158.27 -     */
  158.28 -    public func insertIndex(
  158.29 -        element: Element, shouldInsert: ShouldInsertFunc) -> Int {
  158.30 -        var lowerIndex = 0;
  158.31 -        var upperIndex = count - 1
  158.32 -
  158.33 -        while (true) {
  158.34 -            if lowerIndex == upperIndex {
  158.35 -                let lower = maxIndex(x: 0, y: lowerIndex - 1)
  158.36 -                let upper = minIndex(x: upperIndex + 1, y: count - 1)
  158.37 -                return insertIndexByTraversing(
  158.38 -                    element: element, from: lower, to: upper, shouldInsert: shouldInsert)
  158.39 -            }
  158.40 -            if (lowerIndex > upperIndex) {
  158.41 -                return count
  158.42 -            }
  158.43 -            let currentIndex = (lowerIndex + upperIndex) / 2
  158.44 -            let currentItem = self[currentIndex]
  158.45 -
  158.46 -            if shouldInsert(element, currentItem) {
  158.47 -                // before
  158.48 -                upperIndex = currentIndex - 1
  158.49 -            } else {
  158.50 -                // after
  158.51 -                lowerIndex = currentIndex + 1
  158.52 -            }
  158.53 -        }
  158.54 -    }
  158.55 -
  158.56 -    func maxIndex<T: Comparable>(x: T, y: T) -> T {
  158.57 -        if y > x {
  158.58 -            return y
  158.59 -        }
  158.60 -        return x
  158.61 -    }
  158.62 -
  158.63 -    func minIndex<T: Comparable>(x: T, y: T) -> T {
  158.64 -        if y < x {
  158.65 -            return y
  158.66 -        }
  158.67 -        return x
  158.68 -    }
  158.69 -
  158.70 -   func insertIndexByTraversing(element: Element, from: Int, to: Int,
  158.71 -                                        shouldInsert: ShouldInsertFunc) -> Int {
  158.72 -        if from == to {
  158.73 -            return from
  158.74 -        }
  158.75 -        for i in from...to {
  158.76 -            if shouldInsert(element, self[i]) {
  158.77 -                return i
  158.78 -            }
  158.79 -        }
  158.80 -        return to + 1
  158.81 -    }
  158.82 -
  158.83 -    func insertIndexByTraversing(element: Element, shouldInsert: ShouldInsertFunc) -> Int? {
  158.84 -        return insertIndexByTraversing(
  158.85 -            element: element, from: 0, to: count - 1, shouldInsert: shouldInsert)
  158.86 -    }
  158.87 -
  158.88 -    func binarySearch(element: Element, comparator: Comparator) -> Int? {
  158.89 -        var lowerIndex = 0;
  158.90 -        var upperIndex = count - 1
  158.91 -
  158.92 -        while (true) {
  158.93 -            if (lowerIndex > upperIndex) {
  158.94 -                return nil
  158.95 -            }
  158.96 -
  158.97 -            let currentIndex = (lowerIndex + upperIndex) / 2
  158.98 -
  158.99 -            let comparison = comparator(self[currentIndex], element)
 158.100 -
 158.101 -            if comparison == .orderedSame {
 158.102 -                return currentIndex
 158.103 -            } else {
 158.104 -                if comparison == .orderedDescending {
 158.105 -                    upperIndex = currentIndex - 1
 158.106 -                } else {
 158.107 -                    lowerIndex = currentIndex + 1
 158.108 -                }
 158.109 -            }
 158.110 -        }
 158.111 -    }
 158.112 -}
   159.1 --- a/pEpForiOS/Util/Extensions/ConnectionTransport+AccountSettings.swift	Wed Feb 20 11:00:07 2019 +0100
   159.2 +++ b/pEpForiOS/Util/Extensions/ConnectionTransport+AccountSettings.swift	Mon Mar 18 10:54:14 2019 +0100
   159.3 @@ -7,6 +7,7 @@
   159.4  //
   159.5  
   159.6  import Foundation
   159.7 +import pEpIOSToolbox
   159.8  
   159.9  extension ConnectionTransport {
  159.10      init(accountSettingsTransport: AccountSettingsServerTransport) {
   160.1 --- a/pEpForiOS/Util/Extensions/Data+Extensions.swift	Wed Feb 20 11:00:07 2019 +0100
   160.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   160.3 @@ -1,44 +0,0 @@
   160.4 -//
   160.5 -//  NSData+Extensions.swift
   160.6 -//  pEpForiOS
   160.7 -//
   160.8 -//  Created by Dirk Zimmermann on 17/05/16.
   160.9 -//  Copyright © 2016 p≡p Security S.A. All rights reserved.
  160.10 -//
  160.11 -
  160.12 -extension Data {
  160.13 -    public func stringEncodingFromIANACharset(_ charset: String) -> String.Encoding {
  160.14 -        let enc = CFStringConvertIANACharSetNameToEncoding(charset as CFString)
  160.15 -        return String.Encoding(rawValue: CFStringConvertEncodingToNSStringEncoding(enc))
  160.16 -    }
  160.17 -
  160.18 -    public func toStringWithIANACharset(_ charset: String?) -> String? {
  160.19 -        if let cs = charset {
  160.20 -            let enc = stringEncodingFromIANACharset(cs)
  160.21 -            return String(data: self, encoding: enc)?.applyingDos2Unix()
  160.22 -        } else {
  160.23 -            return String(data: self, encoding: String.Encoding.utf8)?.applyingDos2Unix()
  160.24 -        }
  160.25 -    }
  160.26 -
  160.27 -    public func debugSave(basePath: String, fileName: String, ext: String = "data") {
  160.28 -        let dateDesc = Date().description(with: nil)
  160.29 -        let filePath = "\(basePath)/\(fileName)_\(dateDesc).\(ext)"
  160.30 -        let url = URL(fileURLWithPath: filePath)
  160.31 -        do {
  160.32 -            try write(to: url)
  160.33 -        } catch {
  160.34 -            Logger.utilLogger.error("Could not save to %{public}@", url.absoluteString)
  160.35 -        }
  160.36 -    }
  160.37 -
  160.38 -    public func debugSaveAsJson(basePath: String, fileName: String, ext: String = "data") {
  160.39 -        do {
  160.40 -            let jsonData = try JSONSerialization.data(
  160.41 -                withJSONObject: self, options: .prettyPrinted)
  160.42 -            jsonData.debugSave(basePath: basePath, fileName: fileName, ext: ext)
  160.43 -        } catch let err {
  160.44 -            Logger.utilLogger.error("%{public}@", err.localizedDescription)
  160.45 -        }
  160.46 -    }
  160.47 -}
   161.1 --- a/pEpForiOS/Util/Extensions/Date+Extension.swift	Wed Feb 20 11:00:07 2019 +0100
   161.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   161.3 @@ -1,52 +0,0 @@
   161.4 -//
   161.5 -//  Date+Extension.swift
   161.6 -//  pEpForiOS
   161.7 -//
   161.8 -//  Created by Dirk Zimmermann on 27/03/2017.
   161.9 -//  Copyright © 2017 p≡p Security S.A. All rights reserved.
  161.10 -//
  161.11 -
  161.12 -import Foundation
  161.13 -
  161.14 -extension Date {
  161.15 -    public func isToday() -> Bool {
  161.16 -        let cal = Calendar.current
  161.17 -        return cal.isDateInToday(self)
  161.18 -    }
  161.19 -
  161.20 -    public func isRecent() -> Bool {
  161.21 -        let cal = Calendar.current
  161.22 -        let now = Date()
  161.23 -        let comps = cal.dateComponents([.day], from: self, to: now)
  161.24 -        if let days = comps.day {
  161.25 -            return days < 7
  161.26 -        }
  161.27 -        return false
  161.28 -    }
  161.29 -
  161.30 -    public func smartString() -> String {
  161.31 -        if isToday() {
  161.32 -            let formatter = DateFormatter()
  161.33 -            formatter.dateStyle = .none
  161.34 -            formatter.timeStyle = .short
  161.35 -            return formatter.string(from: self)
  161.36 -        }
  161.37 -        if isRecent() {
  161.38 -            let formatter = DateFormatter()
  161.39 -            formatter.dateFormat = "EEEE"
  161.40 -            return formatter.string(from: self)
  161.41 -        }
  161.42 -
  161.43 -        let formatter = DateFormatter()
  161.44 -        formatter.dateStyle = .medium
  161.45 -        formatter.timeStyle = .none
  161.46 -        return formatter.string(from: self)
  161.47 -    }
  161.48 -
  161.49 -    public func fullString() -> String {
  161.50 -        let formatter = DateFormatter()
  161.51 -        formatter.dateStyle = .short
  161.52 -        formatter.timeStyle = .short
  161.53 -        return formatter.string(from: self)
  161.54 -    }
  161.55 -}
   162.1 --- a/pEpForiOS/Util/Extensions/NSAttributedString+Extensions.swift	Wed Feb 20 11:00:07 2019 +0100
   162.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   162.3 @@ -1,39 +0,0 @@
   162.4 -//
   162.5 -//  NSAttributedString+Extensions.swift
   162.6 -//  pEp
   162.7 -//
   162.8 -//  Created by Andreas Buff on 12.12.17.
   162.9 -//  Copyright © 2017 p≡p Security S.A. All rights reserved.
  162.10 -//
  162.11 -
  162.12 -import Foundation
  162.13 -
  162.14 -extension NSAttributedString {
  162.15 -
  162.16 -    /// Concatenates two attributed strings.
  162.17 -    ///
  162.18 -    /// - Parameters:
  162.19 -    ///   - lhs: first string
  162.20 -    ///   - rhs: string to concatenate to first string
  162.21 -    /// - Returns: lhs + rhs concatenated
  162.22 -    static func +(lhs: NSAttributedString, rhs: NSAttributedString) -> NSAttributedString {
  162.23 -        let result = NSMutableAttributedString()
  162.24 -        result.append(lhs)
  162.25 -        result.append(rhs)
  162.26 -        return result
  162.27 -    }
  162.28 -
  162.29 -    /// Concatenates two strings.
  162.30 -    ///
  162.31 -    /// - Parameters:
  162.32 -    ///   - lhs: first string
  162.33 -    ///   - rhs: string to concatenate to first string
  162.34 -    /// - Returns: lhs + rhs concatenated
  162.35 -    static func +(lhs: NSAttributedString, rhs: String) -> NSAttributedString {
  162.36 -        let result = NSMutableAttributedString()
  162.37 -        result.append(lhs)
  162.38 -        let attributedRhs = NSAttributedString(string: rhs)
  162.39 -        result.append(attributedRhs)
  162.40 -        return result
  162.41 -    }
  162.42 -}
   163.1 --- a/pEpForiOS/Util/Extensions/NSAttributedString+Parsing.swift	Wed Feb 20 11:00:07 2019 +0100
   163.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   163.3 @@ -1,38 +0,0 @@
   163.4 -//
   163.5 -//  NSAttributedString+Parsing.swift
   163.6 -//  pEpForiOS
   163.7 -//
   163.8 -//  Created by Dirk Zimmermann on 22.08.17.
   163.9 -//  Copyright © 2017 p≡p Security S.A. All rights reserved.
  163.10 -//
  163.11 -
  163.12 -import Foundation
  163.13 -import UIKit
  163.14 -
  163.15 -public protocol NSAttributedStringParsingDelegate: class {
  163.16 -    func stringFor(attachment: NSTextAttachment) -> String?
  163.17 -    func stringFor(string: String) -> String?
  163.18 -}
  163.19 -
  163.20 -extension NSAttributedString {
  163.21 -    func convert(delegate: NSAttributedStringParsingDelegate) -> String {
  163.22 -        var resultString = ""
  163.23 -        let string = NSMutableAttributedString(attributedString: self)
  163.24 -        string.fixAttributes(in: string.wholeRange())
  163.25 -
  163.26 -        string.enumerateAttributes(in: string.wholeRange(), options: []) { attrs, r, stop in
  163.27 -            if let attachment = attrs[NSAttributedStringKey(rawValue:"NSAttachment")] as? NSTextAttachment {
  163.28 -                if let attachmentString = delegate.stringFor(attachment: attachment) {
  163.29 -                    resultString = "\(resultString)\(attachmentString)"
  163.30 -                }
  163.31 -            } else {
  163.32 -                let theAttributedString = string.attributedSubstring(from: r)
  163.33 -                let theString = theAttributedString.string
  163.34 -                if let theStringToAppend = delegate.stringFor(string: theString) {
  163.35 -                    resultString = "\(resultString)\(theStringToAppend)"
  163.36 -                }
  163.37 -            }
  163.38 -        }
  163.39 -        return resultString
  163.40 -    }
  163.41 -}
   164.1 --- a/pEpForiOS/Util/Extensions/NSAttributedString+pEp.swift	Wed Feb 20 11:00:07 2019 +0100
   164.2 +++ b/pEpForiOS/Util/Extensions/NSAttributedString+pEp.swift	Mon Mar 18 10:54:14 2019 +0100
   164.3 @@ -7,7 +7,7 @@
   164.4  //
   164.5  
   164.6  import Foundation
   164.7 -
   164.8 +import pEpIOSToolbox
   164.9  import MessageModel
  164.10  
  164.11  class ToMarkdownDelegate: NSAttributedStringParsingDelegate {
   165.1 --- a/pEpForiOS/Util/Extensions/NSRegularExpression+Extension.swift	Wed Feb 20 11:00:07 2019 +0100
   165.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   165.3 @@ -1,22 +0,0 @@
   165.4 -//
   165.5 -//  NSRegularExpression+Extension.swift
   165.6 -//  pEpForiOS
   165.7 -//
   165.8 -//  Created by Dirk Zimmermann on 27/03/2017.
   165.9 -//  Copyright © 2017 p≡p Security S.A. All rights reserved.
  165.10 -//
  165.11 -
  165.12 -import Foundation
  165.13 -
  165.14 -extension NSRegularExpression {
  165.15 -    /**
  165.16 -     Does the first match cover the whole string?
  165.17 -     */
  165.18 -    public func matchesWhole(string: String?) -> Bool {
  165.19 -        if let s = string {
  165.20 -            let range = rangeOfFirstMatch(in: s, options: [], range: s.wholeRange())
  165.21 -            return NSEqualRanges(range, s.wholeRange())
  165.22 -        }
  165.23 -        return false
  165.24 -    }
  165.25 -}
   166.1 --- a/pEpForiOS/Util/Extensions/OperationQueue+Extension.swift	Wed Feb 20 11:00:07 2019 +0100
   166.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   166.3 @@ -1,24 +0,0 @@
   166.4 -//
   166.5 -//  OperationQueue+Extension.swift
   166.6 -//  pEpForiOS
   166.7 -//
   166.8 -//  Created by Dirk Zimmermann on 01/11/16.
   166.9 -//  Copyright © 2016 p≡p Security S.A. All rights reserved.
  166.10 -//
  166.11 -
  166.12 -extension OperationQueue {
  166.13 -    /**
  166.14 -     Adds all operations to the given queue, and calls the completion block once
  166.15 -     they all have finished.
  166.16 -     */
  166.17 -    func batch(operations: [Operation], completionBlock: (() -> Swift.Void)?) {
  166.18 -        let finishOp = BlockOperation(block: {
  166.19 -            completionBlock?()
  166.20 -        })
  166.21 -        for op in operations {
  166.22 -            finishOp.addDependency(op)
  166.23 -            addOperation(op)
  166.24 -        }
  166.25 -        addOperation(finishOp)
  166.26 -    }
  166.27 -}
   167.1 --- a/pEpForiOS/Util/Extensions/PEP_rating+Extension.swift	Wed Feb 20 11:00:07 2019 +0100
   167.2 +++ b/pEpForiOS/Util/Extensions/PEP_rating+Extension.swift	Mon Mar 18 10:54:14 2019 +0100
   167.3 @@ -7,6 +7,7 @@
   167.4  //
   167.5  
   167.6  import Foundation
   167.7 +import pEpIOSToolbox
   167.8  
   167.9  extension PEP_rating {
  167.10  
   168.1 --- a/pEpForiOS/Util/Extensions/String+Attachment.swift	Wed Feb 20 11:00:07 2019 +0100
   168.2 +++ b/pEpForiOS/Util/Extensions/String+Attachment.swift	Mon Mar 18 10:54:14 2019 +0100
   168.3 @@ -7,6 +7,7 @@
   168.4  //
   168.5  
   168.6  import Foundation
   168.7 +import pEpIOSToolbox
   168.8  
   168.9  extension String {
  168.10      public func firstMatch(pattern: String, rangeNumber: Int = 1) -> String? {
   169.1 --- a/pEpForiOS/Util/Extensions/String+Email.swift	Wed Feb 20 11:00:07 2019 +0100
   169.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   169.3 @@ -1,108 +0,0 @@
   169.4 -//
   169.5 -//  String+Email.swift
   169.6 -//  pEp
   169.7 -//
   169.8 -//  Created by Dirk Zimmermann on 20.12.17.
   169.9 -//  Copyright © 2017 p≡p Security S.A. All rights reserved.
  169.10 -//
  169.11 -
  169.12 -import Foundation
  169.13 -
  169.14 -/**
  169.15 - Methods that deal with email detection.
  169.16 - */
  169.17 -extension String {
  169.18 -    private static let gmailRegex = emailProviderDetectionPattern(providerDomainPart: "gmail")
  169.19 -    private static let yahooRegex = emailProviderDetectionPattern(providerDomainPart: "yahoo")
  169.20 -
  169.21 -    public static func emailProviderDetectionPattern(providerDomainPart: String) -> NSRegularExpression {
  169.22 -        return try! NSRegularExpression(
  169.23 -            // character classes: https://en.wikipedia.org/wiki/Unicode_character_property
  169.24 -            pattern: "[-_[\\p{Ll}\\p{Lu}\\p{Nd}.]]+@\(providerDomainPart)\\.[a-z]+",
  169.25 -            options: [])
  169.26 -    }
  169.27 -
  169.28 -    public var isGmailAddress: Bool {
  169.29 -        return String.gmailRegex.matchesWhole(string: self.lowercased())
  169.30 -    }
  169.31 -
  169.32 -    public var isYahooAddress: Bool {
  169.33 -        return String.yahooRegex.matchesWhole(string: self.lowercased())
  169.34 -    }
  169.35 -
  169.36 -    /**
  169.37 -     Very rudimentary test whether this String is a valid email.
  169.38 -     - Returns: `true` if the number of matches are exactly 1, `false` otherwise.
  169.39 -     */
  169.40 -    public func isProbablyValidEmail() -> Bool {
  169.41 -        guard let indexOfAt = index(of: "@") else {
  169.42 -            return false
  169.43 -        }
  169.44 -        let localPart = self[..<indexOfAt]
  169.45 -        let indexOfDomainPart = index(after: indexOfAt)
  169.46 -        let domainPart = self[indexOfDomainPart...]
  169.47 -        return localPart.isValidEmailLocalPart() && domainPart.isValidDomain()
  169.48 -    }
  169.49 -
  169.50 -    /**
  169.51 -     Character range for small latin letters.
  169.52 -     - Note: This is used by a `Substring` extension, but it can probably be found
  169.53 -     easier here.
  169.54 -     */
  169.55 -    public static let rangeLatinLetter: ClosedRange<Character> = "a"..."z"
  169.56 -
  169.57 -    /**
  169.58 -     Character range for capital latin letters.
  169.59 -     - Note: This is used by a `Substring` extension, but it can probably be found
  169.60 -     easier here.
  169.61 -     */
  169.62 -    public static let rangeCapitalLatinLetter: ClosedRange<Character> = "A"..."Z"
  169.63 -
  169.64 -    /**
  169.65 -     Character range for numerical letters.
  169.66 -     - Note: This is used by a `Substring` extension, but it can probably be found
  169.67 -     easier here.
  169.68 -     */
  169.69 -    public static let rangeNumerical: ClosedRange<Character> = "0"..."9"
  169.70 -
  169.71 -    /**
  169.72 -     See https://en.wikipedia.org/wiki/Email_address#Domain and
  169.73 -     the `Substring` method of the same name.
  169.74 -     */
  169.75 -    public func isValidDomainDnsLabel() -> Bool {
  169.76 -        return self[startIndex..<endIndex].isValidDomainDnsLabel()
  169.77 -    }
  169.78 -
  169.79 -    /**
  169.80 -     See https://en.wikipedia.org/wiki/Email_address#Domain and
  169.81 -     the `Substring` method of the same name.
  169.82 -     */
  169.83 -    public func isValidDomain() -> Bool {
  169.84 -        return self[startIndex..<endIndex].isValidDomain()
  169.85 -    }
  169.86 -
  169.87 -    /**
  169.88 -     See https://en.wikipedia.org/wiki/Email_address#Local-part and
  169.89 -     the `Substring` method of the same name.
  169.90 -     */
  169.91 -    public func isValidEmailLocalPart() -> Bool {
  169.92 -        return self[startIndex..<endIndex].isValidEmailLocalPart()
  169.93 -    }
  169.94 -
  169.95 -    /**
  169.96 -     Contains a String like e.g. "email1, email2, email3", only probably valid emails?
  169.97 -     - Parameter delimiter: The delimiter that separates the emails.
  169.98 -     - Returns: True if all email parts yield true with `isProbablyValidEmail`.
  169.99 -     */
 169.100 -    public func isProbablyValidEmailListSeparatedBy(_ delimiter: String = ",") -> Bool {
 169.101 -        let emails = self.components(separatedBy: delimiter).map({
 169.102 -            $0.trimmed()
 169.103 -        })
 169.104 -        for e in emails {
 169.105 -            if e.matches(pattern: "\(delimiter)") || !e.isProbablyValidEmail() {
 169.106 -                return false
 169.107 -            }
 169.108 -        }
 169.109 -        return true
 169.110 -    }
 169.111 -}
   170.1 --- a/pEpForiOS/Util/Extensions/String+Extensions.swift	Wed Feb 20 11:00:07 2019 +0100
   170.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   170.3 @@ -1,429 +0,0 @@
   170.4 -//
   170.5 -//  String+Extensions.swift
   170.6 -//  pEpForiOS
   170.7 -//
   170.8 -//  Created by Dirk Zimmermann on 13/07/16.
   170.9 -//  Copyright © 2016 p≡p Security S.A. All rights reserved.
  170.10 -//
  170.11 -
  170.12 -import UIKit
  170.13 -
  170.14 -public extension String {
  170.15 -
  170.16 -    static let bug1442 = "bug1442"
  170.17 -    static let returnKey = "\n"
  170.18 -    static let space = " "
  170.19 -
  170.20 -    static let unquoteRegex = try! NSRegularExpression(pattern: "^\"(.*)\"$", options: [])
  170.21 -
  170.22 -    static let namePartOfEmailRegex = try! NSRegularExpression(pattern: "^([^@]+)@", options: [])
  170.23 -
  170.24 -    static let endWhiteSpaceRegex = try! NSRegularExpression(pattern: "^(.*?)\\s*$", options: [])
  170.25 -
  170.26 -    static let newlineRegex = try! NSRegularExpression(
  170.27 -        pattern: "(\\n|\\r\\n)+", options: [])
  170.28 -
  170.29 -    static let threeOrMoreNewlinesRegex = try! NSRegularExpression(pattern: "(\\n|\\r\\n){3,}",
  170.30 -                                                                   options: [])
  170.31 -
  170.32 -    static let fileExtensionRegex = try! NSRegularExpression(pattern: "^([^.]+)\\.([^.]+)$",
  170.33 -                                                             options: [])
  170.34 -
  170.35 -    /**
  170.36 -     Trims whitespace from back and front.
  170.37 -     */
  170.38 -    public func trimmed() -> String {
  170.39 -        return trimmingCharacters(in: .whitespacesAndNewlines)
  170.40 -    }
  170.41 -    
  170.42 -    public func contains(find: String) -> Bool {
  170.43 -        return (self.range(of: find, options: .caseInsensitive) != nil)
  170.44 -    }
  170.45 -
  170.46 -    public func unquote() -> String {
  170.47 -        if let match = String.unquoteRegex.firstMatch(
  170.48 -                in: self, options: [],
  170.49 -                range: wholeRange()) {
  170.50 -                let r1 = match.range(at: 1)
  170.51 -                let name = (self as NSString).substring(with: r1)
  170.52 -                return name
  170.53 -            }
  170.54 -        return self
  170.55 -    }
  170.56 -
  170.57 -    public func trimObjectReplacementCharacters() -> String {
  170.58 -        // UITextView places this character if you delete an attachment, which leads to a
  170.59 -        // non-empty string.
  170.60 -        // https://www.fileformat.info/info/unicode/char/fffc/index.htm
  170.61 -        let objectReplacementCharacter = "\u{FFFC}"
  170.62 -
  170.63 -        return self.replacingOccurrences(of: objectReplacementCharacter, with: "")
  170.64 -    }
  170.65 -
  170.66 -    /**
  170.67 -     Runs `trimmedWhiteSpace`, `unquote`, and `trimmedWhiteSpace` again.
  170.68 -     */
  170.69 -    public func fullyUnquoted() -> String {
  170.70 -        return trimmed().unquote().trimmed()
  170.71 -    }
  170.72 -
  170.73 -    /**
  170.74 -     - Returns: The name part of an email, e.g. "test@blah.com" -> "test"
  170.75 -     */
  170.76 -    public func namePartOfEmail() -> String {
  170.77 -            let matches = String.namePartOfEmailRegex.matches(
  170.78 -                in: self, options: [], range: wholeRange())
  170.79 -            if matches.count == 1 {
  170.80 -                let m = matches[0]
  170.81 -                let r = m.range(at: 1)
  170.82 -                if r.location != NSNotFound {
  170.83 -                    let s = self as NSString
  170.84 -                    let result = s.substring(with: r)
  170.85 -                    return result
  170.86 -                }
  170.87 -            }
  170.88 -        return self.replacingOccurrences(of: "@", with: "_")
  170.89 -    }
  170.90 -
  170.91 -    public func containsString(_ substring: String, ignoreCase: Bool = true,
  170.92 -                               ignoreDiacritic: Bool = true) -> Bool {
  170.93 -
  170.94 -        if substring == "" {
  170.95 -            return true
  170.96 -        }
  170.97 -
  170.98 -        var options = NSString.CompareOptions()
  170.99 -
 170.100 -        if ignoreCase { options.formUnion(.caseInsensitive) }
 170.101 -        if ignoreDiacritic { options.formUnion(.diacriticInsensitive) }
 170.102 -
 170.103 -        return self.range(of: substring, options: options) != nil
 170.104 -    }
 170.105 -
 170.106 -    /**
 170.107 -     Mimicks the `NSString` version.
 170.108 -     */
 170.109 -    public func stringByReplacingCharactersInRange(_ range: NSRange,
 170.110 -                                                   withString replacement: String) -> String {
 170.111 -        let s = self as NSString
 170.112 -        return s.replacingCharacters(in: range, with: replacement)
 170.113 -    }
 170.114 -
 170.115 -    /// Replaces all matches of the given regex pattern with a given string.
 170.116 -    ///
 170.117 -    /// - Parameters:
 170.118 -    ///   - pattern: pattern to match
 170.119 -    ///   - replacee: string to raplace matches with
 170.120 -    mutating func replaceRegexMatches(of pattern: String, with replacee: String) {
 170.121 -        do {
 170.122 -            let regex =
 170.123 -                try NSRegularExpression(pattern: pattern,
 170.124 -                                        options: NSRegularExpression.Options.caseInsensitive)
 170.125 -            let range = NSMakeRange(0, self.count)
 170.126 -            self = regex.stringByReplacingMatches(in: self,
 170.127 -                                                  options: [],
 170.128 -                                                  range: range,
 170.129 -                                                  withTemplate: replacee)
 170.130 -        } catch {
 170.131 -            return
 170.132 -        }
 170.133 -    }
 170.134 -
 170.135 -    /// Removes all matches of the given regex pattern.
 170.136 -    ///
 170.137 -    /// - Parameter pattern: regex patterns whichs matches should be removed
 170.138 -    mutating func removeRegexMatches(of pattern: String) {
 170.139 -        replaceRegexMatches(of: pattern, with: "")
 170.140 -    }
 170.141 -
 170.142 -    func stringByRemovingRegexMatches(of pattern: String) -> String {
 170.143 -        return self.stringByReplacingRegexMatches(of: pattern, with: "")
 170.144 -    }
 170.145 -
 170.146 -    func stringByReplacingRegexMatches(of pattern: String, with replacee: String) -> String {
 170.147 -        var result = self
 170.148 -        do {
 170.149 -            let regex =
 170.150 -                try NSRegularExpression(pattern: pattern,
 170.151 -                                        options: NSRegularExpression.Options.caseInsensitive)
 170.152 -            let range = NSMakeRange(0, self.count)
 170.153 -            result = regex.stringByReplacingMatches(in: self,
 170.154 -                                                    options: [],
 170.155 -                                                    range: range,
 170.156 -                                                    withTemplate: replacee)
 170.157 -        } catch {
 170.158 -            Logger.utilLogger.errorAndCrash("Catched!")
 170.159 -            return result
 170.160 -        }
 170.161 -        return result
 170.162 -    }
 170.163 -
 170.164 -    /**
 170.165 -     Does this String match the given regex pattern? Without any options.
 170.166 -     - Parameter pattern: The pattern to match.
 170.167 -     */
 170.168 -    public func matches(pattern: String) -> Bool {
 170.169 -        return matchesPattern(pattern, reOptions: [])
 170.170 -    }
 170.171 -
 170.172 -    /**
 170.173 -     Does this String match the given regex pattern?
 170.174 -     - Parameter pattern: The pattern to match.
 170.175 -     - Parameter reOptions: Options given to the regular expression init.
 170.176 -     */
 170.177 -    public func matchesPattern(
 170.178 -        _ pattern: String, reOptions: NSRegularExpression.Options) -> Bool {
 170.179 -        do {
 170.180 -            let regex = try NSRegularExpression(pattern: pattern, options: reOptions)
 170.181 -            let matches = regex.matches(in: self, options: [], range: wholeRange())
 170.182 -            return matches.count > 0
 170.183 -        } catch {
 170.184 -            Logger.utilLogger.errorAndCrash("%{public}@", error.localizedDescription)
 170.185 -        }
 170.186 -        return false
 170.187 -    }
 170.188 -
 170.189 -    /**
 170.190 -     - Returns: True if this String consists only of whitespace.
 170.191 -     */
 170.192 -    public func isOnlyWhiteSpace() -> Bool {
 170.193 -        let whiteSpacePattern = "^\\s*$"
 170.194 -        return matches(pattern: whiteSpacePattern)
 170.195 -    }
 170.196 -
 170.197 -    /**
 170.198 -     Removes a matching pattern from the end of the String. Note that the '$' will be added
 170.199 -     by this method.
 170.200 -     */
 170.201 -    public func removeTrailingPattern(_ pattern: String) -> String {
 170.202 -        do {
 170.203 -            let regex = try NSRegularExpression(pattern: "(.*?)\(pattern)$", options: [])
 170.204 -            let matches = regex.matches(in: self, options: [], range: wholeRange())
 170.205 -            if matches.count == 1 {
 170.206 -                let m = matches[0]
 170.207 -                let r = m.range(at: 1)
 170.208 -                if r.location != NSNotFound {
 170.209 -                    let s = self as NSString
 170.210 -                    let result = s.substring(with: r)
 170.211 -                    return result
 170.212 -                }
 170.213 -            }
 170.214 -        } catch {
 170.215 -            Logger.utilLogger.errorAndCrash("%{public}@",
 170.216 -                                                        error.localizedDescription)
 170.217 -        }
 170.218 -        return self
 170.219 -    }
 170.220 -
 170.221 -    /**
 170.222 -     Removes a matching pattern from the beginning of the String. Note that the '^' will be added
 170.223 -     by this method.
 170.224 -     */
 170.225 -    public func removeLeadingPattern(_ pattern: String) -> String {
 170.226 -        do {
 170.227 -            let regex = try NSRegularExpression(pattern: "^\(pattern)(.*?)$", options: [])
 170.228 -            let matches = regex.matches(in: self, options: [], range: wholeRange())
 170.229 -            if matches.count == 1 {
 170.230 -                let m = matches[0]
 170.231 -                let r = m.range(at: 1)
 170.232 -                if r.location != NSNotFound {
 170.233 -                    let s = self as NSString
 170.234 -                    let result = s.substring(with: r)
 170.235 -                    return result
 170.236 -                }
 170.237 -            }
 170.238 -        } catch {
 170.239 -            Logger.utilLogger.errorAndCrash("%{public}@",
 170.240 -                                                        error.localizedDescription)
 170.241 -        }
 170.242 -        return self
 170.243 -    }
 170.244 -
 170.245 -    /**
 170.246 -    - Returns: The given string or "" (the empty `String`) if that `String` is nil.
 170.247 -     */
 170.248 -    public static func orEmpty(_ string: String?) -> String {
 170.249 -        if let s = string {
 170.250 -            return s
 170.251 -        }
 170.252 -        return ""
 170.253 -    }
 170.254 -
 170.255 -    /**
 170.256 -     - Returns: True if the given string starts with the given prefix.
 170.257 -     */
 170.258 -    public func startsWith(_ prefix: String) -> Bool {
 170.259 -        return matches(pattern: "^\(prefix)")
 170.260 -    }
 170.261 -
 170.262 -    public func hasExtension(_ ext: String) -> Bool {
 170.263 -        let suffix = ext.startsWith(".") ? ext : ".\(ext)"
 170.264 -        return endsWith(suffix)
 170.265 -    }
 170.266 -
 170.267 -    public func endsWith(_ suffix: String) -> Bool {
 170.268 -        let suffixCount = suffix.count
 170.269 -        if self.count < suffixCount {
 170.270 -            return false
 170.271 -        }
 170.272 -        let fromWhere = index(endIndex, offsetBy: -suffixCount)
 170.273 -        let end = self[fromWhere...]
 170.274 -        return end == suffix
 170.275 -    }
 170.276 -
 170.277 -    public func replaceNewLinesWith(_ delimiter: String) -> String {
 170.278 -        return String.newlineRegex.stringByReplacingMatches(
 170.279 -            in: self, options: [], range: self.wholeRange(), withTemplate: delimiter)
 170.280 -    }
 170.281 -
 170.282 -    /**
 170.283 -     - Returns: A new string that never contains 3 or more consecutive newlines.
 170.284 -     */
 170.285 -    public func eliminateExcessiveNewLines() -> String {
 170.286 -        return String.threeOrMoreNewlinesRegex.stringByReplacingMatches(
 170.287 -            in: self, options: [], range: self.wholeRange(), withTemplate: "\n\n")
 170.288 -    }
 170.289 -
 170.290 -    public func splitFileExtension() -> (String, String?) {
 170.291 -        if let match = String.fileExtensionRegex.firstMatch(
 170.292 -            in: self, options: [],
 170.293 -            range: wholeRange()) {
 170.294 -            let r1 = match.range(at: 1)
 170.295 -            let name = (self as NSString).substring(with: r1)
 170.296 -            let r2 = match.range(at: 2)
 170.297 -            let ext = (self as NSString).substring(with: r2)
 170.298 -            return (name, ext)
 170.299 -        }
 170.300 -        return (self, nil)
 170.301 -    }
 170.302 -
 170.303 -    /**
 170.304 -     Transforms the typical Window/DOS line endings into UNIX ones.
 170.305 -     - Returns: A new string with all newlines being UNIX ones (just "\n").
 170.306 -     */
 170.307 -    public func applyingDos2Unix() -> String {
 170.308 -        return replacingOccurrences(of: "\r\n", with: "\n")
 170.309 -    }
 170.310 -
 170.311 -    /**
 170.312 -     Equivalent to the drop functions. Returns a substring that comprises the first maxCount
 170.313 -     characters.
 170.314 -     */
 170.315 -    public func take(maxCount: Int) -> String {
 170.316 -        let theLength = count
 170.317 -        if maxCount >= theLength {
 170.318 -            return self
 170.319 -        } else {
 170.320 -            return String(dropLast(theLength - maxCount))
 170.321 -        }
 170.322 -    }
 170.323 -}
 170.324 -
 170.325 -public extension NSAttributedString {
 170.326 -    
 170.327 -    public func wholeRange() -> NSRange {
 170.328 -        return NSRange(location: 0, length: length)
 170.329 -    }
 170.330 -}
 170.331 -
 170.332 -public extension Character {
 170.333 -    public func isWhitespace() -> Bool {
 170.334 -        switch self {
 170.335 -        case " ", "\t", "\n", "\r", "\r\n":
 170.336 -            return true
 170.337 -        default:
 170.338 -            return false
 170.339 -        }
 170.340 -    }
 170.341 -
 170.342 -    public func isNewline() -> Bool {
 170.343 -        switch self {
 170.344 -        case "\n", "\r", "\r\n":
 170.345 -            return true
 170.346 -        default:
 170.347 -            return false
 170.348 -        }
 170.349 -    }
 170.350 -}
 170.351 -
 170.352 -// MARK: - Extensions for drawing initials from users
 170.353 -
 170.354 -extension String {
 170.355 -    /**
 170.356 -     - Returns: The first part of a String, with a maximum length of `ofLength`.
 170.357 -     */
 170.358 -    func prefix(ofLength: Int) -> String {
 170.359 -        if self.count >= ofLength {
 170.360 -            let start = self.startIndex
 170.361 -            return String(prefix(upTo: self.index(start, offsetBy: ofLength)))
 170.362 -        } else {
 170.363 -            return self
 170.364 -        }
 170.365 -    }
 170.366 -
 170.367 -    /**
 170.368 -     - Returns: A list of words contained in that String. Primitively separates by
 170.369 -     delimiters like "-", or " ".
 170.370 -     */
 170.371 -    func tokens() -> [String] {
 170.372 -        return self.components(separatedBy: CharacterSet(charactersIn: "- ")).map {
 170.373 -            return $0.trimmingCharacters(in: .whitespacesAndNewlines)
 170.374 -        }
 170.375 -    }
 170.376 -
 170.377 -    /**
 170.378 -     - Returns: The initials of the String interpreted as a name,
 170.379 -     that is ideally the first letters of the given name and the last name.
 170.380 -     If that is not possible, improvisations are used.
 170.381 -     */
 170.382 -    func initials() -> String {
 170.383 -        let words = tokens()
 170.384 -        if words.count == 0 {
 170.385 -            return "?"
 170.386 -        }
 170.387 -        if words.count == 1 {
 170.388 -            return self.prefix(ofLength: 2)
 170.389 -        }
 170.390 -        let word1 = words[0]
 170.391 -        let word2 = words[words.count - 1]
 170.392 -        return "\(word1.prefix(ofLength: 1).capitalized)\(word2.prefix(ofLength: 1).capitalized)"
 170.393 -    }
 170.394 -
 170.395 -    /**
 170.396 -     Draws `text` in the current context in the given `color`, centered in a rectangle with
 170.397 -     size `size`.
 170.398 -     */
 170.399 -    func draw(centeredIn size: CGSize, color: UIColor, font: UIFont) {
 170.400 -        func center(size: CGSize, inRect: CGRect) -> CGRect {
 170.401 -            let xStart = round(inRect.size.width / 2 - size.width / 2)
 170.402 -            let yStart = round(inRect.size.height / 2 - size.height / 2)
 170.403 -            let o = CGPoint(x: xStart, y: yStart)
 170.404 -            return CGRect(origin: o, size: size)
 170.405 -        }
 170.406 -
 170.407 -        let wholeRect = CGRect(origin: CGPoint(x: 0, y: 0), size: size)
 170.408 -        let nsString = self as NSString
 170.409 -        let textAttributes: [NSAttributedStringKey : Any] = [
 170.410 -            NSAttributedStringKey.strokeColor: color,
 170.411 -            NSAttributedStringKey.foregroundColor: color,
 170.412 -            NSAttributedStringKey.font: font]
 170.413 -        let stringSize = nsString.size(withAttributes: textAttributes)
 170.414 -        let textRect = center(size: stringSize, inRect: wholeRect)
 170.415 -        nsString.draw(in: textRect, withAttributes: textAttributes)
 170.416 -    }
 170.417 -
 170.418 -    /**
 170.419 -     - Returns: A string derived from the self with all spaces removed.
 170.420 -     */
 170.421 -    func despaced() -> String {
 170.422 -        var newChars = [Character]()
 170.423 -
 170.424 -        for ch in self {
 170.425 -            if ch != " " {
 170.426 -                newChars.append(ch)
 170.427 -            }
 170.428 -        }
 170.429 -
 170.430 -        return String(newChars)
 170.431 -    }
 170.432 -}
   171.1 --- a/pEpForiOS/Util/Extensions/Substring+Email.swift	Wed Feb 20 11:00:07 2019 +0100
   171.2 +++ b/pEpForiOS/Util/Extensions/Substring+Email.swift	Mon Mar 18 10:54:14 2019 +0100
   171.3 @@ -7,6 +7,7 @@
   171.4  //
   171.5  
   171.6  import Foundation
   171.7 +import pEpUtilities
   171.8  
   171.9  /**
  171.10   Methods for detecting parts of an email.
   172.1 --- a/pEpForiOS/Util/Extensions/Thread+Extension.swift	Wed Feb 20 11:00:07 2019 +0100
   172.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   172.3 @@ -1,31 +0,0 @@
   172.4 -//
   172.5 -//  Thread+Extension.swift
   172.6 -//  pEp
   172.7 -//
   172.8 -//  Created by Dirk Zimmermann on 04.12.18.
   172.9 -//  Copyright © 2018 p≡p Security S.A. All rights reserved.
  172.10 -//
  172.11 -
  172.12 -import Foundation
  172.13 -
  172.14 -extension Thread {
  172.15 -    /**
  172.16 -     Use for debugging.
  172.17 -     */
  172.18 -    public var threadID: String {
  172.19 -        let defaultThreadName = "unknown"
  172.20 -        var threadName = Thread.current.name ?? defaultThreadName
  172.21 -        if threadName.isEmpty {
  172.22 -            threadName = defaultThreadName
  172.23 -        }
  172.24 -        if Thread.isMainThread {
  172.25 -            return "main (\(threadName))"
  172.26 -        } else {
  172.27 -            return "other (\(threadName))"
  172.28 -        }
  172.29 -    }
  172.30 -
  172.31 -    public static var threadID: String {
  172.32 -        return Thread.current.threadID
  172.33 -    }
  172.34 -}
   173.1 --- a/pEpForiOS/Util/GCD.swift	Wed Feb 20 11:00:07 2019 +0100
   173.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   173.3 @@ -1,31 +0,0 @@
   173.4 -//
   173.5 -//  GCD.swift
   173.6 -//  pEpForiOS
   173.7 -//
   173.8 -//  Created by Dirk Zimmermann on 20/04/16.
   173.9 -//  Copyright © 2016 p≡p Security S.A. All rights reserved.
  173.10 -//
  173.11 -
  173.12 -struct GCD {
  173.13 -    /**
  173.14 -     Since you will do this all the time in UI callbacks.
  173.15 -     */
  173.16 -    static func onMain(_ block: @escaping () -> Void) {
  173.17 -        DispatchQueue.main.async(execute: {
  173.18 -            block()
  173.19 -        })
  173.20 -    }
  173.21 -
  173.22 -    /**
  173.23 -     Since you will do this all the time in UI callbacks.
  173.24 -     */
  173.25 -    static func onMainWait(_ block: @escaping () -> Void) {
  173.26 -        if Thread.isMainThread {
  173.27 -            block()
  173.28 -        } else {
  173.29 -            DispatchQueue.main.sync(execute: {
  173.30 -                block()
  173.31 -            })
  173.32 -        }
  173.33 -    }
  173.34 -}
   174.1 --- a/pEpForiOS/Util/IdentityImageTool.swift	Wed Feb 20 11:00:07 2019 +0100
   174.2 +++ b/pEpForiOS/Util/IdentityImageTool.swift	Mon Mar 18 10:54:14 2019 +0100
   174.3 @@ -9,6 +9,7 @@
   174.4  import UIKit
   174.5  import AddressBook
   174.6  import MessageModel
   174.7 +import pEpIOSToolbox
   174.8  
   174.9  class IdentityImageTool {
  174.10      static private let queue = DispatchQueue.global(qos: .userInitiated)
   175.1 --- a/pEpForiOS/Util/LimitedOperationQueue.swift	Wed Feb 20 11:00:07 2019 +0100
   175.2 +++ b/pEpForiOS/Util/LimitedOperationQueue.swift	Mon Mar 18 10:54:14 2019 +0100
   175.3 @@ -7,6 +7,7 @@
   175.4  //
   175.5  
   175.6  import UIKit
   175.7 +import pEpIOSToolbox
   175.8  
   175.9  /**
  175.10   A serialized `OperationQueue` that limits the number of operations in the queue to 2.
   176.1 --- a/pEpForiOS/Util/Log+ASL/Log+ASL.swift	Wed Feb 20 11:00:07 2019 +0100
   176.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   176.3 @@ -1,212 +0,0 @@
   176.4 -//
   176.5 -//  Log+ASL.swift
   176.6 -//  pEp
   176.7 -//
   176.8 -//  Created by Dirk Zimmermann on 03.10.18.
   176.9 -//  Copyright © 2018 p≡p Security S.A. All rights reserved.
  176.10 -//
  176.11 -
  176.12 -import Foundation
  176.13 -
  176.14 -class ASLLogger: ActualLoggerProtocol {
  176.15 -    func saveLog(severity: LoggingSeverity,
  176.16 -                 entity: String,
  176.17 -                 description: String,
  176.18 -                 comment: String) {
  176.19 -        let logMessage = asl_new(UInt32(ASL_TYPE_MSG))
  176.20 -
  176.21 -        asl_set(logMessage, ASL_KEY_SENDER, sender)
  176.22 -        asl_set(logMessage, ASL_KEY_FACILITY, entity)
  176.23 -        asl_set(logMessage, ASL_KEY_MSG, "\(description) [\(comment)]")
  176.24 -        asl_set(logMessage, ASL_KEY_LEVEL, "\(severity.aslLevel())")
  176.25 -
  176.26 -        let nowDate = Date()
  176.27 -        let dateString = "\(Int(nowDate.timeIntervalSince1970))"
  176.28 -        asl_set(logMessage, ASL_KEY_TIME, dateString)
  176.29 -
  176.30 -        asl_set(logMessage, ASL_KEY_READ_UID, "-1")
  176.31 -
  176.32 -        asl_send(self.consoleClient, logMessage)
  176.33 -        asl_free(logMessage)
  176.34 -    }
  176.35 -
  176.36 -    func retrieveLog() -> String {
  176.37 -        let query = asl_new(UInt32(ASL_TYPE_QUERY))
  176.38 -
  176.39 -        var result = asl_set_query(
  176.40 -            query,
  176.41 -            ASL_KEY_SENDER,
  176.42 -            sender,
  176.43 -            UInt32(ASL_QUERY_OP_EQUAL))
  176.44 -        ASLLogger.checkASLSuccess(result: result, comment: "asl_set_query ASL_KEY_SENDER")
  176.45 -
  176.46 -        let fromDate = Date(timeInterval: -600, since: Date())
  176.47 -        let fromDateString = "\(Int(fromDate.timeIntervalSince1970))"
  176.48 -        result = asl_set_query(
  176.49 -            query,
  176.50 -            ASL_KEY_TIME,
  176.51 -            fromDateString,
  176.52 -            UInt32(ASL_QUERY_OP_GREATER_EQUAL))
  176.53 -        ASLLogger.checkASLSuccess(result: result, comment: "asl_set_query ASL_KEY_TIME")
  176.54 -
  176.55 -        let theClient = createConsoleLogger()
  176.56 -
  176.57 -        let response = asl_search(theClient, query)
  176.58 -        var next = asl_next(response)
  176.59 -        var logString = ""
  176.60 -        while next != nil {
  176.61 -            let timeString = String(cString: asl_get(next, ASL_KEY_TIME))
  176.62 -            let messageString = String(cString: asl_get(next, ASL_KEY_MSG))
  176.63 -            let facilityString = String(cString: asl_get(next, ASL_KEY_FACILITY))
  176.64 -            let levelString = String(cString: asl_get(next, ASL_KEY_LEVEL))
  176.65 -
  176.66 -            let level = levelString.aslLevelStringToASL()
  176.67 -            let ownLevelString = level.criticalityString()
  176.68 -
  176.69 -            var dateString = "<NoTime>"
  176.70 -            if let dateInt = Int(timeString) {
  176.71 -                let date = Date(timeIntervalSince1970: TimeInterval(dateInt))
  176.72 -                dateString = "\(date)"
  176.73 -            }
  176.74 -
  176.75 -            if !logString.isEmpty {
  176.76 -                logString.append("\n")
  176.77 -            }
  176.78 -
  176.79 -            let stringToLog = "\(dateString) [\(ownLevelString)] [\(facilityString)] \(messageString)"
  176.80 -            logString.append(stringToLog)
  176.81 -
  176.82 -            next = asl_next(response)
  176.83 -        }
  176.84 -
  176.85 -        asl_free(query)
  176.86 -        asl_free(response)
  176.87 -        asl_free(theClient)
  176.88 -
  176.89 -        return logString
  176.90 -    }
  176.91 -
  176.92 -    init() {
  176.93 -        self.consoleClient = createConsoleLogger()
  176.94 -    }
  176.95 -
  176.96 -    deinit {
  176.97 -        asl_release(consoleClient)
  176.98 -    }
  176.99 -
 176.100 -    private let sender = "security.pEp.app.iOS"
 176.101 -
 176.102 -    private var consoleClient: aslclient?
 176.103 -
 176.104 -    private func createConsoleLogger() -> asl_object_t {
 176.105 -        return asl_open(self.sender, "default", 0)
 176.106 -    }
 176.107 -
 176.108 -    private static func checkASLSuccess(result: Int32, comment: String) {
 176.109 -        if result != 0 {
 176.110 -            print("error: \(comment)")
 176.111 -        }
 176.112 -    }
 176.113 -}
 176.114 -
 176.115 -extension LoggingSeverity {
 176.116 -    /**
 176.117 -     Maps the internal criticality of a log  message into a subsystem of ASL levels.
 176.118 -
 176.119 -     ASL has the following:
 176.120 -     * ASL_LEVEL_EMERG
 176.121 -     * ASL_LEVEL_ALERT
 176.122 -     * ASL_LEVEL_CRIT
 176.123 -     * ASL_LEVEL_ERR
 176.124 -     * ASL_LEVEL_WARNING
 176.125 -     * ASL_LEVEL_NOTICE
 176.126 -     * ASL_LEVEL_INFO
 176.127 -     * ASL_LEVEL_DEBUG
 176.128 -     */
 176.129 -    func aslLevel() -> Int32 {
 176.130 -        switch self {
 176.131 -        case .verbose:
 176.132 -            return ASL_LEVEL_DEBUG
 176.133 -        case .info:
 176.134 -            return ASL_LEVEL_NOTICE
 176.135 -        case .warning:
 176.136 -            return ASL_LEVEL_WARNING
 176.137 -        case .error:
 176.138 -            return ASL_LEVEL_ERR
 176.139 -        }
 176.140 -    }
 176.141 -}
 176.142 -
 176.143 -extension String {
 176.144 -    func aslLevelStringToASL() -> Int32 {
 176.145 -        switch self {
 176.146 -        case "0":
 176.147 -            return ASL_LEVEL_EMERG
 176.148 -        case "1":
 176.149 -            return ASL_LEVEL_ALERT
 176.150 -        case "2":
 176.151 -            return ASL_LEVEL_CRIT
 176.152 -        case "3":
 176.153 -            return ASL_LEVEL_ERR
 176.154 -        case "4":
 176.155 -            return ASL_LEVEL_WARNING
 176.156 -        case "5":
 176.157 -            return ASL_LEVEL_NOTICE
 176.158 -        case "6":
 176.159 -            return ASL_LEVEL_INFO
 176.160 -        case "7":
 176.161 -            return ASL_LEVEL_DEBUG
 176.162 -
 176.163 -        default:
 176.164 -            return ASL_LEVEL_DEBUG
 176.165 -        }
 176.166 -    }
 176.167 -}
 176.168 -
 176.169 -extension Int32 {
 176.170 -    func criticalityString() -> String {
 176.171 -        switch self {
 176.172 -        case ASL_LEVEL_EMERG:
 176.173 -            return "EMERG"
 176.174 -        case ASL_LEVEL_ALERT:
 176.175 -            return "ALERT"
 176.176 -        case ASL_LEVEL_CRIT:
 176.177 -            return "CRIT"
 176.178 -        case ASL_LEVEL_ERR:
 176.179 -            return "ERR"
 176.180 -        case ASL_LEVEL_WARNING:
 176.181 -            return "WARNING"
 176.182 -        case ASL_LEVEL_NOTICE:
 176.183 -            return "NOTICE"
 176.184 -        case ASL_LEVEL_INFO:
 176.185 -            return "INFO"
 176.186 -        case ASL_LEVEL_DEBUG:
 176.187 -            return "DEBUG"
 176.188 -        default:
 176.189 -            return "UNKNOWN"
 176.190 -        }
 176.191 -    }
 176.192 -
 176.193 -    func aslLevelString() -> String {
 176.194 -        switch self {
 176.195 -        case ASL_LEVEL_EMERG:
 176.196 -            return "ASL_LEVEL_EMERG"
 176.197 -        case ASL_LEVEL_ALERT:
 176.198 -            return "ASL_LEVEL_ALERT"
 176.199 -        case ASL_LEVEL_CRIT:
 176.200 -            return "ASL_LEVEL_CRIT"
 176.201 -        case ASL_LEVEL_ERR:
 176.202 -            return "ASL_LEVEL_ERR"
 176.203 -        case ASL_LEVEL_WARNING:
 176.204 -            return "ASL_LEVEL_WARNING"
 176.205 -        case ASL_LEVEL_NOTICE:
 176.206 -            return "ASL_LEVEL_NOTICE"
 176.207 -        case ASL_LEVEL_INFO:
 176.208 -            return "ASL_LEVEL_INFO"
 176.209 -        case ASL_LEVEL_DEBUG:
 176.210 -            return "ASL_LEVEL_DEBUG"
 176.211 -        default:
 176.212 -            return "ASL_LEVEL_UNKNOWN"
 176.213 -        }
 176.214 -    }
 176.215 -}
   177.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   177.2 +++ b/pEpForiOS/Util/Log+Extension.swift	Mon Mar 18 10:54:14 2019 +0100
   177.3 @@ -0,0 +1,24 @@
   177.4 +//
   177.5 +//  Log+Extension.swift
   177.6 +//  MessageModel
   177.7 +//
   177.8 +//  Created by Xavier Algarra on 04/02/2019.
   177.9 +//  Copyright © 2019 pEp Security S.A. All rights reserved.
  177.10 +//
  177.11 +
  177.12 +import Foundation
  177.13 +import pEpUtilities
  177.14 +
  177.15 +extension Log: CWLogging {
  177.16 +    @objc open func infoComponent(_ component: String, message: String) {
  177.17 +        Log.info(component: component, content: message)
  177.18 +    }
  177.19 +
  177.20 +    @objc open func warnComponent(_ component: String, message: String) {
  177.21 +        Log.warn(component: component, content: message)
  177.22 +    }
  177.23 +
  177.24 +    @objc open func errorComponent(_ component: String, message: String) {
  177.25 +        Log.error(component: component, errorString: message)
  177.26 +    }
  177.27 +}
   178.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   178.2 +++ b/pEpForiOS/Util/Log+Extensions.swift	Mon Mar 18 10:54:14 2019 +0100
   178.3 @@ -0,0 +1,24 @@
   178.4 +//
   178.5 +//  Log+Extensions.swift
   178.6 +//  pEp
   178.7 +//
   178.8 +//  Created by Xavier Algarra on 28/01/2019.
   178.9 +//  Copyright © 2019 p≡p Security S.A. All rights reserved.
  178.10 +//
  178.11 +
  178.12 +import Foundation
  178.13 +import pEpUtilities
  178.14 +
  178.15 +extension Log: CWLogging {
  178.16 +    @objc open func infoComponent(_ component: String, message: String) {
  178.17 +        Log.info(component: component, content: message)
  178.18 +    }
  178.19 +
  178.20 +    @objc open func warnComponent(_ component: String, message: String) {
  178.21 +        Log.warn(component: component, content: message)
  178.22 +    }
  178.23 +
  178.24 +    @objc open func errorComponent(_ component: String, message: String) {
  178.25 +        Log.error(component: component, errorString: message)
  178.26 +    }
  178.27 +}
   179.1 --- a/pEpForiOS/Util/Log.swift	Wed Feb 20 11:00:07 2019 +0100
   179.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   179.3 @@ -1,222 +0,0 @@
   179.4 -//
   179.5 -//  Log.swift
   179.6 -//  pEpForiOS
   179.7 -//
   179.8 -//  Created by Dirk Zimmermann on 08/04/16.
   179.9 -//  Copyright © 2016 p≡p Security S.A. All rights reserved.
  179.10 -//
  179.11 -
  179.12 -import os.log
  179.13 -
  179.14 -import MessageModel
  179.15 -
  179.16 -enum LoggingSeverity {
  179.17 -    case verbose
  179.18 -    case info
  179.19 -    case warning
  179.20 -    case error
  179.21 -}
  179.22 -
  179.23 -/**
  179.24 - Handling the actual logging.
  179.25 - */
  179.26 -protocol ActualLoggerProtocol {
  179.27 -    func saveLog(severity: LoggingSeverity,
  179.28 -                 entity: String,
  179.29 -                 description: String,
  179.30 -                 comment: String)
  179.31 -
  179.32 -    func retrieveLog() -> String
  179.33 -}
  179.34 -
  179.35 -/** Very primitive Logging class. */
  179.36 -@objc open class Log: NSObject {
  179.37 -    static public let shared: Log = {
  179.38 -        let instance = Log()
  179.39 -        return instance
  179.40 -    }()
  179.41 -
  179.42 -    static public func disableLog() {
  179.43 -        Log.shared.loggingQueue.addOperation() {
  179.44 -            Log.shared.logEnabled = false
  179.45 -        }
  179.46 -    }
  179.47 -
  179.48 -    static public func enableLog() {
  179.49 -        Log.shared.loggingQueue.addOperation() {
  179.50 -            Log.shared.logEnabled = true
  179.51 -        }
  179.52 -    }
  179.53 -
  179.54 -    static public func checkEnabled(_ block: ((Bool) -> ())?) {
  179.55 -        Log.shared.loggingQueue.addOperation() {
  179.56 -            let b = Log.shared.logEnabled
  179.57 -            block?(b)
  179.58 -        }
  179.59 -    }
  179.60 -
  179.61 -    static public func checklog(_ block: ((String?) -> ())?) {
  179.62 -        Log.shared.loggingQueue.addOperation() {
  179.63 -            let logString = Log.shared.internalLogger.retrieveLog()
  179.64 -            block?(logString)
  179.65 -        }
  179.66 -    }
  179.67 -
  179.68 -    static public func verbose(component: String, content: String) {
  179.69 -        Log.shared.saveLog(severity:.verbose,
  179.70 -                           entity: component, description: content, comment: "verbose")
  179.71 -    }
  179.72 -
  179.73 -    /** Somewhat verbose */
  179.74 -    static public func info(component: String, content: String) {
  179.75 -        Log.shared.saveLog(severity:.info,
  179.76 -                           entity: component, description: content, comment: "info")
  179.77 -    }
  179.78 -
  179.79 -    /** More important */
  179.80 -    static public func warn(component: String, content: String) {
  179.81 -        Log.shared.saveLog(severity:.warning,
  179.82 -                           entity: component, description: content, comment: "warn")
  179.83 -    }
  179.84 -
  179.85 -    static public func error(component: String, error: Error?) {
  179.86 -        if let err = error {
  179.87 -            Log.shared.saveLog(severity:.error,
  179.88 -                               entity: component, description: " \(err)", comment: "error")
  179.89 -        }
  179.90 -    }
  179.91 -
  179.92 -    static public func error(component: String, errorString: String, error: Error) {
  179.93 -        Log.shared.saveLog(severity:.error,
  179.94 -            entity: component, description: "\(errorString) \(error)", comment: "error")
  179.95 -    }
  179.96 -
  179.97 -    static public func error(component: String, errorString: String) {
  179.98 -        Log.shared.saveLog(severity:.error,
  179.99 -                           entity: component, description: errorString, comment: "error")
 179.100 -    }
 179.101 -
 179.102 -    public static func log(comp: String, mySelf: AnyObject, functionName: String) {
 179.103 -        let selfDesc = unsafeBitCast(mySelf, to: UnsafeRawPointer.self)
 179.104 -        Log.shared.info(component: comp, content: "\(functionName): \(selfDesc)")
 179.105 -    }
 179.106 -
 179.107 -    public func resume() {
 179.108 -        Log.shared.paused = false
 179.109 -    }
 179.110 -
 179.111 -    public func pause() {
 179.112 -        Log.shared.paused = true
 179.113 -        Log.shared.loggingQueue.cancelAllOperations()
 179.114 -    }
 179.115 -
 179.116 -    private let title = "pEpForiOS"
 179.117 -    private var logEnabled = true
 179.118 -    private var paused = false
 179.119 -
 179.120 -    private let loggingQueue: OperationQueue = {
 179.121 -        let createe = OperationQueue()
 179.122 -        createe.qualityOfService = .background
 179.123 -        createe.maxConcurrentOperationCount = 1
 179.124 -        return createe
 179.125 -    }()
 179.126 -
 179.127 -    private let internalLogger = ASLLogger()
 179.128 -
 179.129 -    /**
 179.130 -     Prints and/or saves a log entry.
 179.131 -     - Note: For a log to be printed, the entity must be contained in `allowedEntities`,
 179.132 -     or the severity must be noted in `allowedSeverities`.
 179.133 -     */
 179.134 -    private func saveLog(severity: LoggingSeverity,
 179.135 -                         entity: String,
 179.136 -                         description: String,
 179.137 -                         comment: String) {
 179.138 -        let allowedEntities = Set<String>(["CWIMAPStore", "ImapSync"])
 179.139 -        let allowedSeverities = Set<LoggingSeverity>([.error, .warning, .info])
 179.140 -
 179.141 -        if allowedSeverities.contains(severity) || allowedEntities.contains(entity) {
 179.142 -            internalLogger.saveLog(severity: severity,
 179.143 -                                   entity: entity,
 179.144 -                                   description: description,
 179.145 -                                   comment: comment)
 179.146 -        }
 179.147 -    }
 179.148 -}
 179.149 -
 179.150 -extension Log: MessageModelLogging {
 179.151 -    public func verbose(component: String, content: String) {
 179.152 -        Log.verbose(component: component, content: content)
 179.153 -    }
 179.154 -
 179.155 -    public func info(component: String, content: String) {
 179.156 -        Log.info(component: component, content: content)
 179.157 -    }
 179.158 -
 179.159 -    public func warn(component: String, content: String) {
 179.160 -        Log.warn(component: component, content: content)
 179.161 -    }
 179.162 -
 179.163 -    public func error(component: String, error: Error) {
 179.164 -        Log.error(component: component, error: error)
 179.165 -    }
 179.166 -
 179.167 -    public func error(component: String, errorString: String, error: Error) {
 179.168 -        Log.error(component: component, errorString: errorString, error: error)
 179.169 -    }
 179.170 -
 179.171 -    public func error(component: String, errorString: String) {
 179.172 -        Log.error(component: component, errorString: errorString)
 179.173 -    }
 179.174 -
 179.175 -    /// Logs component and error.
 179.176 -    ///
 179.177 -    /// - note: If (and only if) in DEBUG configuration, it also calls fatalError().
 179.178 -    ///
 179.179 -    /// - Parameters:
 179.180 -    ///   - component: caller information to log
 179.181 -    ///   - error: error to log
 179.182 -    public func errorAndCrash(component: String, error: Error) {
 179.183 -        Log.error(component: component, error: error)
 179.184 -        SystemUtils.crash("ERROR \(component): \(error.localizedDescription)")
 179.185 -    }
 179.186 -
 179.187 -    /// Logs component and error.
 179.188 -    ///
 179.189 -    /// - note: If (and only if) in DEBUG configuration, it also calls fatalError().
 179.190 -    ///
 179.191 -    /// - Parameters:
 179.192 -    ///   - component: caller information to log
 179.193 -    ///   - errorString: error information to log
 179.194 -    ///   - error: error to log
 179.195 -    public func errorAndCrash(component: String, errorString: String, error: Error) {
 179.196 -        Log.error(component: component, errorString: errorString, error: error)
 179.197 -        SystemUtils.crash("ERROR \(component): \(errorString): \(error.localizedDescription)")
 179.198 -    }
 179.199 -
 179.200 -    /// Logs component and error.
 179.201 -    ///
 179.202 -    /// - note: If (and only if) in DEBUG configuration, it also calls fatalError().
 179.203 -    ///
 179.204 -    /// - Parameters:
 179.205 -    ///   - component: caller information to log
 179.206 -    ///   - errorString: error information to log
 179.207 -    public func errorAndCrash(component: String, errorString: String) {
 179.208 -        Log.error(component: component, errorString: errorString)
 179.209 -        SystemUtils.crash("ERROR \(component): \(errorString)")
 179.210 -    }
 179.211 -}
 179.212 -
 179.213 -extension Log: CWLogging {
 179.214 -    @objc open func infoComponent(_ component: String, message: String) {
 179.215 -        Log.info(component: component, content: message)
 179.216 -    }
 179.217 -
 179.218 -    @objc open func warnComponent(_ component: String, message: String) {
 179.219 -        Log.warn(component: component, content: message)
 179.220 -    }
 179.221 -
 179.222 -    @objc open func errorComponent(_ component: String, message: String) {
 179.223 -        Log.error(component: component, errorString: message)
 179.224 -    }
 179.225 -}
   180.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   180.2 +++ b/pEpForiOS/Util/Log/Log+ASL.swift	Mon Mar 18 10:54:14 2019 +0100
   180.3 @@ -0,0 +1,213 @@
   180.4 +//
   180.5 +//  Log+ASL.swift
   180.6 +//  pEp
   180.7 +//
   180.8 +//  Created by Dirk Zimmermann on 03.10.18.
   180.9 +//  Copyright © 2018 p≡p Security S.A. All rights reserved.
  180.10 +//
  180.11 +
  180.12 +import Foundation
  180.13 +import asl
  180.14 +
  180.15 +class ASLLogger: ActualLoggerProtocol {
  180.16 +    func saveLog(severity: LoggingSeverity,
  180.17 +                 entity: String,
  180.18 +                 description: String,
  180.19 +                 comment: String) {
  180.20 +        let logMessage = asl_new(UInt32(ASL_TYPE_MSG))
  180.21 +
  180.22 +        asl_set(logMessage, ASL_KEY_SENDER, sender)
  180.23 +        asl_set(logMessage, ASL_KEY_FACILITY, entity)
  180.24 +        asl_set(logMessage, ASL_KEY_MSG, "\(description) [\(comment)]")
  180.25 +        asl_set(logMessage, ASL_KEY_LEVEL, "\(severity.aslLevel())")
  180.26 +
  180.27 +        let nowDate = Date()
  180.28 +        let dateString = "\(Int(nowDate.timeIntervalSince1970))"
  180.29 +        asl_set(logMessage, ASL_KEY_TIME, dateString)
  180.30 +
  180.31 +        asl_set(logMessage, ASL_KEY_READ_UID, "-1")
  180.32 +
  180.33 +        asl_send(self.consoleClient, logMessage)
  180.34 +        asl_free(logMessage)
  180.35 +    }
  180.36 +
  180.37 +    func retrieveLog() -> String {
  180.38 +        let query = asl_new(UInt32(ASL_TYPE_QUERY))
  180.39 +
  180.40 +        var result = asl_set_query(
  180.41 +            query,
  180.42 +            ASL_KEY_SENDER,
  180.43 +            sender,
  180.44 +            UInt32(ASL_QUERY_OP_EQUAL))
  180.45 +        ASLLogger.checkASLSuccess(result: result, comment: "asl_set_query ASL_KEY_SENDER")
  180.46 +
  180.47 +        let fromDate = Date(timeInterval: -600, since: Date())
  180.48 +        let fromDateString = "\(Int(fromDate.timeIntervalSince1970))"
  180.49 +        result = asl_set_query(
  180.50 +            query,
  180.51 +            ASL_KEY_TIME,
  180.52 +            fromDateString,
  180.53 +            UInt32(ASL_QUERY_OP_GREATER_EQUAL))
  180.54 +        ASLLogger.checkASLSuccess(result: result, comment: "asl_set_query ASL_KEY_TIME")
  180.55 +
  180.56 +        let theClient = createConsoleLogger()
  180.57 +
  180.58 +        let response = asl_search(theClient, query)
  180.59 +        var next = asl_next(response)
  180.60 +        var logString = ""
  180.61 +        while next != nil {
  180.62 +            let timeString = String(cString: asl_get(next, ASL_KEY_TIME))
  180.63 +            let messageString = String(cString: asl_get(next, ASL_KEY_MSG))
  180.64 +            let facilityString = String(cString: asl_get(next, ASL_KEY_FACILITY))
  180.65 +            let levelString = String(cString: asl_get(next, ASL_KEY_LEVEL))
  180.66 +
  180.67 +            let level = levelString.aslLevelStringToASL()
  180.68 +            let ownLevelString = level.criticalityString()
  180.69 +
  180.70 +            var dateString = "<NoTime>"
  180.71 +            if let dateInt = Int(timeString) {
  180.72 +                let date = Date(timeIntervalSince1970: TimeInterval(dateInt))
  180.73 +                dateString = "\(date)"
  180.74 +            }
  180.75 +
  180.76 +            if !logString.isEmpty {
  180.77 +                logString.append("\n")
  180.78 +            }
  180.79 +
  180.80 +            let stringToLog = "\(dateString) [\(ownLevelString)] [\(facilityString)] \(messageString)"
  180.81 +            logString.append(stringToLog)
  180.82 +
  180.83 +            next = asl_next(response)
  180.84 +        }
  180.85 +
  180.86 +        asl_free(query)
  180.87 +        asl_free(response)
  180.88 +        asl_free(theClient)
  180.89 +
  180.90 +        return logString
  180.91 +    }
  180.92 +
  180.93 +    init() {
  180.94 +        self.consoleClient = createConsoleLogger()
  180.95 +    }
  180.96 +
  180.97 +    deinit {
  180.98 +        asl_release(consoleClient)
  180.99 +    }
 180.100 +
 180.101 +    private let sender = "security.pEp.app.iOS"
 180.102 +
 180.103 +    private var consoleClient: aslclient?
 180.104 +
 180.105 +    private func createConsoleLogger() -> asl_object_t {
 180.106 +        return asl_open(self.sender, "default", 0)
 180.107 +    }
 180.108 +
 180.109 +    private static func checkASLSuccess(result: Int32, comment: String) {
 180.110 +        if result != 0 {
 180.111 +            print("error: \(comment)")
 180.112 +        }
 180.113 +    }
 180.114 +}
 180.115 +
 180.116 +extension LoggingSeverity {
 180.117 +    /**
 180.118 +     Maps the internal criticality of a log  message into a subsystem of ASL levels.
 180.119 +
 180.120 +     ASL has the following:
 180.121 +     * ASL_LEVEL_EMERG
 180.122 +     * ASL_LEVEL_ALERT
 180.123 +     * ASL_LEVEL_CRIT
 180.124 +     * ASL_LEVEL_ERR
 180.125 +     * ASL_LEVEL_WARNING
 180.126 +     * ASL_LEVEL_NOTICE
 180.127 +     * ASL_LEVEL_INFO
 180.128 +     * ASL_LEVEL_DEBUG
 180.129 +     */
 180.130 +    func aslLevel() -> Int32 {
 180.131 +        switch self {
 180.132 +        case .verbose:
 180.133 +            return ASL_LEVEL_DEBUG
 180.134 +        case .info:
 180.135 +            return ASL_LEVEL_NOTICE
 180.136 +        case .warning:
 180.137 +            return ASL_LEVEL_WARNING
 180.138 +        case .error:
 180.139 +            return ASL_LEVEL_ERR
 180.140 +        }
 180.141 +    }
 180.142 +}
 180.143 +
 180.144 +extension String {
 180.145 +    func aslLevelStringToASL() -> Int32 {
 180.146 +        switch self {
 180.147 +        case "0":
 180.148 +            return ASL_LEVEL_EMERG
 180.149 +        case "1":
 180.150 +            return ASL_LEVEL_ALERT
 180.151 +        case "2":
 180.152 +            return ASL_LEVEL_CRIT
 180.153 +        case "3":
 180.154 +            return ASL_LEVEL_ERR
 180.155 +        case "4":
 180.156 +            return ASL_LEVEL_WARNING
 180.157 +        case "5":
 180.158 +            return ASL_LEVEL_NOTICE
 180.159 +        case "6":
 180.160 +            return ASL_LEVEL_INFO
 180.161 +        case "7":
 180.162 +            return ASL_LEVEL_DEBUG
 180.163 +
 180.164 +        default:
 180.165 +            return ASL_LEVEL_DEBUG
 180.166 +        }
 180.167 +    }
 180.168 +}
 180.169 +
 180.170 +extension Int32 {
 180.171 +    func criticalityString() -> String {
 180.172 +        switch self {
 180.173 +        case ASL_LEVEL_EMERG:
 180.174 +            return "EMERG"
 180.175 +        case ASL_LEVEL_ALERT:
 180.176 +            return "ALERT"
 180.177 +        case ASL_LEVEL_CRIT:
 180.178 +            return "CRIT"
 180.179 +        case ASL_LEVEL_ERR:
 180.180 +            return "ERR"
 180.181 +        case ASL_LEVEL_WARNING:
 180.182 +            return "WARNING"
 180.183 +        case ASL_LEVEL_NOTICE:
 180.184 +            return "NOTICE"
 180.185 +        case ASL_LEVEL_INFO:
 180.186 +            return "INFO"
 180.187 +        case ASL_LEVEL_DEBUG:
 180.188 +            return "DEBUG"
 180.189 +        default:
 180.190 +            return "UNKNOWN"
 180.191 +        }
 180.192 +    }
 180.193 +
 180.194 +    func aslLevelString() -> String {
 180.195 +        switch self {
 180.196 +        case ASL_LEVEL_EMERG:
 180.197 +            return "ASL_LEVEL_EMERG"
 180.198 +        case ASL_LEVEL_ALERT:
 180.199 +            return "ASL_LEVEL_ALERT"
 180.200 +        case ASL_LEVEL_CRIT:
 180.201 +            return "ASL_LEVEL_CRIT"
 180.202 +        case ASL_LEVEL_ERR:
 180.203 +            return "ASL_LEVEL_ERR"
 180.204 +        case ASL_LEVEL_WARNING:
 180.205 +            return "ASL_LEVEL_WARNING"
 180.206 +        case ASL_LEVEL_NOTICE:
 180.207 +            return "ASL_LEVEL_NOTICE"
 180.208 +        case ASL_LEVEL_INFO:
 180.209 +            return "ASL_LEVEL_INFO"
 180.210 +        case ASL_LEVEL_DEBUG:
 180.211 +            return "ASL_LEVEL_DEBUG"
 180.212 +        default:
 180.213 +            return "ASL_LEVEL_UNKNOWN"
 180.214 +        }
 180.215 +    }
 180.216 +}
   181.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   181.2 +++ b/pEpForiOS/Util/Log/Log.swift	Mon Mar 18 10:54:14 2019 +0100
   181.3 @@ -0,0 +1,222 @@
   181.4 +//
   181.5 +//  Log.swift
   181.6 +//  pEpForiOS
   181.7 +//
   181.8 +//  Created by Dirk Zimmermann on 08/04/16.
   181.9 +//  Copyright © 2016 p≡p Security S.A. All rights reserved.
  181.10 +//
  181.11 +
  181.12 +import os.log
  181.13 +
  181.14 +import MessageModel
  181.15 +
  181.16 +enum LoggingSeverity {
  181.17 +    case verbose
  181.18 +    case info
  181.19 +    case warning
  181.20 +    case error
  181.21 +}
  181.22 +
  181.23 +/**
  181.24 + Handling the actual logging.
  181.25 + */
  181.26 +protocol ActualLoggerProtocol {
  181.27 +    func saveLog(severity: LoggingSeverity,
  181.28 +                 entity: String,
  181.29 +                 description: String,
  181.30 +                 comment: String)
  181.31 +
  181.32 +    func retrieveLog() -> String
  181.33 +}
  181.34 +
  181.35 +/** Very primitive Logging class. */
  181.36 +@objc open class Log: NSObject {
  181.37 +    static public let shared: Log = {
  181.38 +        let instance = Log()
  181.39 +        return instance
  181.40 +    }()
  181.41 +
  181.42 +    static public func disableLog() {
  181.43 +        Log.shared.loggingQueue.addOperation() {
  181.44 +            Log.shared.logEnabled = false
  181.45 +        }
  181.46 +    }
  181.47 +
  181.48 +    static public func enableLog() {
  181.49 +        Log.shared.loggingQueue.addOperation() {
  181.50 +            Log.shared.logEnabled = true
  181.51 +        }
  181.52 +    }
  181.53 +
  181.54 +    static public func checkEnabled(_ block: ((Bool) -> ())?) {
  181.55 +        Log.shared.loggingQueue.addOperation() {
  181.56 +            let b = Log.shared.logEnabled
  181.57 +            block?(b)
  181.58 +        }
  181.59 +    }
  181.60 +
  181.61 +    static public func checklog(_ block: ((String?) -> ())?) {
  181.62 +        Log.shared.loggingQueue.addOperation() {
  181.63 +            let logString = Log.shared.internalLogger.retrieveLog()
  181.64 +            block?(logString)
  181.65 +        }
  181.66 +    }
  181.67 +
  181.68 +    static public func verbose(component: String, content: String) {
  181.69 +        Log.shared.saveLog(severity:.verbose,
  181.70 +                           entity: component, description: content, comment: "verbose")
  181.71 +    }
  181.72 +
  181.73 +    /** Somewhat verbose */
  181.74 +    static public func info(component: String, content: String) {
  181.75 +        Log.shared.saveLog(severity:.info,
  181.76 +                           entity: component, description: content, comment: "info")
  181.77 +    }
  181.78 +
  181.79 +    /** More important */
  181.80 +    static public func warn(component: String, content: String) {
  181.81 +        Log.shared.saveLog(severity:.warning,
  181.82 +                           entity: component, description: content, comment: "warn")
  181.83 +    }
  181.84 +
  181.85 +    static public func error(component: String, error: Error?) {
  181.86 +        if let err = error {
  181.87 +            Log.shared.saveLog(severity:.error,
  181.88 +                               entity: component, description: " \(err)", comment: "error")
  181.89 +        }
  181.90 +    }
  181.91 +
  181.92 +    static public func error(component: String, errorString: String, error: Error) {
  181.93 +        Log.shared.saveLog(severity:.error,
  181.94 +                           entity: component, description: "\(errorString) \(error)", comment: "error")
  181.95 +    }
  181.96 +
  181.97 +    static public func error(component: String, errorString: String) {
  181.98 +        Log.shared.saveLog(severity:.error,
  181.99 +                           entity: component, description: errorString, comment: "error")
 181.100 +    }
 181.101 +
 181.102 +    public static func log(comp: String, mySelf: AnyObject, functionName: String) {
 181.103 +        let selfDesc = unsafeBitCast(mySelf, to: UnsafeRawPointer.self)
 181.104 +        Log.shared.info(component: comp, content: "\(functionName): \(selfDesc)")
 181.105 +    }
 181.106 +
 181.107 +    public func resume() {
 181.108 +        Log.shared.paused = false
 181.109 +    }
 181.110 +
 181.111 +    public func pause() {
 181.112 +        Log.shared.paused = true
 181.113 +        Log.shared.loggingQueue.cancelAllOperations()
 181.114 +    }
 181.115 +
 181.116 +    private let title = "pEpForiOS"
 181.117 +    private var logEnabled = true
 181.118 +    private var paused = false
 181.119 +
 181.120 +    private let loggingQueue: OperationQueue = {
 181.121 +        let createe = OperationQueue()
 181.122 +        createe.qualityOfService = .background
 181.123 +        createe.maxConcurrentOperationCount = 1
 181.124 +        return createe
 181.125 +    }()
 181.126 +
 181.127 +    private let internalLogger = ASLLogger()
 181.128 +
 181.129 +    /**
 181.130 +     Prints and/or saves a log entry.
 181.131 +     - Note: For a log to be printed, the entity must be contained in `allowedEntities`,
 181.132 +     or the severity must be noted in `allowedSeverities`.
 181.133 +     */
 181.134 +    private func saveLog(severity: LoggingSeverity,
 181.135 +                         entity: String,
 181.136 +                         description: String,
 181.137 +                         comment: String) {
 181.138 +        let allowedEntities = Set<String>(["CWIMAPStore", "ImapSync"])
 181.139 +        let allowedSeverities = Set<LoggingSeverity>([.error, .warning, .info])
 181.140 +
 181.141 +        if allowedSeverities.contains(severity) || allowedEntities.contains(entity) {
 181.142 +            internalLogger.saveLog(severity: severity,
 181.143 +                                   entity: entity,
 181.144 +                                   description: description,
 181.145 +                                   comment: comment)
 181.146 +        }
 181.147 +    }
 181.148 +}
 181.149 +
 181.150 +extension Log: MessageModelLogging {
 181.151 +    public func verbose(component: String, content: String) {
 181.152 +        Log.verbose(component: component, content: content)
 181.153 +    }
 181.154 +
 181.155 +    public func info(component: String, content: String) {
 181.156 +        Log.info(component: component, content: content)
 181.157 +    }
 181.158 +
 181.159 +    public func warn(component: String, content: String) {
 181.160 +        Log.warn(component: component, content: content)
 181.161 +    }
 181.162 +
 181.163 +    public func error(component: String, error: Error) {
 181.164 +        Log.error(component: component, error: error)
 181.165 +    }
 181.166 +
 181.167 +    public func error(component: String, errorString: String, error: Error) {
 181.168 +        Log.error(component: component, errorString: errorString, error: error)
 181.169 +    }
 181.170 +
 181.171 +    public func error(component: String, errorString: String) {
 181.172 +        Log.error(component: component, errorString: errorString)
 181.173 +    }
 181.174 +
 181.175 +    /// Logs component and error.
 181.176 +    ///
 181.177 +    /// - note: If (and only if) in DEBUG configuration, it also calls fatalError().
 181.178 +    ///
 181.179 +    /// - Parameters:
 181.180 +    ///   - component: caller information to log
 181.181 +    ///   - error: error to log
 181.182 +    public func errorAndCrash(component: String, error: Error) {
 181.183 +        Log.error(component: component, error: error)
 181.184 +        SystemUtils.crash("ERROR \(component): \(error.localizedDescription)")
 181.185 +    }
 181.186 +
 181.187 +    /// Logs component and error.
 181.188 +    ///
 181.189 +    /// - note: If (and only if) in DEBUG configuration, it also calls fatalError().
 181.190 +    ///
 181.191 +    /// - Parameters:
 181.192 +    ///   - component: caller information to log
 181.193 +    ///   - errorString: error information to log
 181.194 +    ///   - error: error to log
 181.195 +    public func errorAndCrash(component: String, errorString: String, error: Error) {
 181.196 +        Log.error(component: component, errorString: errorString, error: error)
 181.197 +        SystemUtils.crash("ERROR \(component): \(errorString): \(error.localizedDescription)")
 181.198 +    }
 181.199 +
 181.200 +    /// Logs component and error.
 181.201 +    ///
 181.202 +    /// - note: If (and only if) in DEBUG configuration, it also calls fatalError().
 181.203 +    ///
 181.204 +    /// - Parameters:
 181.205 +    ///   - component: caller information to log
 181.206 +    ///   - errorString: error information to log
 181.207 +    public func errorAndCrash(component: String, errorString: String) {
 181.208 +        Log.error(component: component, errorString: errorString)
 181.209 +        SystemUtils.crash("ERROR \(component): \(errorString)")
 181.210 +    }
 181.211 +}
 181.212 +
 181.213 +extension Log: CWLogging {
 181.214 +    @objc open func infoComponent(_ component: String, message: String) {
 181.215 +        Log.info(component: component, content: message)
 181.216 +    }
 181.217 +
 181.218 +    @objc open func warnComponent(_ component: String, message: String) {
 181.219 +        Log.warn(component: component, content: message)
 181.220 +    }
 181.221 +
 181.222 +    @objc open func errorComponent(_ component: String, message: String) {
 181.223 +        Log.error(component: component, errorString: message)
 181.224 +    }
 181.225 +}
   182.1 --- a/pEpForiOS/Util/Logger.swift	Wed Feb 20 11:00:07 2019 +0100
   182.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   182.3 @@ -1,453 +0,0 @@
   182.4 -//
   182.5 -//  Logger.swift
   182.6 -//  pEp
   182.7 -//
   182.8 -//  Created by Dirk Zimmermann on 18.12.18.
   182.9 -//  Copyright © 2018 p≡p Security S.A. All rights reserved.
  182.10 -//
  182.11 -
  182.12 -import Foundation
  182.13 -import os.log
  182.14 -
  182.15 -import MessageModel // For SystemUtils.crash only
  182.16 -
  182.17 -/**
  182.18 - Thin layer over `os_log` or `asl_logger` where not available.
  182.19 - The fallback to asl is only in effect for iOS 9, and currently
  182.20 - doesn't appear anywhere visible on that platform.
  182.21 - */
  182.22 -public class Logger {
  182.23 -    /**
  182.24 -     Map `os_log` levels.
  182.25 -     */
  182.26 -    public enum Severity {
  182.27 -        /**
  182.28 -         - Note: Not persisted by default, but will be written in case of errors.
  182.29 -         */
  182.30 -        case info
  182.31 -
  182.32 -        /**
  182.33 -         - Note: Not persisted by default, but will be written in case of errors.
  182.34 -         */
  182.35 -        case debug
  182.36 -
  182.37 -        /**
  182.38 -         This is the lowest priority that gets written to disk by default.
  182.39 -         Used like WARN in this logger.
  182.40 -         */
  182.41 -        case `default`
  182.42 -
  182.43 -        case error
  182.44 -
  182.45 -        /**
  182.46 -         - Note: As this is referring to inter-process problems, I don't see a use-case
  182.47 -         for iOS.
  182.48 -         */
  182.49 -        case fault
  182.50 -
  182.51 -        @available(iOS 10.0, macOS 10.12, tvOS 10.0, watchOS 3.0, *)
  182.52 -        public func osLogType() -> OSLogType {
  182.53 -            switch self {
  182.54 -            case .info:
  182.55 -                return .info
  182.56 -            case .debug:
  182.57 -                return .debug
  182.58 -            case .default:
  182.59 -                return .default
  182.60 -            case .error:
  182.61 -                return .error
  182.62 -            case .fault:
  182.63 -                return .fault
  182.64 -            }
  182.65 -        }
  182.66 -
  182.67 -        /**
  182.68 -         Maps the internal criticality of a log  message into a subsystem of ASL levels.
  182.69 -
  182.70 -         ASL has the following:
  182.71 -         * ASL_LEVEL_EMERG
  182.72 -         * ASL_LEVEL_ALERT
  182.73 -         * ASL_LEVEL_CRIT
  182.74 -         * ASL_LEVEL_ERR
  182.75 -         * ASL_LEVEL_WARNING
  182.76 -         * ASL_LEVEL_NOTICE
  182.77 -         * ASL_LEVEL_INFO
  182.78 -         * ASL_LEVEL_DEBUG
  182.79 -         */
  182.80 -        public func aslLevelString() -> String {
  182.81 -            switch self {
  182.82 -            case .default:
  182.83 -                return "ASL_LEVEL_NOTICE"
  182.84 -            case .info:
  182.85 -                return "ASL_LEVEL_INFO"
  182.86 -            case .debug:
  182.87 -                return "ASL_LEVEL_DEBUG"
  182.88 -            case .error:
  182.89 -                return "ASL_LEVEL_ERR"
  182.90 -            case .fault:
  182.91 -                return "ASL_LEVEL_CRIT"
  182.92 -            }
  182.93 -        }
  182.94 -    }
  182.95 -
  182.96 -    public static let frontendLogger = Logger(category: "frontend")
  182.97 -    public static let backendLogger = Logger(category: "backend")
  182.98 -    public static let utilLogger = Logger(category: "util")
  182.99 -    public static let htmlParsingLogger = Logger(category: "htmlParsing")
 182.100 -    public static let modelLogger = Logger(category: "model")
 182.101 -    public static let appDelegateLogger = Logger(category: "appDelegate")
 182.102 -
 182.103 -    public init(subsystem: String = "security.pEp.app.iOS", category: String) {
 182.104 -        self.subsystem = subsystem
 182.105 -        self.category = category
 182.106 -        if #available(iOS 10.0, macOS 10.12, tvOS 10.0, watchOS 3.0, *) {
 182.107 -            osLogger = OSLog(subsystem: subsystem, category: category)
 182.108 -        } else {
 182.109 -            osLogger = nil
 182.110 -        }
 182.111 -    }
 182.112 -
 182.113 -    /**
 182.114 -     Logs to default.
 182.115 -     */
 182.116 -    public func log(function: String = #function,
 182.117 -                    filePath: String = #file,
 182.118 -                    fileLine: Int = #line,
 182.119 -                    _ message: StaticString,
 182.120 -                    _ args: CVarArg...) {
 182.121 -        saveLog(message: message,
 182.122 -                severity: .default,
 182.123 -                function: function,
 182.124 -                filePath: filePath,
 182.125 -                fileLine: fileLine,
 182.126 -                args: args)
 182.127 -    }
 182.128 -
 182.129 -    /**
 182.130 -     os_log doesn't have a warn per se, but default is coming close.
 182.131 -     This is the same as log.
 182.132 -     */
 182.133 -    public func warn(function: String = #function,
 182.134 -                     filePath: String = #file,
 182.135 -                     fileLine: Int = #line,
 182.136 -                     _ message: StaticString,
 182.137 -                     _ args: CVarArg...) {
 182.138 -        saveLog(message: message,
 182.139 -                severity: .default,
 182.140 -                function: function,
 182.141 -                filePath: filePath,
 182.142 -                fileLine: fileLine,
 182.143 -                args: args)
 182.144 -    }
 182.145 -
 182.146 -    /**
 182.147 -     Logs to info.
 182.148 -     */
 182.149 -    public func info(function: String = #function,
 182.150 -                     filePath: String = #file,
 182.151 -                     fileLine: Int = #line,
 182.152 -                     _ message: StaticString,
 182.153 -                     _ args: CVarArg...) {
 182.154 -        saveLog(message: message,
 182.155 -                severity: .info,
 182.156 -                function: function,
 182.157 -                filePath: filePath,
 182.158 -                fileLine: fileLine,
 182.159 -                args: args)
 182.160 -    }
 182.161 -
 182.162 -    /**
 182.163 -     Logs to debug.
 182.164 -     */
 182.165 -    public func debug(function: String = #function,
 182.166 -                      filePath: String = #file,
 182.167 -                      fileLine: Int = #line,
 182.168 -                      _ message: StaticString,
 182.169 -                      _ args: CVarArg...) {
 182.170 -        saveLog(message: message,
 182.171 -                severity: .debug,
 182.172 -                function: function,
 182.173 -                filePath: filePath,
 182.174 -                fileLine: fileLine,
 182.175 -                args: args)
 182.176 -    }
 182.177 -
 182.178 -    /**
 182.179 -     Logs to error.
 182.180 -     */
 182.181 -    public func error(function: String = #function,
 182.182 -                      filePath: String = #file,
 182.183 -                      fileLine: Int = #line,
 182.184 -                      _ message: StaticString,
 182.185 -                      _ args: CVarArg...) {
 182.186 -        saveLog(message: message,
 182.187 -                severity: .error,
 182.188 -                function: function,
 182.189 -                filePath: filePath,
 182.190 -                fileLine: fileLine,
 182.191 -                args: args)
 182.192 -    }
 182.193 -
 182.194 -    /**
 182.195 -     Logs to fault.
 182.196 -     */
 182.197 -    public func fault(function: String = #function,
 182.198 -                      filePath: String = #file,
 182.199 -                      fileLine: Int = #line,
 182.200 -                      _ message: StaticString,
 182.201 -                      _ args: CVarArg...) {
 182.202 -        saveLog(message: message,
 182.203 -                severity: .fault,
 182.204 -                function: function,
 182.205 -                filePath: filePath,
 182.206 -                fileLine: fileLine,
 182.207 -                args: args)
 182.208 -    }
 182.209 -
 182.210 -    public func errorAndCrash(function: String = #function,
 182.211 -                              filePath: String = #file,
 182.212 -                              fileLine: Int = #line,
 182.213 -                              _ message: StaticString,
 182.214 -                              _ args: CVarArg...) {
 182.215 -        saveLog(message: message,
 182.216 -                severity: .fault,
 182.217 -                function: function,
 182.218 -                filePath: filePath,
 182.219 -                fileLine: fileLine,
 182.220 -                args: args)
 182.221 -
 182.222 -        // This will omit the arguments, but it's still matchable
 182.223 -        SystemUtils.crash("\(message)")
 182.224 -    }
 182.225 -
 182.226 -    /**
 182.227 -     Logs an error.
 182.228 -     */
 182.229 -    public func log(function: String = #function,
 182.230 -                    filePath: String = #file,
 182.231 -                    fileLine: Int = #line,
 182.232 -                    error: Error) {
 182.233 -        // Error is not supported by "%@", because it doesn't conform to CVArg
 182.234 -        // and CVArg is only meant for internal types.
 182.235 -        // An alternative would be to use localizedDescription(),
 182.236 -        // but if they are indeed localized you end up with international
 182.237 -        // log messages.
 182.238 -        // So we wrap it into an NSError which does suppord CVArg.
 182.239 -        let nsErr = NSError(domain: subsystem, code: 0, userInfo: [NSUnderlyingErrorKey: error])
 182.240 -
 182.241 -        saveLog(message: "%{public}@",
 182.242 -                severity: .default,
 182.243 -                function: function,
 182.244 -                filePath: filePath,
 182.245 -                fileLine: fileLine,
 182.246 -                args: [nsErr])
 182.247 -    }
 182.248 -
 182.249 -    /**
 182.250 -     Testing only. If you want to test the fallback to ASL logging you may have to call
 182.251 -     this, as all the logging is deferred to a serial queue.
 182.252 -     */
 182.253 -    public func testFlush() {
 182.254 -        if #available(iOS 10.0, macOS 10.12, tvOS 10.0, watchOS 3.0, *) {
 182.255 -            // no sense on these versions
 182.256 -        } else {
 182.257 -            aslLogQueue.sync {
 182.258 -                // nothing
 182.259 -            }
 182.260 -        }
 182.261 -    }
 182.262 -
 182.263 -    /**
 182.264 -     Since this kind of logging is used so often in the codebase, it has its
 182.265 -     own method.
 182.266 -     */
 182.267 -    public func lostMySelf() {
 182.268 -        errorAndCrash("Lost MySelf")
 182.269 -    }
 182.270 -
 182.271 -    private let subsystem: String
 182.272 -    private let category: String
 182.273 -
 182.274 -    private let osLogger: Any?
 182.275 -
 182.276 -    private func saveLog(message: StaticString,
 182.277 -                         severity: Severity,
 182.278 -                         function: String = #function,
 182.279 -                         filePath: String = #file,
 182.280 -                         fileLine: Int = #line,
 182.281 -                         args: [CVarArg]) {
 182.282 -        if #available(iOS 10.0, macOS 10.12, tvOS 10.0, watchOS 3.0, *) {
 182.283 -            osLog(message: message,
 182.284 -                  severity: severity,
 182.285 -                  function: function,
 182.286 -                  filePath: filePath,
 182.287 -                  fileLine: fileLine,
 182.288 -                  args: args)
 182.289 -        } else {
 182.290 -            aslLog(message: message,
 182.291 -                   severity: severity,
 182.292 -                   function: function,
 182.293 -                   filePath: filePath,
 182.294 -                   fileLine: fileLine,
 182.295 -                   args: args)
 182.296 -        }
 182.297 -    }
 182.298 -
 182.299 -    /**
 182.300 -     - Note: If the number of arguments to the format string exceeds 10,
 182.301 -     the logging doesn't work correctly. Can be easily fixed though, if really needed.
 182.302 -     */
 182.303 -    @available(iOS 10.0, macOS 10.12, tvOS 10.0, watchOS 3.0, *)
 182.304 -    private func osLog(message: StaticString,
 182.305 -                       severity: Severity,
 182.306 -                       function: String = #function,
 182.307 -                       filePath: String = #file,
 182.308 -                       fileLine: Int = #line,
 182.309 -                       args: [CVarArg]) {
 182.310 -        let theLog = osLogger as! OSLog
 182.311 -        let theType = severity.osLogType()
 182.312 -
 182.313 -        // I haven't found a way of injecting `function` etc. into the original message for
 182.314 -        // just one call to `os_log`, so the 'position' is logged on a separate line.
 182.315 -        os_log("%@:%d %@:",
 182.316 -               log: theLog,
 182.317 -               type: theType,
 182.318 -               filePath,
 182.319 -               fileLine,
 182.320 -               function)
 182.321 -
 182.322 -        // We have to expand the array of arguments into positional ones.
 182.323 -        // There is no attempt of trying to format the string on our side
 182.324 -        // in order to make use of `os_log`'s fast 'offline' formatting
 182.325 -        // (that is, the work is delayed until actual log display).
 182.326 -        switch args.count {
 182.327 -        case 0:
 182.328 -            os_log(message,
 182.329 -                   log: theLog,
 182.330 -                   type: theType)
 182.331 -        case 1:
 182.332 -            os_log(message,
 182.333 -                   log: theLog,
 182.334 -                   type: theType,
 182.335 -                   args[0])
 182.336 -        case 2:
 182.337 -            os_log(message,
 182.338 -                   log: theLog,
 182.339 -                   type: theType,
 182.340 -                   args[0], args[1])
 182.341 -        case 3:
 182.342 -            os_log(message,
 182.343 -                   log: theLog,
 182.344 -                   type: theType,
 182.345 -                   args[0], args[1], args[2])
 182.346 -        case 4:
 182.347 -            os_log(message,
 182.348 -                   log: theLog,
 182.349 -                   type: theType,
 182.350 -                   args[0], args[1], args[2], args[3])
 182.351 -        case 5:
 182.352 -            os_log(message,
 182.353 -                   log: theLog,
 182.354 -                   type: theType,
 182.355 -                   args[0], args[1], args[2], args[3], args[4])
 182.356 -        case 6:
 182.357 -            os_log(message,
 182.358 -                   log: theLog,
 182.359 -                   type: theType,
 182.360 -                   args[0], args[1], args[2], args[3], args[4], args[5])
 182.361 -        case 7:
 182.362 -            os_log(message,
 182.363 -                   log: theLog,
 182.364 -                   type: theType,
 182.365 -                   args[0], args[1], args[2], args[3], args[4], args[5], args[6])
 182.366 -        case 8:
 182.367 -            os_log(message,
 182.368 -                   log: theLog,
 182.369 -                   type: theType,
 182.370 -                   args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7])
 182.371 -        case 9:
 182.372 -            os_log(message,
 182.373 -                   log: theLog,
 182.374 -                   type: theType,
 182.375 -                   args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7],
 182.376 -                   args[8])
 182.377 -        case 10:
 182.378 -            os_log(message,
 182.379 -                   log: theLog,
 182.380 -                   type: theType,
 182.381 -                   args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7],
 182.382 -                   args[8], args[9])
 182.383 -        default:
 182.384 -            os_log("Using more than 10 parameters",
 182.385 -                   log: theLog,
 182.386 -                   type: .error)
 182.387 -            os_log(message,
 182.388 -                   log: theLog,
 182.389 -                   type: theType,
 182.390 -                   args)
 182.391 -        }
 182.392 -    }
 182.393 -
 182.394 -    private func aslLog(message: StaticString,
 182.395 -                        severity: Severity,
 182.396 -                        function: String = #function,
 182.397 -                        filePath: String = #file,
 182.398 -                        fileLine: Int = #line,
 182.399 -                        args: [CVarArg]) {
 182.400 -        aslLogQueue.async { [weak self] in
 182.401 -            if let theSelf = self {
 182.402 -                let logMessage = asl_new(UInt32(ASL_TYPE_MSG))
 182.403 -
 182.404 -                theSelf.checkASLSuccess(asl_set(logMessage, ASL_KEY_SENDER, theSelf.subsystem))
 182.405 -
 182.406 -                theSelf.checkASLSuccess(asl_set(logMessage, ASL_KEY_FACILITY, theSelf.category))
 182.407 -
 182.408 -                theSelf.checkASLSuccess(asl_set(
 182.409 -                    logMessage,
 182.410 -                    ASL_KEY_MSG,
 182.411 -                    "\(filePath):\(fileLine) \(function): \(message) \(args)"))
 182.412 -
 182.413 -                theSelf.checkASLSuccess(asl_set(logMessage, ASL_KEY_LEVEL, "ASL_LEVEL_ERROR"))
 182.414 -
 182.415 -                let nowDate = Date()
 182.416 -                let dateString = "\(Int(nowDate.timeIntervalSince1970))"
 182.417 -                theSelf.checkASLSuccess(asl_set(logMessage, ASL_KEY_TIME, dateString))
 182.418 -
 182.419 -                theSelf.checkASLSuccess(asl_set(logMessage, ASL_KEY_READ_UID, "-1"))
 182.420 -
 182.421 -                theSelf.checkASLSuccess(asl_send(theSelf.consoleLogger(), logMessage))
 182.422 -
 182.423 -                asl_free(logMessage)
 182.424 -            }
 182.425 -        }
 182.426 -    }
 182.427 -
 182.428 -    private var consoleClient: aslclient?
 182.429 -
 182.430 -    private lazy var aslLogQueue = DispatchQueue(label: "security.pEp.asl.log")
 182.431 -
 182.432 -    private let sender = "security.pEp.app.iOS"
 182.433 -
 182.434 -    private func createConsoleLogger() -> asl_object_t {
 182.435 -        return asl_open(self.sender, subsystem, 0)
 182.436 -    }
 182.437 -
 182.438 -    private func consoleLogger() -> aslclient? {
 182.439 -        if consoleClient == nil {
 182.440 -            consoleClient = createConsoleLogger()
 182.441 -        }
 182.442 -        return consoleClient
 182.443 -    }
 182.444 -
 182.445 -    deinit {
 182.446 -        if consoleClient != nil {
 182.447 -            asl_free(consoleClient)
 182.448 -        }
 182.449 -    }
 182.450 -
 182.451 -    private func checkASLSuccess(_ result: Int32, comment: String = "no comment") {
 182.452 -        if result != 0 {
 182.453 -            print("*** error: \(comment)")
 182.454 -        }
 182.455 -    }
 182.456 -}
   183.1 --- a/pEpForiOS/Util/MimeTypeUtil.swift	Wed Feb 20 11:00:07 2019 +0100
   183.2 +++ b/pEpForiOS/Util/MimeTypeUtil.swift	Mon Mar 18 10:54:14 2019 +0100
   183.3 @@ -7,6 +7,7 @@
   183.4  //
   183.5  
   183.6  import Foundation
   183.7 +import pEpIOSToolbox
   183.8  
   183.9  open class MimeTypeUtil {
  183.10      public static let defaultMimeType = "application/octet-stream"
   184.1 --- a/pEpForiOS/Util/MiscUtil.swift	Wed Feb 20 11:00:07 2019 +0100
   184.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   184.3 @@ -1,35 +0,0 @@
   184.4 -//
   184.5 -//  MiscUtil.swift
   184.6 -//  pEpForiOS
   184.7 -//
   184.8 -//  Created by Dirk Zimmermann on 27/06/16.
   184.9 -//  Copyright © 2016 p≡p Security S.A. All rights reserved.
  184.10 -//
  184.11 -
  184.12 -open class MiscUtil {
  184.13 -    public static func optionalHashValue<T: Hashable>(_ someVar: T?) -> Int {
  184.14 -        if let theVar = someVar {
  184.15 -            return theVar.hashValue
  184.16 -        } else {
  184.17 -            return 0
  184.18 -        }
  184.19 -    }
  184.20 -
  184.21 -    public static func isNilOrEmptyNSArray(_ array: NSArray?) -> Bool {
  184.22 -        return array == nil || array?.count == 0
  184.23 -    }
  184.24 -
  184.25 -    public static func isEmptyString(_ s: String?) -> Bool {
  184.26 -        if s == nil {
  184.27 -            return true
  184.28 -        }
  184.29 -        if s?.count == 0 {
  184.30 -            return true
  184.31 -        }
  184.32 -        return false
  184.33 -    }
  184.34 -
  184.35 -    public static func isUnitTest() -> Bool {
  184.36 -        return ProcessInfo.processInfo.environment["XCTestConfigurationFilePath"] != nil
  184.37 -    }
  184.38 -}
   185.1 --- a/pEpForiOS/Util/PEPUtil.swift	Wed Feb 20 11:00:07 2019 +0100
   185.2 +++ b/pEpForiOS/Util/PEPUtil.swift	Mon Mar 18 10:54:14 2019 +0100
   185.3 @@ -7,6 +7,7 @@
   185.4  //
   185.5  
   185.6  import MessageModel
   185.7 +import pEpIOSToolbox
   185.8  
   185.9  /**
  185.10   Simple `Hashable` implementation so PEP_rating can be put into dictionaries.
   186.1 --- a/pEpForiOS/Util/ReferenceCounter.swift	Wed Feb 20 11:00:07 2019 +0100
   186.2 +++ b/pEpForiOS/Util/ReferenceCounter.swift	Mon Mar 18 10:54:14 2019 +0100
   186.3 @@ -6,6 +6,8 @@
   186.4  //  Copyright © 2016 p≡p Security S.A. All rights reserved.
   186.5  //
   186.6  
   186.7 +import pEpIOSToolbox
   186.8 +
   186.9  /**
  186.10   Primitive class to verify memory leaks.
  186.11   */
   187.1 --- a/pEpForiOS/Util/ReplyUtil.swift	Wed Feb 20 11:00:07 2019 +0100
   187.2 +++ b/pEpForiOS/Util/ReplyUtil.swift	Mon Mar 18 10:54:14 2019 +0100
   187.3 @@ -7,6 +7,7 @@
   187.4  //
   187.5  
   187.6  import MessageModel
   187.7 +import pEpIOSToolbox
   187.8  
   187.9  public struct ReplyUtil {
  187.10      private static let nameSeparator = ", "
   188.1 --- a/pEpForiOS/Util/SegueHandlerType.swift	Wed Feb 20 11:00:07 2019 +0100
   188.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   188.3 @@ -1,32 +0,0 @@
   188.4 -//
   188.5 -//  SegueHandlerType.swift
   188.6 -//
   188.7 -//  Pattern for using segues via enumeration.
   188.8 -//  see: https://developer.apple.com/videos/wwdc/2015/?id=411
   188.9 -//
  188.10 -//  Created by Marko Tadic on 8/25/15.
  188.11 -//  Copyright © 2015 AE. All rights reserved.
  188.12 -//
  188.13 -
  188.14 -import UIKit
  188.15 -
  188.16 -public protocol SegueHandlerType {
  188.17 -    associatedtype SegueIdentifier: RawRepresentable
  188.18 -}