From c291b6a047f97f9ea7e642614f6b6adc3fb077bc Mon Sep 17 00:00:00 2001
From: jakobsbode <jakobsbode@mi.fu-berlin.de>
Date: Mon, 31 Jul 2017 21:09:30 +0200
Subject: [PATCH] added subfolder support

---
 EnzevalosContact+CoreDataClass.swift          |  2 +-
 enzevalos_iphone/AddressHandler.swift         |  2 +-
 enzevalos_iphone/AppDelegate.swift            |  2 +-
 enzevalos_iphone/DataHandler.swift            | 34 ++++++----
 enzevalos_iphone/Folder+CoreDataClass.swift   | 14 ++++-
 .../Folder+CoreDataProperties.swift           | 18 ------
 enzevalos_iphone/FolderViewController.swift   | 24 +++----
 enzevalos_iphone/InboxViewController.swift    |  6 +-
 enzevalos_iphone/ListViewController.swift     |  4 +-
 enzevalos_iphone/MailHandler.swift            | 43 ++++++-------
 enzevalos_iphone/ReadViewController.swift     |  6 +-
 enzevalos_iphone/UserData.swift               | 63 ++++++++++---------
 .../enzevalos_iphone.xcdatamodel/contents     |  7 +--
 13 files changed, 112 insertions(+), 113 deletions(-)

diff --git a/EnzevalosContact+CoreDataClass.swift b/EnzevalosContact+CoreDataClass.swift
index 785e0780..dd2ae17c 100644
--- a/EnzevalosContact+CoreDataClass.swift
+++ b/EnzevalosContact+CoreDataClass.swift
@@ -134,7 +134,7 @@ open class EnzevalosContact: NSManagedObject, Contact, Comparable {
         get {
             var myrecords = [KeyRecord]()
             for folder in DataHandler.handler.allFolders{
-                for r in DataHandler.handler.folderRecords(folder: folder.name) {
+                for r in DataHandler.handler.folderRecords(folderPath: folder.path) {
                     if r.ezContact == self {
                         myrecords.append(r)
                     }
diff --git a/enzevalos_iphone/AddressHandler.swift b/enzevalos_iphone/AddressHandler.swift
index 1b65cfdf..af8b9850 100644
--- a/enzevalos_iphone/AddressHandler.swift
+++ b/enzevalos_iphone/AddressHandler.swift
@@ -76,7 +76,7 @@ class AddressHandler {
     static var freqAlgorithm2: ([String]) -> [(UIImage, String, String, UIImage?, UIColor)] = {
         (inserted: [String]) -> [(UIImage, String, String, UIImage?, UIColor)] in
 
-        var cons = DataHandler.handler.folderRecords()
+        var cons = DataHandler.handler.folderRecords(folderPath: UserManager.backendInboxFolderPath)
         var list: [(UIImage, String, String, UIImage?, UIColor)] = []
         var localInserted = inserted
 
diff --git a/enzevalos_iphone/AppDelegate.swift b/enzevalos_iphone/AppDelegate.swift
index d8642d05..abe940e8 100644
--- a/enzevalos_iphone/AppDelegate.swift
+++ b/enzevalos_iphone/AppDelegate.swift
@@ -88,7 +88,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
         if UserDefaults.standard.bool(forKey: "reset") {
             if UserManager.loadUserValue(Attribute.userAddr) as! String == "ullimuelle@web.de" {
                 let mailhandler = MailHandler.init()
-                mailhandler.move(mails: DataHandler.handler.findFolder(name: "INBOX").mailsOfFolder, from: "INBOX", to: "Archive")
+                //mailhandler.move(mails: DataHandler.handler.findFolder(name: "INBOX").mailsOfFolder, from: "INBOX", to: "Archive")
             }
             DataHandler.handler.reset()
             Onboarding.credentials = nil
diff --git a/enzevalos_iphone/DataHandler.swift b/enzevalos_iphone/DataHandler.swift
index a225515f..7dab64ba 100644
--- a/enzevalos_iphone/DataHandler.swift
+++ b/enzevalos_iphone/DataHandler.swift
@@ -56,7 +56,17 @@ class DataHandler {
             }
             return folders
         }
+    }
     
+    //All Folders, which are not a subfolder
+    var allRootFolders: [Folder] {
+        var root: [Folder] = []
+        for f in allFolders {
+            if !f.path.contains(f.delimiter) {
+                root.append(f)
+            }
+        }
+        return root
     }
 
     
@@ -71,8 +81,8 @@ class DataHandler {
             if let newFolders = array{
                 for new in newFolders{
                     if case let folder as MCOIMAPFolder = new{
-                        let f = self.findFolder(name: folder.path) //FIXME: this should take the full path instead of the name
-                        f.delimiter = folder.delimiter.description
+                        let f = self.findFolder(with: folder.path) //FIXME: this should take the full path instead of the name
+                        f.delimiter = String(Character(UnicodeScalar(UInt8(folder.delimiter))))
                         f.flags = folder.flags
                     }
                 }
@@ -249,19 +259,19 @@ class DataHandler {
         }
 
 
-    func findFolder(name: String) -> Folder{
-        if let search = find("Folder", type: "path", search:name){
+    func findFolder(with path: String) -> Folder{
+        if let search = find("Folder", type: "path", search:path){
             if search.count > 0{
                 return search[0] as! Folder
             }
         }
         let folder  = NSEntityDescription.insertNewObject(forEntityName: "Folder", into: managedObjectContext) as! Folder
-        folder.path = name
+        folder.path = path
         return folder
     }
     
-    func existsFolder(with name: String) -> Bool {
-        if let search = find("Folder", type: "path", search:name), search.count > 0{
+    func existsFolder(with path: String) -> Bool {
+        if let search = find("Folder", type: "path", search:path), search.count > 0{
             return true
         }
         return false
@@ -414,7 +424,7 @@ class DataHandler {
 
         // -------- End handle to, cc, from addresses --------
 
-    func createMail(_ uid: UInt64, sender: MCOAddress?, receivers: [MCOAddress], cc: [MCOAddress], time: Date, received: Bool, subject: String, body: String?, flags: MCOMessageFlag, record: KeyRecord?, autocrypt: AutocryptContact?, decryptedData: DecryptedData?, folder: String = "INBOX") {
+    func createMail(_ uid: UInt64, sender: MCOAddress?, receivers: [MCOAddress], cc: [MCOAddress], time: Date, received: Bool, subject: String, body: String?, flags: MCOMessageFlag, record: KeyRecord?, autocrypt: AutocryptContact?, decryptedData: DecryptedData?, folderPath: String) {
 
             let finding = findNum("PersistentMail", type: "uid", search: uid)
             let mail: PersistentMail
@@ -485,8 +495,8 @@ class DataHandler {
                 return
             }
         
-            let myfolder = findFolder(name: folder) as Folder
-            print("DataHAndler around line 455: ", folder)
+            let myfolder = findFolder(with: folderPath) as Folder
+            print("DataHAndler around line 455: ", folderPath)
             myfolder.addToMails(mail)
             if mail.uid > myfolder.maxID{
                 myfolder.maxID = mail.uid
@@ -547,8 +557,8 @@ class DataHandler {
     
 
     
-    func folderRecords(folder: String = "INBOX") -> [KeyRecord]{
-        let folder = findFolder(name: folder) as Folder
+    func folderRecords(folderPath: String) -> [KeyRecord]{
+        let folder = findFolder(with: folderPath) as Folder
         return folder.records
     }
 
diff --git a/enzevalos_iphone/Folder+CoreDataClass.swift b/enzevalos_iphone/Folder+CoreDataClass.swift
index e6fe707f..eac4b96c 100644
--- a/enzevalos_iphone/Folder+CoreDataClass.swift
+++ b/enzevalos_iphone/Folder+CoreDataClass.swift
@@ -23,7 +23,7 @@ public class Folder: NSManagedObject {
     
     var frontendName: String {
         get {
-            return UserManager.convertToFrontendFoldername(from: name)
+            return UserManager.convertToFrontendFolderPath(from: name)
         }
     }
     
@@ -67,6 +67,18 @@ public class Folder: NSManagedObject {
         }
     }
     
+    var subfolders: [Folder] {
+        get {
+            var folders: [Folder] = []
+            for f in DataHandler.handler.allFolders {
+                if f.path.hasPrefix(path+delimiter) && f.path != path {
+                    folders.append(f)
+                }
+            }
+            return folders
+        }
+    }
+    
     private func addToRecords(_ m: PersistentMail, records: inout [KeyRecord]) {
         
         var found = false
diff --git a/enzevalos_iphone/Folder+CoreDataProperties.swift b/enzevalos_iphone/Folder+CoreDataProperties.swift
index b63d2752..ca845025 100644
--- a/enzevalos_iphone/Folder+CoreDataProperties.swift
+++ b/enzevalos_iphone/Folder+CoreDataProperties.swift
@@ -17,7 +17,6 @@ extension Folder {
     }
 
     @NSManaged public var parent: Folder?
-    @NSManaged public var subfolder: NSSet?
     @NSManaged public var mails: NSSet?
     @NSManaged public var path: String
     @NSManaged public var delimiter: String
@@ -98,23 +97,6 @@ extension Folder {
 
 }
 
-// MARK: Generated accessors for subfolder
-extension Folder {
-
-    @objc(addSubfolderObject:)
-    @NSManaged public func addToSubfolder(_ value: Folder)
-
-    @objc(removeSubfolderObject:)
-    @NSManaged public func removeFromSubfolder(_ value: Folder)
-
-    @objc(addSubfolder:)
-    @NSManaged public func addToSubfolder(_ values: NSSet)
-
-    @objc(removeSubfolder:)
-    @NSManaged public func removeFromSubfolder(_ values: NSSet)
-
-}
-
 extension Folder: Comparable {
     public static func <(lhs: Folder, rhs: Folder) -> Bool {
         return lhs.name < rhs.name
diff --git a/enzevalos_iphone/FolderViewController.swift b/enzevalos_iphone/FolderViewController.swift
index 986e2bff..9e15e6c0 100644
--- a/enzevalos_iphone/FolderViewController.swift
+++ b/enzevalos_iphone/FolderViewController.swift
@@ -19,7 +19,7 @@ class FolderViewController: UITableViewController {
         self.refreshControl?.addTarget(self, action: #selector(FolderViewController.refresh), for: UIControlEvents.valueChanged)
         
         if isFirstFolderViewController {
-            folders = DataHandler.handler.allFolders.sorted().filter { $0.name != NSLocalizedString("INBOX", comment: "") }
+            folders = DataHandler.handler.allRootFolders.sorted().filter { $0.path != UserManager.backendInboxFolderPath }
             DataHandler.handler.callForFolders(done: endRefreshing)
             navigationItem.title = NSLocalizedString("Folders", comment: "")
         }
@@ -27,12 +27,10 @@ class FolderViewController: UITableViewController {
             navigationItem.setLeftBarButton(navigationItem.backBarButtonItem, animated: false)
         }
         if let thisFolder = presentedFolder {
-            navigationItem.title = (AppDelegate.getAppDelegate().mailHandler.IMAPSession.defaultNamespace.components(fromPath: thisFolder.name) as! [String])[0]
+            navigationItem.title = UserManager.convertToFrontendFolderPath(from: thisFolder.name)
             refreshControl?.beginRefreshing()
             AppDelegate.getAppDelegate().mailHandler.firstLookUp(thisFolder.path, newMailCallback: newMails, completionCallback: endRefreshing)
-            if let set = thisFolder.subfolder, let subFolders = set.allObjects as? [Folder] {
-                folders = subFolders.sorted()
-            }
+            folders = thisFolder.subfolders.sorted()
         }
     }
     override func viewDidAppear(_ animated: Bool) {
@@ -132,7 +130,7 @@ class FolderViewController: UITableViewController {
         }
         else if indexPath.row < folders.count {
             cell.folderName.text = folders[indexPath.row].frontendName
-            cell.folderImage.image = getImage(for: folders[indexPath.row].frontendName)
+            cell.folderImage.image = getImage(for: UserManager.convertToFrontendFolderPath(from: folders[indexPath.row].path, with: folders[indexPath.row].delimiter))
         }
             
         return cell
@@ -163,7 +161,7 @@ class FolderViewController: UITableViewController {
             let destinationVC = segue.destination as! ReadViewController
             if let mail = sender as? PersistentMail {
                 destinationVC.mail = mail
-                if presentedFolder?.name == UserManager.backendDraftFolderName {
+                if let presFolder = presentedFolder, presFolder.path.hasPrefix(UserManager.backendDraftFolderPath) {
                     destinationVC.isDraft = true
                 }
             }
@@ -186,13 +184,11 @@ class FolderViewController: UITableViewController {
     }
     func endRefreshing(_ error: Bool) {
         if let thisFolder = presentedFolder {
-            if let set = thisFolder.subfolder, let subFolders = set.allObjects as? [Folder] {
-                folders = subFolders.sorted()
-                presentedFolder = thisFolder
-            }
+            folders = thisFolder.subfolders.sorted()
+            presentedFolder = thisFolder
         }
         if isFirstFolderViewController {
-            folders = DataHandler.handler.allFolders.sorted().filter { $0.name != NSLocalizedString("INBOX", comment: "") }
+            folders = DataHandler.handler.allRootFolders.sorted().filter { $0.path != UserManager.backendInboxFolderPath }
         }
         tableView.reloadData()
         refreshControl?.endRefreshing()
@@ -201,8 +197,8 @@ class FolderViewController: UITableViewController {
         print("newMails")
     }
     
-    func getImage(for name: String) -> UIImage {
-        if name == UserManager.frontendInboxFolderName {
+    func getImage(for path: String) -> UIImage {
+        if path == UserManager.frontendInboxFolderPath {
             return #imageLiteral(resourceName: "Inbox")
         }
         /* TODO: Add more in here*/
diff --git a/enzevalos_iphone/InboxViewController.swift b/enzevalos_iphone/InboxViewController.swift
index a2872f2c..8cb8c569 100644
--- a/enzevalos_iphone/InboxViewController.swift
+++ b/enzevalos_iphone/InboxViewController.swift
@@ -91,7 +91,7 @@ class InboxViewController: UITableViewController, InboxCellDelegator {
 
     func refresh(_ refreshControl: UIRefreshControl) {
         lastUpdateText = NSLocalizedString("Updating", comment: "Getting new data")
-        AppDelegate.getAppDelegate().mailHandler.firstLookUp(newMailCallback: addNewMail, completionCallback: getMailCompleted)
+        AppDelegate.getAppDelegate().mailHandler.firstLookUp(UserManager.backendInboxFolderPath, newMailCallback: addNewMail, completionCallback: getMailCompleted)
       
 
     }
@@ -123,7 +123,7 @@ class InboxViewController: UITableViewController, InboxCellDelegator {
         let cell = tableView.dequeueReusableCell(withIdentifier: "inboxCell", for: indexPath) as! InboxTableViewCell
 
         cell.delegate = self
-        cell.enzContact = DataHandler.handler.folderRecords()[indexPath.section]
+        cell.enzContact = DataHandler.handler.folderRecords(folderPath: UserManager.backendInboxFolderPath)[indexPath.section]
         
         
 
@@ -131,7 +131,7 @@ class InboxViewController: UITableViewController, InboxCellDelegator {
     }
 
     override func numberOfSections(in tableView: UITableView) -> Int {
-        return DataHandler.handler.folderRecords().count
+        return DataHandler.handler.folderRecords(folderPath: UserManager.backendInboxFolderPath).count
     }
 
     // set top and bottom seperator height
diff --git a/enzevalos_iphone/ListViewController.swift b/enzevalos_iphone/ListViewController.swift
index 2017fc75..29de6d67 100644
--- a/enzevalos_iphone/ListViewController.swift
+++ b/enzevalos_iphone/ListViewController.swift
@@ -52,7 +52,7 @@ class ListViewController: UITableViewController {
             self.title = contact!.name
             if contact!.mails.count < 20 {
                 loading = true
-                AppDelegate.getAppDelegate().mailHandler.loadMoreMails(contact!, newMailCallback: addNewMail, completionCallback: doneLoading)
+                AppDelegate.getAppDelegate().mailHandler.loadMoreMails(contact!, folderPath: UserManager.backendInboxFolderPath, newMailCallback: addNewMail, completionCallback: doneLoading)
             }
         }
     }
@@ -211,7 +211,7 @@ class ListViewController: UITableViewController {
         if y > h + reload_distance && !loading {
             print("loading new mail because we scrolled to the bottom")
             loading = true
-            AppDelegate.getAppDelegate().mailHandler.loadMoreMails(contact!, newMailCallback: addNewMail, completionCallback: doneLoading)
+            AppDelegate.getAppDelegate().mailHandler.loadMoreMails(contact!, folderPath: UserManager.backendInboxFolderPath, newMailCallback: addNewMail, completionCallback: doneLoading)
             tableView.reloadData()
         }
     }
diff --git a/enzevalos_iphone/MailHandler.swift b/enzevalos_iphone/MailHandler.swift
index 1ce30ae2..a7223680 100644
--- a/enzevalos_iphone/MailHandler.swift
+++ b/enzevalos_iphone/MailHandler.swift
@@ -281,7 +281,7 @@ class MailHandler {
     }
 
     fileprivate func createSendCopy(sendData: Data) {
-        let sentFolder = UserManager.backendSentFolderName
+        let sentFolder = UserManager.backendSentFolderPath
         if !DataHandler.handler.existsFolder(with: sentFolder) {
             let op = IMAPSession.createFolderOperation(sentFolder)
             op?.start({ error in
@@ -319,7 +319,7 @@ class MailHandler {
         if let encData = encryption.signAndEncrypt("\n" + message, mailaddresses: [useraddr]) { //ohne "\n" wird der erste Teil der Nachricht, bis sich ein einzelnen \n in einer Zeile befindet nicht in die Nachricht getan
             sendData = builder.openPGPEncryptedMessageData(withEncryptedData: encData)
             
-            let drafts = UserManager.backendDraftFolderName
+            let drafts = UserManager.backendDraftFolderPath
             
             if !DataHandler.handler.existsFolder(with: drafts) {
                 let op = IMAPSession.createFolderOperation(drafts)
@@ -335,7 +335,7 @@ class MailHandler {
     }
     
     fileprivate func saveDraft(data: Data, callback: @escaping (Error?) -> Void) {
-        let op = IMAPSession.appendMessageOperation(withFolder: UserManager.backendDraftFolderName, messageData: data, flags: MCOMessageFlag.draft)
+        let op = IMAPSession.appendMessageOperation(withFolder: UserManager.backendDraftFolderPath, messageData: data, flags: MCOMessageFlag.draft)
         op?.start({_,_ in callback(nil)})
     }
     
@@ -390,11 +390,8 @@ class MailHandler {
         }
     }
 
-    func firstLookUp(_ folder: String = "INBOX", newMailCallback: @escaping (() -> ()), completionCallback: @escaping ((_ error: Bool) -> ())) {
-        
-        let folderName = folder
-
-        findMaxUID(folderName){max in
+    func firstLookUp(_ folderPath: String, newMailCallback: @escaping (() -> ()), completionCallback: @escaping ((_ error: Bool) -> ())) {
+        findMaxUID(folderPath){max in
             var uids: MCOIndexSet
             print("Max uid: \(max)")
             var (min, overflow) = UInt64.subtractWithOverflow(max, UInt64(MailHandler.MAXMAILS))
@@ -403,38 +400,38 @@ class MailHandler {
             }
             uids = MCOIndexSet(range: MCORangeMake(min, UInt64(MailHandler.MAXMAILS))) // DataHandler.handler.maxUID
             print("call for #\(uids.count()) uids \(uids.rangesCount()); min \(min); max \(max)")
-            uids.remove(DataHandler.handler.findFolder(name: folderName).uids)
-            self.loadMessagesFromServer(uids, folder: folderName, record: nil, newMailCallback: newMailCallback, completionCallback: completionCallback)
+            uids.remove(DataHandler.handler.findFolder(with: folderPath).uids)
+            self.loadMessagesFromServer(uids, folderPath: folderPath, record: nil, newMailCallback: newMailCallback, completionCallback: completionCallback)
         
         }
         
     }
     
     
-    func olderMailsFolder(_ folder: String = "INBOX", newMailCallback: @escaping (() -> ()), completionCallback: @escaping ((_ error: Bool) -> ())) {
+    func olderMails(with folderPath: String, newMailCallback: @escaping (() -> ()), completionCallback: @escaping ((_ error: Bool) -> ())) {
         var uids: MCOIndexSet
-        let myfolder = DataHandler.handler.findFolder(name: folder)
+        let myfolder = DataHandler.handler.findFolder(with: folderPath)
         
         if myfolder.maxID <= 1{
-            return firstLookUp(newMailCallback: newMailCallback, completionCallback: completionCallback)
+            return firstLookUp(folderPath, newMailCallback: newMailCallback, completionCallback: completionCallback)
         }
         print("look for more mails: \(myfolder.lastID) to \(myfolder.maxID)")
         
         uids = MCOIndexSet(range: MCORangeMake(myfolder.lastID, myfolder.maxID))
         uids.remove(myfolder.uids)
         
-        self.loadMessagesFromServer(uids, folder: folder, record: nil, newMailCallback: newMailCallback, completionCallback: completionCallback)
+        self.loadMessagesFromServer(uids, folderPath: folderPath, record: nil, newMailCallback: newMailCallback, completionCallback: completionCallback)
     }
     
     
 
-    func loadMoreMails(_ record: KeyRecord, folder: String = "INBOX", newMailCallback: @escaping (() -> ()), completionCallback: @escaping ((_ error: Bool) -> ())) {
+    func loadMoreMails(_ record: KeyRecord, folderPath: String, newMailCallback: @escaping (() -> ()), completionCallback: @escaping ((_ error: Bool) -> ())) {
         let addresses: [MailAddress]
         addresses = record.addresses
 
         for adr in addresses {
             let searchExpr: MCOIMAPSearchExpression = MCOIMAPSearchExpression.search(from: adr.mailAddress)
-            let searchOperation: MCOIMAPSearchOperation = self.IMAPSession.searchExpressionOperation(withFolder: folder, expression: searchExpr)
+            let searchOperation: MCOIMAPSearchOperation = self.IMAPSession.searchExpressionOperation(withFolder: folderPath, expression: searchExpr)
 
             searchOperation.start { (err, indices) -> Void in
                 guard err == nil else {
@@ -453,15 +450,15 @@ class MailHandler {
                     }
                     setOfIndices = self.cutIndexSet(setOfIndices)
 
-                    self.loadMessagesFromServer(setOfIndices, record: record, newMailCallback: newMailCallback, completionCallback: completionCallback)
+                    self.loadMessagesFromServer(setOfIndices, folderPath: folderPath, record: record, newMailCallback: newMailCallback, completionCallback: completionCallback)
                 }
             }
         }
     }
 
-    func loadMessagesFromServer(_ uids: MCOIndexSet, folder: String = "INBOX", maxLoad: Int = MailHandler.MAXMAILS,record: KeyRecord?, newMailCallback: @escaping (() -> ()), completionCallback: @escaping ((_ error: Bool) -> ())) {
+    func loadMessagesFromServer(_ uids: MCOIndexSet, folderPath: String, maxLoad: Int = MailHandler.MAXMAILS,record: KeyRecord?, newMailCallback: @escaping (() -> ()), completionCallback: @escaping ((_ error: Bool) -> ())) {
         let requestKind = MCOIMAPMessagesRequestKind(rawValue: MCOIMAPMessagesRequestKind.headers.rawValue | MCOIMAPMessagesRequestKind.flags.rawValue)
-        let fetchOperation: MCOIMAPFetchMessagesOperation = self.IMAPSession.fetchMessagesOperation(withFolder: folder, requestKind: requestKind, uids: uids)
+        let fetchOperation: MCOIMAPFetchMessagesOperation = self.IMAPSession.fetchMessagesOperation(withFolder: folderPath, requestKind: requestKind, uids: uids)
         fetchOperation.extraHeaders = [AUTOCRYPTHEADER]
 
         fetchOperation.start { (err, msg, vanished) -> Void in
@@ -478,8 +475,8 @@ class MailHandler {
                     let message: MCOIMAPMessage = m as! MCOIMAPMessage
                     dispatchGroup.enter()
 
-                    let op = self.IMAPSession.fetchParsedMessageOperation(withFolder: folder, uid: message.uid)
-                    op?.start { err, data in self.parseMail(err, parser: data, message: message, record: record, folder: folder, newMailCallback: newMailCallback)
+                    let op = self.IMAPSession.fetchParsedMessageOperation(withFolder: folderPath, uid: message.uid)
+                    op?.start { err, data in self.parseMail(err, parser: data, message: message, record: record, folderPath: folderPath, newMailCallback: newMailCallback)
                         dispatchGroup.leave()
                     }
                     calledMails += 1
@@ -496,7 +493,7 @@ class MailHandler {
         }
     }
 
-    func parseMail(_ error: Error?, parser: MCOMessageParser?, message: MCOIMAPMessage, record: KeyRecord?, folder: String, newMailCallback: (() -> ())) {
+    func parseMail(_ error: Error?, parser: MCOMessageParser?, message: MCOIMAPMessage, record: KeyRecord?, folderPath: String, newMailCallback: (() -> ())) {
         guard error == nil else {
             print("Error while fetching mail: \(String(describing: error))")
             return
@@ -586,7 +583,7 @@ class MailHandler {
             }
             
             if let header = header, let from = header.from, let date = header.date {
-                _ = DataHandler.handler.createMail(UInt64(message.uid), sender: from, receivers: rec, cc: cc, time: date, received: true, subject: header.subject ?? "", body: body, flags: message.flags, record: record, autocrypt: autocrypt, decryptedData: dec, folder: folder) //TODO @Olli: fatal error: unexpectedly found nil while unwrapping an Optional value //crash wenn kein header vorhanden ist
+                _ = DataHandler.handler.createMail(UInt64(message.uid), sender: from, receivers: rec, cc: cc, time: date, received: true, subject: header.subject ?? "", body: body, flags: message.flags, record: record, autocrypt: autocrypt, decryptedData: dec, folderPath: folderPath) //TODO @Olli: fatal error: unexpectedly found nil while unwrapping an Optional value //crash wenn kein header vorhanden ist
                 newMailCallback()
             }
         }
diff --git a/enzevalos_iphone/ReadViewController.swift b/enzevalos_iphone/ReadViewController.swift
index 5240fdf6..a6a9b879 100644
--- a/enzevalos_iphone/ReadViewController.swift
+++ b/enzevalos_iphone/ReadViewController.swift
@@ -222,8 +222,8 @@ class ReadViewController: UITableViewController {
 
     @IBAction func deleteButton(_ sender: AnyObject) {
         if let mail = mail {
-            let trashFolder = UserManager.loadUserValue(Attribute.trashFolderName) as? String ?? NSLocalizedString("Trash", comment: "")
-            if mail.folder.name == trashFolder {
+            let trashFolder = UserManager.backendTrashFolderPath
+            if mail.folder.path == trashFolder {
                 AppDelegate.getAppDelegate().mailHandler.addFlag(mail.uid, flags: MCOMessageFlag.deleted, folder: mail.folder.path)
             } else {
                 AppDelegate.getAppDelegate().mailHandler.move(mails: [mail], from: mail.folder.path, to: trashFolder)
@@ -234,7 +234,7 @@ class ReadViewController: UITableViewController {
 
     @IBAction func archiveButton(_ sender: AnyObject) {
         if let mail = mail {
-            let archiveFolder = UserManager.loadUserValue(Attribute.archiveFolderName) as? String ?? NSLocalizedString("Archive", comment: "")
+            let archiveFolder = UserManager.backendArchiveFolderPath
             AppDelegate.getAppDelegate().mailHandler.move(mails: [mail], from: mail.folder.path, to: archiveFolder)
         }
         _ = navigationController?.popViewController(animated: true)
diff --git a/enzevalos_iphone/UserData.swift b/enzevalos_iphone/UserData.swift
index fc91c50d..a85ba240 100644
--- a/enzevalos_iphone/UserData.swift
+++ b/enzevalos_iphone/UserData.swift
@@ -11,7 +11,7 @@ import Foundation
 
 
 enum Attribute: Int{
-    case accountname, userName, userAddr, userPW, smtpHostname, smtpPort, imapHostname, imapPort, prefEncryption, publicKey, autocryptType, imapConnectionType, imapAuthType, smtpConnectionType, smtpAuthType, sentFolderName, draftFolderName, trashFolderName, inboxFolderName, archiveFolderName
+    case accountname, userName, userAddr, userPW, smtpHostname, smtpPort, imapHostname, imapPort, prefEncryption, publicKey, autocryptType, imapConnectionType, imapAuthType, smtpConnectionType, smtpAuthType, sentFolderPath, draftFolderPath, trashFolderPath, inboxFolderPath, archiveFolderPath
     
     var defaultValue:AnyObject? {
         switch self {
@@ -42,15 +42,15 @@ enum Attribute: Int{
         case .smtpConnectionType:
              return MCOConnectionType.TLS.rawValue as AnyObject?//startTLS.rawValue
             //return MCOConnectionType.startTLS.rawValue as AnyObject?//startTLS.rawValue
-        case .sentFolderName:
+        case .sentFolderPath:
             return NSLocalizedString("Sent", comment: "Default name for the sentFolder") as AnyObject?
-        case .draftFolderName:
+        case .draftFolderPath:
             return NSLocalizedString("Drafts", comment: "Default name for the draftFolder") as AnyObject?
-        case .trashFolderName:
+        case .trashFolderPath:
             return NSLocalizedString("Trash", comment: "Default name for the trashFolder") as AnyObject?
-        case .inboxFolderName:
+        case .inboxFolderPath:
             return NSLocalizedString("INBOX", comment: "Default name for the inboxFolder") as AnyObject?
-        case .archiveFolderName:
+        case .archiveFolderPath:
             return NSLocalizedString("Archive", comment: "Default name for the archiveFolder") as AnyObject?
             
         case .smtpAuthType:
@@ -85,72 +85,75 @@ struct UserManager{
     
     //Frontend (GUI and providers.json) uses UTF-8 String-Encoding
     //The backend uses because of the definition of IMAP UTF-7 String-Encoding
-    static var frontendDraftFolderName: String {
+    static var frontendDraftFolderPath: String {
         get {
-            return loadUserValue(Attribute.draftFolderName) as? String ?? NSLocalizedString("Drafts", comment: "")
+            return loadUserValue(Attribute.draftFolderPath) as? String ?? NSLocalizedString("Drafts", comment: "")
         }
     }
     
-    static var frontendInboxFolderName: String {
+    static var frontendInboxFolderPath: String {
         get {
-            return loadUserValue(Attribute.inboxFolderName) as? String ?? NSLocalizedString("INBOX", comment: "")
+            return loadUserValue(Attribute.inboxFolderPath) as? String ?? NSLocalizedString("INBOX", comment: "")
         }
     }
     
-    static var frontendSentFolderName: String {
+    static var frontendSentFolderPath: String {
         get {
-            return loadUserValue(Attribute.sentFolderName) as? String ?? NSLocalizedString("Sent", comment: "")
+            return loadUserValue(Attribute.sentFolderPath) as? String ?? NSLocalizedString("Sent", comment: "")
         }
     }
     
-    static var frontendArchiveFolderName: String {
+    static var frontendArchiveFolderPath
+        : String {
         get {
-            return loadUserValue(Attribute.archiveFolderName) as? String ?? NSLocalizedString("Archive", comment: "")
+            return loadUserValue(Attribute.archiveFolderPath) as? String ?? NSLocalizedString("Archive", comment: "")
         }
     }
     
-    static var frontendTrashFolderName: String {
+    static var frontendTrashFolderPath: String {
         get {
-            return loadUserValue(Attribute.trashFolderName) as? String ?? NSLocalizedString("Trash", comment: "")
+            return loadUserValue(Attribute.trashFolderPath) as? String ?? NSLocalizedString("Trash", comment: "")
         }
     }
     
-    static var backendDraftFolderName: String {
+    static var backendDraftFolderPath: String {
         get {
-            return convertToBackendFoldername(from: frontendDraftFolderName)
+            return convertToBackendFolderPath(from: frontendDraftFolderPath)
         }
     }
     
-    static var backendSentFolderName: String {
+    static var backendSentFolderPath: String {
         get {
-            return convertToBackendFoldername(from: frontendSentFolderName)
+            return convertToBackendFolderPath(from: frontendSentFolderPath)
         }
     }
     
-    static var backendArchiveFolderName: String {
+    static var backendArchiveFolderPath: String {
         get {
-            return convertToBackendFoldername(from: frontendArchiveFolderName)
+            return convertToBackendFolderPath(from: frontendArchiveFolderPath)
         }
     }
     
-    static var backendTrashFolderName: String {
+    static var backendTrashFolderPath: String {
         get {
-            return convertToBackendFoldername(from: frontendTrashFolderName)
+            return convertToBackendFolderPath(from: frontendTrashFolderPath)
         }
     }
     
-    static var backendInboxFolderName: String {
+    static var backendInboxFolderPath: String {
         get {
-            return convertToBackendFoldername(from: frontendInboxFolderName)
+            return convertToBackendFolderPath(from: frontendInboxFolderPath)
         }
     }
     
-    static func convertToFrontendFoldername(from backendFolderName: String) -> String{
-        return (AppDelegate.getAppDelegate().mailHandler.IMAPSession.defaultNamespace.components(fromPath: backendFolderName) as! [String])[0]
+    //Usable for paths too
+    static func convertToFrontendFolderPath(from backendFolderPath: String, with delimiter: String = ".") -> String{
+        return (AppDelegate.getAppDelegate().mailHandler.IMAPSession.defaultNamespace.components(fromPath: backendFolderPath) as! [String]).joined(separator: delimiter)
     }
     
-    static func convertToBackendFoldername(from frontendFolderName: String) -> String {
-        return AppDelegate.getAppDelegate().mailHandler.IMAPSession.defaultNamespace.path(forComponents: [frontendFolderName])
+    //Usable for paths too
+    static func convertToBackendFolderPath(from frontendFolderPath: String) -> String {
+        return AppDelegate.getAppDelegate().mailHandler.IMAPSession.defaultNamespace.path(forComponents: [frontendFolderPath])
     }
     
     static func storeUserValue(_ value: AnyObject?, attribute: Attribute) {
diff --git a/enzevalos_iphone/enzevalos_iphone.xcdatamodeld/enzevalos_iphone.xcdatamodel/contents b/enzevalos_iphone/enzevalos_iphone.xcdatamodeld/enzevalos_iphone.xcdatamodel/contents
index 4ca13000..180e78bb 100644
--- a/enzevalos_iphone/enzevalos_iphone.xcdatamodeld/enzevalos_iphone.xcdatamodel/contents
+++ b/enzevalos_iphone/enzevalos_iphone.xcdatamodeld/enzevalos_iphone.xcdatamodel/contents
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="12141" systemVersion="16F73" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
+<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="12141" systemVersion="16G29" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
     <entity name="Account" representedClassName="Account" syncable="YES" codeGenerationType="class">
         <attribute name="accountname" attributeType="String" syncable="YES"/>
         <attribute name="dispalyname" attributeType="String" syncable="YES"/>
@@ -20,8 +20,7 @@
         <attribute name="maxID" optional="YES" attributeType="Decimal" defaultValueString="1" syncable="YES"/>
         <attribute name="path" attributeType="String" syncable="YES"/>
         <relationship name="mails" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="PersistentMail" inverseName="folder" inverseEntity="PersistentMail" syncable="YES"/>
-        <relationship name="parent" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Folder" inverseName="subfolder" inverseEntity="Folder" syncable="YES"/>
-        <relationship name="subfolder" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Folder" inverseName="parent" inverseEntity="Folder" syncable="YES"/>
+        <relationship name="parent" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Folder" syncable="YES"/>
     </entity>
     <entity name="Mail_Address" representedClassName="Mail_Address" syncable="YES">
         <attribute name="address" attributeType="String" defaultValueString="&quot;&quot;" syncable="YES"/>
@@ -70,7 +69,7 @@
     <elements>
         <element name="Account" positionX="-288" positionY="-9" width="128" height="135"/>
         <element name="EnzevalosContact" positionX="-209" positionY="198" width="128" height="90"/>
-        <element name="Folder" positionX="-297" positionY="-18" width="128" height="165"/>
+        <element name="Folder" positionX="-297" positionY="-18" width="128" height="150"/>
         <element name="Mail_Address" positionX="-297" positionY="-18" width="128" height="195"/>
         <element name="PersistentMail" positionX="-416" positionY="-189" width="128" height="315"/>
         <element name="Server" positionX="-279" positionY="0" width="128" height="105"/>
-- 
GitLab