浏览代码

update get Master key with biometric

alqindiirsyam 8 月之前
父节点
当前提交
091c1e9f9c
共有 52 个文件被更改,包括 3256 次插入2464 次删除
  1. 14 4
      appbuilder-ios/NexilisLite/NexilisLite/Source/APIS.swift
  2. 6 1
      appbuilder-ios/NexilisLite/NexilisLite/Source/Callback.swift
  3. 12 0
      appbuilder-ios/NexilisLite/NexilisLite/Source/CoreMessage_TMessageBank.swift
  4. 1 0
      appbuilder-ios/NexilisLite/NexilisLite/Source/CoreMessage_TMessageCode.swift
  5. 41 13
      appbuilder-ios/NexilisLite/NexilisLite/Source/Database.swift
  6. 23 18
      appbuilder-ios/NexilisLite/NexilisLite/Source/Extension.swift
  7. 8 3
      appbuilder-ios/NexilisLite/NexilisLite/Source/FloatingButton/FloatingButton.swift
  8. 271 195
      appbuilder-ios/NexilisLite/NexilisLite/Source/IncomingThread.swift
  9. 21 16
      appbuilder-ios/NexilisLite/NexilisLite/Source/InquiryThread.swift
  10. 34 0
      appbuilder-ios/NexilisLite/NexilisLite/Source/MasterKeyUtil.swift
  11. 27 17
      appbuilder-ios/NexilisLite/NexilisLite/Source/Model/CategoryCC.swift
  12. 58 48
      appbuilder-ios/NexilisLite/NexilisLite/Source/Model/Chat.swift
  13. 66 41
      appbuilder-ios/NexilisLite/NexilisLite/Source/Model/Group.swift
  14. 17 12
      appbuilder-ios/NexilisLite/NexilisLite/Source/Model/Group_NM.swift
  15. 73 53
      appbuilder-ios/NexilisLite/NexilisLite/Source/Model/User.swift
  16. 13 8
      appbuilder-ios/NexilisLite/NexilisLite/Source/Model/WorkingArea.swift
  17. 304 404
      appbuilder-ios/NexilisLite/NexilisLite/Source/Nexilis.swift
  18. 127 92
      appbuilder-ios/NexilisLite/NexilisLite/Source/OutgoingThread.swift
  19. 106 62
      appbuilder-ios/NexilisLite/NexilisLite/Source/Utils.swift
  20. 41 16
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/BNIView/BNIBookingWebView.swift
  21. 13 8
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Call/AudioViewController.swift
  22. 2 2
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Call/QmeraAudioConference.swift
  23. 13 8
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Call/QmeraAudioViewController.swift
  24. 18 13
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Call/QmeraCallContactViewController.swift
  25. 48 43
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Call/QmeraVideoViewController.swift
  26. 132 87
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Chat/ChatGPTBotView.swift
  27. 316 221
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Chat/EditorGroup.swift
  28. 396 281
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Chat/EditorPersonal.swift
  29. 77 57
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Chat/EditorStarMessages.swift
  30. 16 6
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Chat/ListGroupImages.swift
  31. 18 13
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Chat/MessageInfo.swift
  32. 34 29
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Contact/ContactCallViewController.swift
  33. 254 249
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/BackupRestoreView.swift
  34. 7 2
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/BroadcastMembersTableViewController.swift
  35. 15 10
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/BroadcastViewController.swift
  36. 3 0
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/ChangeDeviceViewController.swift
  37. 6 1
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/ChangeNamePassswordViewController.swift
  38. 14 4
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/ChangeNameTableViewController.swift
  39. 65 40
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/ContactChatViewController.swift
  40. 6 1
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/GroupDescViewController.swift
  41. 90 60
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/GroupDetailViewController.swift
  42. 60 50
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/GroupMemberViewController.swift
  43. 6 1
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/GroupNameViewController.swift
  44. 6 1
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/GroupTopicViewController.swift
  45. 8 3
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/HistoryBroadcastViewController.swift
  46. 37 27
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/HistoryCCViewController.swift
  47. 79 44
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/ProfileViewController.swift
  48. 75 60
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/SetInternalCSAccount.swift
  49. 118 97
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/SettingTableViewController.swift
  50. 14 6
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/SignUpSignIn.swift
  51. 30 25
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Streaming/QmeraGroupChooserViewController.swift
  52. 17 12
      appbuilder-ios/NexilisLite/NexilisLite/Source/View/Streaming/QmeraUserChooserViewController.swift

+ 14 - 4
appbuilder-ios/NexilisLite/NexilisLite/Source/APIS.swift

@@ -21,9 +21,14 @@ public class APIS: NSObject {
     public static func getTotalCounter() -> Int32 {
         var counter: Int32?
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT SUM(counter) FROM MESSAGE_SUMMARY"), cursor.next() {
-                counter = cursor.int(forColumnIndex: 0)
-                cursor.close()
+            do {
+                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT SUM(counter) FROM MESSAGE_SUMMARY"), cursor.next() {
+                    counter = cursor.int(forColumnIndex: 0)
+                    cursor.close()
+                }
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         return counter ?? 0
@@ -761,7 +766,12 @@ public class APIS: NSObject {
             if let resp = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getChangePersonInfoName(firstname: first, lastname: last)) {
                 if resp.isOk() {
                     Database.shared.database?.inTransaction({ fmdb, rollback in
-                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: ["first_name": first , "last_name": last], _where: "f_pin = '\(User.getMyPin())'")
+                        do {
+                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: ["first_name": first , "last_name": last], _where: "f_pin = '\(User.getMyPin())'")
+                        } catch {
+                            rollback.pointee = true
+                            print("Access database error: \(error.localizedDescription)")
+                        }
                     })
                     NotificationCenter.default.post(name: NSNotification.Name(rawValue: "updateFifthTab"), object: nil, userInfo: nil)
                     DispatchQueue.main.async {

+ 6 - 1
appbuilder-ios/NexilisLite/NexilisLite/Source/Callback.swift

@@ -118,7 +118,12 @@ class Callback : CallBack {
         //print("asycnACKReceived: \(sPacketID)")
         DispatchQueue.global().async {
             Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                OutgoingThread.default.delOutgoing(fmdb: fmdb, packageId: sPacketID)
+                do {
+                    OutgoingThread.default.delOutgoing(fmdb: fmdb, packageId: sPacketID)
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
+                }
             })
         }
     }

+ 12 - 0
appbuilder-ios/NexilisLite/NexilisLite/Source/CoreMessage_TMessageBank.swift

@@ -2513,4 +2513,16 @@ public class CoreMessage_TMessageBank {
         return tmessage
     }
     
+    public static func getPrefs(key: String = "") -> TMessage {
+        let tMessage = NexilisLite.TMessage()
+        let me = User.getMyPin()
+        tMessage.mCode = CoreMessage_TMessageCode.PULL_PREFS
+        tMessage.mStatus = CoreMessage_TMessageUtil.getTID()
+        tMessage.mBodies[CoreMessage_TMessageKey.F_PIN] = me
+        if !key.isEmpty {
+            tMessage.mBodies[CoreMessage_TMessageKey.KEY] = key
+        }
+        return tMessage
+    }
+    
 }

+ 1 - 0
appbuilder-ios/NexilisLite/NexilisLite/Source/CoreMessage_TMessageCode.swift

@@ -395,6 +395,7 @@ public class CoreMessage_TMessageCode {
     public static let INIT_BATCH_GROUP_NO_MEMBERS = "GNM";
     public static let INIT_BATCH_TOPIC = "IBT";
     public static let INIT_PREFS = "ITT";
+    public static let PULL_PREFS = "PPR";
     public static let INIT_FLAG_FINISH = "IFF";
     public static let INIT_FLAG_RESET  = "IFR";
     

+ 41 - 13
appbuilder-ios/NexilisLite/NexilisLite/Source/Database.swift

@@ -17,21 +17,49 @@ public class Database {
     
     public static let shared = Database()
     
-    public let database = FMDatabaseQueue(path: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] + "/encrypted_db_es.db")
+    public var database: FMDatabaseQueue!
+    
+    func setupDatabaseQueue(withPath databasePath: String) -> FMDatabaseQueue? {
+        if !FileManager.default.fileExists(atPath: databasePath) {
+            FileManager.default.createFile(atPath: databasePath, contents: nil, attributes: nil)
+        }
+        
+        do {
+            try FileManager.default.setAttributes([.protectionKey: FileProtectionType.complete], ofItemAtPath: databasePath)
+//            print("File protection attribute set to 'complete'.")
+        } catch {
+//            print("Error setting file protection attribute: \(error)")
+            return nil
+        }
+        
+        guard let dbQueue = FMDatabaseQueue(path: databasePath) else {
+//            print("Failed to create FMDatabaseQueue.")
+            return nil
+        }
+        
+        return dbQueue
+    }
 
     
-    func openDatabase() {
-        database?.inDatabase({(fmdb) in
-            fmdb.setKey(Utils.getPasswordDB() ?? "Lumia")
-//            print("Open Done")
-        })
-        database?.inTransaction({(fmdb, rollback) in
-            do {
-                try createDatabase(fmdb: fmdb)
-//                print("Create Done")
-            } catch {
-            }
-        })
+    func openDatabase() -> Int {
+        if let key = Utils.getPasswordDB() {
+            let databasePath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] + "/encrypted_db_es.db"
+            database = setupDatabaseQueue(withPath: databasePath)
+            
+            database?.inDatabase({(fmdb) in
+                fmdb.setKey(key)
+    //            print("Open Done")
+            })
+            database?.inTransaction({(fmdb, rollback) in
+                do {
+                    try createDatabase(fmdb: fmdb)
+    //                print("Create Done")
+                } catch {
+                }
+            })
+            return 1
+        }
+        return 0
     }
     
     func createDatabase(fmdb:FMDatabase) throws -> Void{

+ 23 - 18
appbuilder-ios/NexilisLite/NexilisLite/Source/Extension.swift

@@ -391,24 +391,29 @@ extension NSObject {
     
     public func deleteAllRecordDatabase() {
         Database.shared.database?.inTransaction({ fmdb, rollback in
-            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "BUDDY", _where: "")
-            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ", _where: "")
-            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE", _where: "")
-            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ_MEMBER", _where: "")
-            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "DISCUSSION_FORUM", _where: "")
-            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "POST", _where: "")
-            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_STATUS", _where: "")
-            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "")
-            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "OUTGOING", _where: "")
-            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "FOLLOW", _where: "")
-            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_FAVORITE", _where: "")
-            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "LINK_PREVIEW", _where: "")
-            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "PULL_DB", _where: "")
-            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "PREFS", _where: "")
-            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "CALL_CENTER_HISTORY", _where: "")
-            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "FORM_DATA", _where: "")
-            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "TASK_PIC", _where: "")
-            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "TASK_DETAIL", _where: "")
+            do {
+                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "BUDDY", _where: "")
+                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ", _where: "")
+                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE", _where: "")
+                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ_MEMBER", _where: "")
+                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "DISCUSSION_FORUM", _where: "")
+                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "POST", _where: "")
+                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_STATUS", _where: "")
+                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "")
+                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "OUTGOING", _where: "")
+                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "FOLLOW", _where: "")
+                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_FAVORITE", _where: "")
+                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "LINK_PREVIEW", _where: "")
+                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "PULL_DB", _where: "")
+                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "PREFS", _where: "")
+                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "CALL_CENTER_HISTORY", _where: "")
+                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "FORM_DATA", _where: "")
+                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "TASK_PIC", _where: "")
+                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "TASK_DETAIL", _where: "")
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
+            }
         })
         Utils.setFinishInitPrefs(value: false)
     }

+ 8 - 3
appbuilder-ios/NexilisLite/NexilisLite/Source/FloatingButton/FloatingButton.swift

@@ -579,9 +579,14 @@ public class FloatingButton: UIView {
     private func queryCountCounter() -> Int32 {
         var counter: Int32?
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT SUM(counter) FROM MESSAGE_SUMMARY"), cursor.next() {
-                counter = cursor.int(forColumnIndex: 0)
-                cursor.close()
+            do {
+                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT SUM(counter) FROM MESSAGE_SUMMARY"), cursor.next() {
+                    counter = cursor.int(forColumnIndex: 0)
+                    cursor.close()
+                }
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         return counter ?? 0

+ 271 - 195
appbuilder-ios/NexilisLite/NexilisLite/Source/IncomingThread.swift

@@ -183,7 +183,7 @@ class IncomingThread {
             askingForEndCall(message: message)
         } else if message.getCode() == CoreMessage_TMessageCode.GET_BATCH_GROUP_NO_MEMBERS {
             pushGroupNoMembers(message: message)
-        } else if message.getCode() == CoreMessage_TMessageCode.INIT_PREFS {
+        } else if message.getCode() == CoreMessage_TMessageCode.INIT_PREFS || message.getCode() == CoreMessage_TMessageCode.PULL_PREFS {
             initPrefs(message: message)
         } else if message.getCode() == CoreMessage_TMessageCode.NOTIFY_TO_CALLING {
             notifyCalling(message: message)
@@ -362,7 +362,7 @@ class IncomingThread {
                         ack(message: message)
                     } catch {
                         rollback.pointee = true
-                        //print(error)
+                        print("Access database error: \(error.localizedDescription)")
                     }
                 })
             }
@@ -499,91 +499,96 @@ class IncomingThread {
                 DispatchQueue.main.async {
                     let f_pin = CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.F_PIN)
                     Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                        if message.getPIN() == User.getMyPin() {
-                            return
-                        }
-                        if let cursorUser = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_pin FROM BUDDY where f_pin='\(f_pin)'"), cursorUser.next() {
-                            return
-                        }
-                        if message.getBody(key: "is_silent") == "1" {
-                            return
-                        }
-                        let firstname = CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.FIRST_NAME)
-                        let lastname = CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.LAST_NAME)
-                        let f_pin = CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.F_PIN)
-                        if (firstname + " " + lastname).trimmingCharacters(in: .whitespaces) == "USR\(f_pin)" {
-                            return
-                        }
-                        let onGoingCC: String = SecureUserDefaults.shared.value(forKey: "onGoingCC") ?? ""
-                        if !onGoingCC.isEmpty {
-                            return
-                        }
-                        let container = UIView()
-                        container.backgroundColor = .gray
-                        let profileImage = UIImageView()
-                        profileImage.frame.size = CGSize(width: 60, height: 60)
-                        container.addSubview(profileImage)
-                        profileImage.translatesAutoresizingMaskIntoConstraints = false
-                        NSLayoutConstraint.activate([
-                            profileImage.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 8.0),
-                            profileImage.centerYAnchor.constraint(equalTo: container.centerYAnchor),
-                            profileImage.widthAnchor.constraint(equalToConstant: 60),
-                            profileImage.heightAnchor.constraint(equalToConstant: 60),
-                        ])
-                        
-                        let title = UILabel()
-                        container.addSubview(title)
-                        title.translatesAutoresizingMaskIntoConstraints = false
-                        NSLayoutConstraint.activate([
-                            title.leadingAnchor.constraint(equalTo: profileImage.trailingAnchor, constant: 8.0),
-                            title.centerYAnchor.constraint(equalTo: container.centerYAnchor),
-                            title.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: -8.0)
-                        ])
-                        title.font = UIFont.systemFont(ofSize: 14)
-                        title.text = (firstname + " " + lastname).trimmingCharacters(in: .whitespaces) + " " + "added you as friend".localized()
-                        title.textColor = .white
-                        title.numberOfLines = 0
-                        
-                        if Nexilis.shared.floating != nil {
-                            Nexilis.shared.floating.dismiss()
-                        }
-                        Nexilis.shared.floating = FloatingNotificationBanner(customView: container)
-                        Nexilis.shared.floating.bannerHeight = 100.0
-                        Nexilis.shared.floating.transparency = 0.9
-                        
-                        let profile = CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.THUMB_ID)
-                        if profile != "" {
-                            profileImage.circle()
-                            do {
-                                let documentDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
-                                let file = documentDir.appendingPathComponent(profile)
-                                if FileManager().fileExists(atPath: file.path) {
-                                    profileImage.image = UIImage(contentsOfFile: file.path)
-                                    profileImage.backgroundColor = .clear
-                                } else {
-                                    Download().startHTTP(forKey: profile) { (name, progress) in
-                                        guard progress == 100 else {
-                                            return
-                                        }
-                                        
-                                        DispatchQueue.main.async {
-                                            profileImage.image = UIImage(contentsOfFile: file.path)
-                                            profileImage.backgroundColor = .clear
-                                            Nexilis.shared.floating.show(queuePosition: .front, bannerPosition: .top, queue: NotificationBannerQueue(maxBannersOnScreenSimultaneously: 1), on: nil, edgeInsets: UIEdgeInsets(top: 8.0, left: 8.0, bottom: 0, right: 8.0), cornerRadius: 8.0, shadowColor: .clear, shadowOpacity: .zero, shadowBlurRadius: .zero, shadowCornerRadius: .zero, shadowOffset: .zero, shadowEdgeInsets: nil)
-                                            return
+                        do {
+                            if message.getPIN() == User.getMyPin() {
+                                return
+                            }
+                            if let cursorUser = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_pin FROM BUDDY where f_pin='\(f_pin)'"), cursorUser.next() {
+                                return
+                            }
+                            if message.getBody(key: "is_silent") == "1" {
+                                return
+                            }
+                            let firstname = CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.FIRST_NAME)
+                            let lastname = CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.LAST_NAME)
+                            let f_pin = CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.F_PIN)
+                            if (firstname + " " + lastname).trimmingCharacters(in: .whitespaces) == "USR\(f_pin)" {
+                                return
+                            }
+                            let onGoingCC: String = SecureUserDefaults.shared.value(forKey: "onGoingCC") ?? ""
+                            if !onGoingCC.isEmpty {
+                                return
+                            }
+                            let container = UIView()
+                            container.backgroundColor = .gray
+                            let profileImage = UIImageView()
+                            profileImage.frame.size = CGSize(width: 60, height: 60)
+                            container.addSubview(profileImage)
+                            profileImage.translatesAutoresizingMaskIntoConstraints = false
+                            NSLayoutConstraint.activate([
+                                profileImage.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 8.0),
+                                profileImage.centerYAnchor.constraint(equalTo: container.centerYAnchor),
+                                profileImage.widthAnchor.constraint(equalToConstant: 60),
+                                profileImage.heightAnchor.constraint(equalToConstant: 60),
+                            ])
+                            
+                            let title = UILabel()
+                            container.addSubview(title)
+                            title.translatesAutoresizingMaskIntoConstraints = false
+                            NSLayoutConstraint.activate([
+                                title.leadingAnchor.constraint(equalTo: profileImage.trailingAnchor, constant: 8.0),
+                                title.centerYAnchor.constraint(equalTo: container.centerYAnchor),
+                                title.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: -8.0)
+                            ])
+                            title.font = UIFont.systemFont(ofSize: 14)
+                            title.text = (firstname + " " + lastname).trimmingCharacters(in: .whitespaces) + " " + "added you as friend".localized()
+                            title.textColor = .white
+                            title.numberOfLines = 0
+                            
+                            if Nexilis.shared.floating != nil {
+                                Nexilis.shared.floating.dismiss()
+                            }
+                            Nexilis.shared.floating = FloatingNotificationBanner(customView: container)
+                            Nexilis.shared.floating.bannerHeight = 100.0
+                            Nexilis.shared.floating.transparency = 0.9
+                            
+                            let profile = CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.THUMB_ID)
+                            if profile != "" {
+                                profileImage.circle()
+                                do {
+                                    let documentDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
+                                    let file = documentDir.appendingPathComponent(profile)
+                                    if FileManager().fileExists(atPath: file.path) {
+                                        profileImage.image = UIImage(contentsOfFile: file.path)
+                                        profileImage.backgroundColor = .clear
+                                    } else {
+                                        Download().startHTTP(forKey: profile) { (name, progress) in
+                                            guard progress == 100 else {
+                                                return
+                                            }
+                                            
+                                            DispatchQueue.main.async {
+                                                profileImage.image = UIImage(contentsOfFile: file.path)
+                                                profileImage.backgroundColor = .clear
+                                                Nexilis.shared.floating.show(queuePosition: .front, bannerPosition: .top, queue: NotificationBannerQueue(maxBannersOnScreenSimultaneously: 1), on: nil, edgeInsets: UIEdgeInsets(top: 8.0, left: 8.0, bottom: 0, right: 8.0), cornerRadius: 8.0, shadowColor: .clear, shadowOpacity: .zero, shadowBlurRadius: .zero, shadowCornerRadius: .zero, shadowOffset: .zero, shadowEdgeInsets: nil)
+                                                return
+                                            }
                                         }
                                     }
-                                }
-                            } catch {}
-                            profileImage.contentMode = .scaleAspectFill
-                        } else {
-                            profileImage.circle()
-                            profileImage.image = UIImage(systemName: "person")
-                            profileImage.contentMode = .scaleAspectFit
-                            profileImage.backgroundColor = .lightGray
-                            profileImage.tintColor = .white
+                                } catch {}
+                                profileImage.contentMode = .scaleAspectFill
+                            } else {
+                                profileImage.circle()
+                                profileImage.image = UIImage(systemName: "person")
+                                profileImage.contentMode = .scaleAspectFit
+                                profileImage.backgroundColor = .lightGray
+                                profileImage.tintColor = .white
+                            }
+                            Nexilis.shared.floating.show(queuePosition: .front, bannerPosition: .top, queue: NotificationBannerQueue(maxBannersOnScreenSimultaneously: 1), on: nil, edgeInsets: UIEdgeInsets(top: 8.0, left: 8.0, bottom: 0, right: 8.0), cornerRadius: 8.0, shadowColor: .clear, shadowOpacity: .zero, shadowBlurRadius: .zero, shadowCornerRadius: .zero, shadowOffset: .zero, shadowEdgeInsets: nil)
+                        } catch {
+                            rollback.pointee = true
+                            print("Access database error: \(error.localizedDescription)")
                         }
-                        Nexilis.shared.floating.show(queuePosition: .front, bannerPosition: .top, queue: NotificationBannerQueue(maxBannersOnScreenSimultaneously: 1), on: nil, edgeInsets: UIEdgeInsets(top: 8.0, left: 8.0, bottom: 0, right: 8.0), cornerRadius: 8.0, shadowColor: .clear, shadowOpacity: .zero, shadowBlurRadius: .zero, shadowCornerRadius: .zero, shadowOffset: .zero, shadowEdgeInsets: nil)
                     })
                 }
             }
@@ -595,12 +600,17 @@ class IncomingThread {
         var err_code = "10"
         if !message_id.isEmpty {
             Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select message_id from MESSAGE where message_id = '\(message_id)'") {
-                    if cursor.next() {
-                        err_code = "00"
+                do {
+                    if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select message_id from MESSAGE where message_id = '\(message_id)'") {
+                        if cursor.next() {
+                            err_code = "00"
+                        }
+                        _ = Nexilis.write(message: CoreMessage_TMessageBank.getInquiry(message_id: message_id, error_code: err_code, data: message_id))
+                        cursor.close()
                     }
-                    _ = Nexilis.write(message: CoreMessage_TMessageBank.getInquiry(message_id: message_id, error_code: err_code, data: message_id))
-                    cursor.close()
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
                 }
             })
         }
@@ -618,17 +628,22 @@ class IncomingThread {
         } else {
             //print("MASUK MINQ SEND CHAT")
             Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select message from INQUIRY where id = '\(message_id)'"), cursor.next() {
-                    if let message = cursor.string(forColumnIndex: 0) {
-                        //print("MASUK MINQ ADA MESSAGE")
-                        OutgoingThread.default.addQueue(message: TMessage(data: message))
-                        if message_scope != "3" {
-                            DispatchQueue.main.async {
-                                self.updateInquiry(messageId: message_id)
+                do {
+                    if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select message from INQUIRY where id = '\(message_id)'"), cursor.next() {
+                        if let message = cursor.string(forColumnIndex: 0) {
+                            //print("MASUK MINQ ADA MESSAGE")
+                            OutgoingThread.default.addQueue(message: TMessage(data: message))
+                            if message_scope != "3" {
+                                DispatchQueue.main.async {
+                                    self.updateInquiry(messageId: message_id)
+                                }
                             }
                         }
+                        cursor.close()
                     }
-                    cursor.close()
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
                 }
             })
         }
@@ -637,9 +652,14 @@ class IncomingThread {
     private func updateInquiry(messageId: String) {
         //print("UPDATE INQUIRY")
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            _ = Database.shared.updateRecord(fmdb: fmdb, table: "INQUIRY", cvalues: [
-                "status" : "1"
-            ], _where: "id = '\(messageId)'")
+            do {
+                _ = Database.shared.updateRecord(fmdb: fmdb, table: "INQUIRY", cvalues: [
+                    "status" : "1"
+                ], _where: "id = '\(messageId)'")
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
+            }
         })
     }
     
@@ -676,9 +696,14 @@ class IncomingThread {
         let block = message.getBody(key: CoreMessage_TMessageKey.BLOCK)
         //print ("BLOCK INCOMING \(block)")
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
-                "ex_block" : block
-            ], _where: "f_pin = '\(l_pin)'")
+            do {
+                _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
+                    "ex_block" : block
+                ], _where: "f_pin = '\(l_pin)'")
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
+            }
         })
         if let delegate = Nexilis.shared.personInfoDelegate {
             var object = [String:String]()
@@ -721,27 +746,32 @@ class IncomingThread {
         let type = message.getBody(key: CoreMessage_TMessageKey.DELETE_MESSAGE_FLAG)
         
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            if type == "1" {
-                if !messageId.contains("'") {
-                    messageId = "'\(messageId)'"
+            do {
+                if type == "1" {
+                    if !messageId.contains("'") {
+                        messageId = "'\(messageId)'"
+                    }
+                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                        "message_text" : "🚫 _This message was deleted_",
+                        "lock" : "1",
+                        "thumb_id" : "",
+                        "image_id" : "",
+                        "file_id" : "",
+                        "audio_id" : "",
+                        "video_id" : "",
+                        "reff_id" : "",
+                        "attachment_flag" : 0,
+                        "is_stared" : "0",
+                        "credential" : "0",
+                        "read_receipts" : "4"
+                    ], _where: "message_id = \(messageId)")
                 }
-                _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                    "message_text" : "🚫 _This message was deleted_",
-                    "lock" : "1",
-                    "thumb_id" : "",
-                    "image_id" : "",
-                    "file_id" : "",
-                    "audio_id" : "",
-                    "video_id" : "",
-                    "reff_id" : "",
-                    "attachment_flag" : 0,
-                    "is_stared" : "0",
-                    "credential" : "0",
-                    "read_receipts" : "4"
-                ], _where: "message_id = \(messageId)")
-            }
-            if let delegate = Nexilis.shared.messageDelegate {
-                delegate.onMessage(message: message)
+                if let delegate = Nexilis.shared.messageDelegate {
+                    delegate.onMessage(message: message)
+                }
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         ack(message: message)
@@ -811,7 +841,12 @@ class IncomingThread {
     private func deleteChat(message: TMessage) -> Void {
         let chat_id = message.getBody(key: CoreMessage_TMessageKey.CHAT_ID)
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "DISCUSSION_FORUM", _where: "chat_id = '\(chat_id)'")
+            do {
+                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "DISCUSSION_FORUM", _where: "chat_id = '\(chat_id)'")
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
+            }
         })
         if let delegate = Nexilis.shared.groupDelegate {
             delegate.onTopic(code: message.getCode(), f_pin: message.getPIN(), topicId: chat_id)
@@ -822,9 +857,14 @@ class IncomingThread {
     private func updateChat(message: TMessage) -> Void {
         let chat_id = message.getBody(key: CoreMessage_TMessageKey.CHAT_ID)
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            _ = Database.shared.updateRecord(fmdb: fmdb, table: "DISCUSSION_FORUM", cvalues: [
-                "title" : message.getBody(key: CoreMessage_TMessageKey.TITLE)
-            ], _where: "chat_id = '\(chat_id)'")
+            do {
+                _ = Database.shared.updateRecord(fmdb: fmdb, table: "DISCUSSION_FORUM", cvalues: [
+                    "title" : message.getBody(key: CoreMessage_TMessageKey.TITLE)
+                ], _where: "chat_id = '\(chat_id)'")
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
+            }
         })
         if let delegate = Nexilis.shared.groupDelegate {
             delegate.onTopic(code: message.getCode(), f_pin: message.getPIN(), topicId: chat_id)
@@ -854,7 +894,7 @@ class IncomingThread {
                         ack(message: message)
                     } catch {
                         rollback.pointee = true
-                        //print(error)
+                        print("Access database error: \(error.localizedDescription)")
                     }
                 })
             }
@@ -887,7 +927,12 @@ class IncomingThread {
         if (!is_edu.isEmpty) { cvalues["is_education"] = official }
         
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            _ = Database.shared.updateRecord(fmdb: fmdb, table: "GROUPZ", cvalues: cvalues, _where: "group_id = '\(group_id)'")
+            do {
+                _ = Database.shared.updateRecord(fmdb: fmdb, table: "GROUPZ", cvalues: cvalues, _where: "group_id = '\(group_id)'")
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
+            }
         })
         if let delegate = Nexilis.shared.groupDelegate {
             delegate.onGroup(code: message.getCode(), f_pin: message.getPIN(), groupId: group_id)
@@ -900,57 +945,67 @@ class IncomingThread {
         let group_id = message.getBody(key: CoreMessage_TMessageKey.GROUP_ID)
         if let me = User.getMyPin(), me == f_pin {
             Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                if let cursorIsEducation = Database.shared.getRecords(fmdb: fmdb, query: "select is_education from GROUPZ where group_id='\(group_id)'"), cursorIsEducation.next() {
-                    let is_education = Int(cursorIsEducation.int(forColumnIndex: 0))
-                    if (is_education == 3 || is_education == 2 || is_education == 4) {
-                        _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ_MEMBER", _where: "group_id = '\(group_id)' and f_pin = '\(f_pin)'")
-                        _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE", _where: "l_pin='\(group_id)'")
-                        _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "l_pin='\(group_id)'")
-                        if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select chat_id from DISCUSSION_FORUM where group_id='\(group_id)'") {
-                            while cursor.next() {
-                                if let chat_id = cursor.string(forColumnIndex: 0) {
-                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "l_pin='\(chat_id)'")
+                do {
+                    if let cursorIsEducation = Database.shared.getRecords(fmdb: fmdb, query: "select is_education from GROUPZ where group_id='\(group_id)'"), cursorIsEducation.next() {
+                        let is_education = Int(cursorIsEducation.int(forColumnIndex: 0))
+                        if (is_education == 3 || is_education == 2 || is_education == 4) {
+                            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ_MEMBER", _where: "group_id = '\(group_id)' and f_pin = '\(f_pin)'")
+                            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE", _where: "l_pin='\(group_id)'")
+                            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "l_pin='\(group_id)'")
+                            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select chat_id from DISCUSSION_FORUM where group_id='\(group_id)'") {
+                                while cursor.next() {
+                                    if let chat_id = cursor.string(forColumnIndex: 0) {
+                                        _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "l_pin='\(chat_id)'")
+                                    }
                                 }
+                                cursor.close()
                             }
-                            cursor.close()
-                        }
-                    } else {
-                        _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ", _where: "group_id = '\(group_id)'")
-                        _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE", _where: "l_pin='\(group_id)'")
-                        _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "l_pin='\(group_id)'")
-                        if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select chat_id from DISCUSSION_FORUM where group_id='\(group_id)'") {
-                            while cursor.next() {
-                                if let chat_id = cursor.string(forColumnIndex: 0) {
-                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "l_pin='\(chat_id)'")
+                        } else {
+                            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ", _where: "group_id = '\(group_id)'")
+                            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE", _where: "l_pin='\(group_id)'")
+                            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "l_pin='\(group_id)'")
+                            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select chat_id from DISCUSSION_FORUM where group_id='\(group_id)'") {
+                                while cursor.next() {
+                                    if let chat_id = cursor.string(forColumnIndex: 0) {
+                                        _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "l_pin='\(chat_id)'")
+                                    }
                                 }
+                                cursor.close()
                             }
-                            cursor.close()
-                        }
-                        if let cursorSub = Database.shared.getRecords(fmdb: fmdb, query: "select group_id from GROUPZ where parent='\(group_id)'") {
-                            while cursorSub.next() {
-                                if let subGroup = cursorSub.string(forColumnIndex: 0) {
-                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ", _where: "group_id = '\(subGroup)'")
-                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE", _where: "l_pin='\(subGroup)'")
-                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "l_pin='\(subGroup)'")
-                                    if let cursorSubGroupTopic = Database.shared.getRecords(fmdb: fmdb, query: "select chat_id from DISCUSSION_FORUM where group_id='\(subGroup)'") {
-                                        while cursorSubGroupTopic.next() {
-                                            if let chat_id_sub = cursorSubGroupTopic.string(forColumnIndex: 0) {
-                                                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "l_pin='\(chat_id_sub)'")
+                            if let cursorSub = Database.shared.getRecords(fmdb: fmdb, query: "select group_id from GROUPZ where parent='\(group_id)'") {
+                                while cursorSub.next() {
+                                    if let subGroup = cursorSub.string(forColumnIndex: 0) {
+                                        _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ", _where: "group_id = '\(subGroup)'")
+                                        _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE", _where: "l_pin='\(subGroup)'")
+                                        _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "l_pin='\(subGroup)'")
+                                        if let cursorSubGroupTopic = Database.shared.getRecords(fmdb: fmdb, query: "select chat_id from DISCUSSION_FORUM where group_id='\(subGroup)'") {
+                                            while cursorSubGroupTopic.next() {
+                                                if let chat_id_sub = cursorSubGroupTopic.string(forColumnIndex: 0) {
+                                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "l_pin='\(chat_id_sub)'")
+                                                }
                                             }
+                                            cursorSubGroupTopic.close()
                                         }
-                                        cursorSubGroupTopic.close()
                                     }
                                 }
+                                cursorSub.close()
                             }
-                            cursorSub.close()
                         }
+                        cursorIsEducation.close()
                     }
-                    cursorIsEducation.close()
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
                 }
             })
         } else {
             Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ_MEMBER", _where: "group_id = '\(group_id)' and f_pin = '\(f_pin)'")
+                do {
+                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ_MEMBER", _where: "group_id = '\(group_id)' and f_pin = '\(f_pin)'")
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
+                }
             })
         }
         if let delegate = Nexilis.shared.groupDelegate {
@@ -964,9 +1019,14 @@ class IncomingThread {
         let f_pin = message.getBody(key: CoreMessage_TMessageKey.F_PIN)
         let position = message.getBody(key: CoreMessage_TMessageKey.POSITION)
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            _ = Database.shared.updateRecord(fmdb: fmdb, table: "GROUPZ_MEMBER", cvalues: [
-                "position" : position
-            ], _where: "group_id = '\(group_id)' and f_pin = '\(f_pin)'")
+            do {
+                _ = Database.shared.updateRecord(fmdb: fmdb, table: "GROUPZ_MEMBER", cvalues: [
+                    "position" : position
+                ], _where: "group_id = '\(group_id)' and f_pin = '\(f_pin)'")
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
+            }
         })
         if let delegate = Nexilis.shared.groupDelegate {
             delegate.onMember(code: message.getCode(), f_pin: message.getPIN(), groupId: group_id, member: f_pin)
@@ -1006,7 +1066,7 @@ class IncomingThread {
                             ack(message: message)
                         } catch {
                             rollback.pointee = true
-                            //print(error)
+                            print("Access database error: \(error.localizedDescription)")
                         }
                     })
                 }
@@ -1045,7 +1105,7 @@ class IncomingThread {
                         }
                     } catch {
                         rollback.pointee = true
-                        //print(error)
+                        print("Access database error: \(error.localizedDescription)")
                     }
                 })
             }
@@ -1088,7 +1148,7 @@ class IncomingThread {
                         ack(message: message)
                     } catch {
                         rollback.pointee = true
-                        //print(error)
+                        print("Access database error: \(error.localizedDescription)")
                     }
                 })
             }
@@ -1125,7 +1185,7 @@ class IncomingThread {
                     }
                 } catch {
                     rollback.pointee = true
-                    //print(error)
+                    print("Access database error: \(error.localizedDescription)")
                 }
             })
         }
@@ -1164,7 +1224,7 @@ class IncomingThread {
                         ack(message: message)
                     } catch {
                         rollback.pointee = true
-                        //print(error)
+                        print("Access database error: \(error.localizedDescription)")
                     }
                 })
             }
@@ -1198,7 +1258,7 @@ class IncomingThread {
                     }
                 } catch {
                     rollback.pointee = true
-                    //print(error)
+                    print("Access database error: \(error.localizedDescription)")
                 }
             })
         }
@@ -1212,10 +1272,15 @@ class IncomingThread {
             return
         }
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select message_id from MESSAGE where message_id = '\(message_id)'"), cursor.next() {
-                ack(message: message)
-                cursor.close()
-                return
+            do {
+                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select message_id from MESSAGE where message_id = '\(message_id)'"), cursor.next() {
+                    ack(message: message)
+                    cursor.close()
+                    return
+                }
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         let media = message.getMedia()
@@ -1367,7 +1432,7 @@ class IncomingThread {
                     ack(message: message)
                 } catch {
                     rollback.pointee = true
-                    //print(error)
+                    print("Access database error: \(error.localizedDescription)")
                 }
             })
         }
@@ -1390,6 +1455,9 @@ class IncomingThread {
                     }
                 }
                 ack(message: message)
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
     }
@@ -1528,7 +1596,7 @@ class IncomingThread {
                 }
             } catch {
                 rollback.pointee = true
-                //print(error)
+                print("Access database error: \(error.localizedDescription)")
             }
         })
     }
@@ -1582,7 +1650,7 @@ class IncomingThread {
                     ack(message: message)
                 } catch {
                     rollback.pointee = true
-                    //print(error)
+                    print("Access database error: \(error.localizedDescription)")
                 }
             })
         }
@@ -1619,7 +1687,7 @@ class IncomingThread {
                     ack(message: message)
                 } catch {
                     rollback.pointee = true
-                    //print(error)
+                    print("Access database error: \(error.localizedDescription)")
                 }
             })
         }
@@ -1662,7 +1730,7 @@ class IncomingThread {
                     ack(message: message)
                 } catch {
                     rollback.pointee = true
-                    //print(error)
+                    print("Access database error: \(error.localizedDescription)")
                 }
             })
         }
@@ -1750,17 +1818,22 @@ class IncomingThread {
             delegate.onUpdatePersonInfo(state: 00, message: connected)
         }
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
-                "first_name" : fname,
-                "last_name" : lname,
-                "offline_mode" : offline_mode,
-                "auto_quote" : auto_quote,
-                "cell" : cell,
-                "connected" : connected,
-                "latitude" : latitude,
-                "last_loc_update" : last_loc_update,
-                "user_type" : user_type
-            ], _where: "f_pin = '\(fPin)'")
+            do {
+                _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
+                    "first_name" : fname,
+                    "last_name" : lname,
+                    "offline_mode" : offline_mode,
+                    "auto_quote" : auto_quote,
+                    "cell" : cell,
+                    "connected" : connected,
+                    "latitude" : latitude,
+                    "last_loc_update" : last_loc_update,
+                    "user_type" : user_type
+                ], _where: "f_pin = '\(fPin)'")
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
+            }
         })
         ack(message: message)
     }
@@ -2007,7 +2080,7 @@ class IncomingThread {
                 ack(message: message)
             } catch {
                 rollback.pointee = true
-                //print(error)
+                print("Access database error: \(error.localizedDescription)")
             }
         })
     }
@@ -2150,6 +2223,9 @@ class IncomingThread {
                              }
                         }
                     }
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
                 }
             })
             ack(message: message)

+ 21 - 16
appbuilder-ios/NexilisLite/NexilisLite/Source/InquiryThread.swift

@@ -23,25 +23,30 @@ class InquiryThread {
     
     init() {
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select status, message, id from INQUIRY") {
-                while cursor.next() {
-                    let status = cursor.int(forColumnIndex: 0)
-                    if status == 1 {
-                        delInquiry(fmdb: fmdb, messageId: cursor.string(forColumnIndex: 2)!)
-                        continue
-                    }
-                    if let cursorMessage = Database.shared.getRecords(fmdb: fmdb, query: "select message_id from MESSAGE where message_id = '\(cursor.string(forColumnIndex: 2)!)'") {
-                        if cursorMessage.next() {
-                            if let message = cursor.string(forColumnIndex: 1) {
-                                addQueue(message: TMessage(data: message))
-                            }
-                        } else {
+            do {
+                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select status, message, id from INQUIRY") {
+                    while cursor.next() {
+                        let status = cursor.int(forColumnIndex: 0)
+                        if status == 1 {
                             delInquiry(fmdb: fmdb, messageId: cursor.string(forColumnIndex: 2)!)
+                            continue
+                        }
+                        if let cursorMessage = Database.shared.getRecords(fmdb: fmdb, query: "select message_id from MESSAGE where message_id = '\(cursor.string(forColumnIndex: 2)!)'") {
+                            if cursorMessage.next() {
+                                if let message = cursor.string(forColumnIndex: 1) {
+                                    addQueue(message: TMessage(data: message))
+                                }
+                            } else {
+                                delInquiry(fmdb: fmdb, messageId: cursor.string(forColumnIndex: 2)!)
+                            }
+                            cursorMessage.close()
                         }
-                        cursorMessage.close()
                     }
+                    cursor.close()
                 }
-                cursor.close()
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
     }
@@ -77,7 +82,7 @@ class InquiryThread {
                         ], replace: true)
                     } catch {
                         rollback.pointee = true
-                        //print(error)
+                        print("Access database error: \(error.localizedDescription)")
                     }
                 })
             }

+ 34 - 0
appbuilder-ios/NexilisLite/NexilisLite/Source/MasterKeyUtil.swift

@@ -6,6 +6,7 @@
 //
 
 import CryptoKit
+import LocalAuthentication
 
 
 public class MasterKeyUtil {
@@ -59,6 +60,17 @@ public class MasterKeyUtil {
         }
     }
     
+    func isDeviceNotSecure() -> Bool {
+        let context = LAContext()
+        var error: NSError?
+        
+        if !context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) || Utils.shouldRequestAuthentication() {
+            return true
+        } else {
+            return false
+        }
+    }
+    
     func isKeyExists(keyAliasCode: String) throws -> Bool {
         let query: [String: Any] = [
             kSecClass as String: kSecClassKey,
@@ -77,6 +89,28 @@ public class MasterKeyUtil {
     }
     
     func getMasterKey() throws -> SymmetricKey {
+        if (Nexilis.checkingAccess(key: "authentication") && isDeviceNotSecure()) {
+            var result = false
+            Nexilis.dispatch = DispatchGroup()
+            Nexilis.dispatch?.enter()
+            Utils.authenticateWithBiometrics { success, errorMessage in
+                if success {
+                    print("Access granted!")
+                    result = true
+                } else {
+                    print("Access denied: \(errorMessage ?? "Unknown error")")
+                }
+                if let dispatch = Nexilis.dispatch {
+                    dispatch.leave()
+                }
+            }
+            Nexilis.dispatch?.wait()
+            Nexilis.dispatch = nil
+            if !result {
+                Utils.showAlert(title: "Failed to get Master Key".localized(), message: "Biometric authentication hasn't been set up/Biometric invalid.".localized())
+                throw NSError(domain: "KeychainError", code: -99, userInfo: nil)
+            }
+        }
         let query: [String: Any] = [
             kSecClass as String: kSecClassKey,
             kSecAttrApplicationTag as String: keyAlias,

+ 27 - 17
appbuilder-ios/NexilisLite/NexilisLite/Source/Model/CategoryCC.swift

@@ -35,16 +35,21 @@ public class CategoryCC: Model {
     public static func getDatafromParent(parent: String) -> [CategoryCC] {
         var data: [CategoryCC] = []
         Database.shared.database?.inTransaction({ fmdb, rollback in
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select id, service_id, service_name, description, parent, is_tablet from SERVICE_BANK where parent = '\(parent)'") {
-                while cursor.next() {
-                    data.append(CategoryCC(id: cursor.string(forColumnIndex: 0) ?? "",
-                                           service_id: cursor.string(forColumnIndex: 1) ?? "",
-                                           service_name: cursor.string(forColumnIndex: 2) ?? "",
-                                           parent: cursor.string(forColumnIndex: 4) ?? "",
-                                           description: cursor.string(forColumnIndex: 3) ?? "",
-                                           is_tablet: cursor.string(forColumnIndex: 5) ?? ""))
+            do {
+                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select id, service_id, service_name, description, parent, is_tablet from SERVICE_BANK where parent = '\(parent)'") {
+                    while cursor.next() {
+                        data.append(CategoryCC(id: cursor.string(forColumnIndex: 0) ?? "",
+                                               service_id: cursor.string(forColumnIndex: 1) ?? "",
+                                               service_name: cursor.string(forColumnIndex: 2) ?? "",
+                                               parent: cursor.string(forColumnIndex: 4) ?? "",
+                                               description: cursor.string(forColumnIndex: 3) ?? "",
+                                               is_tablet: cursor.string(forColumnIndex: 5) ?? ""))
+                    }
+                    cursor.close()
                 }
-                cursor.close()
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         return data
@@ -53,14 +58,19 @@ public class CategoryCC: Model {
     public static func getDataFromServiceId(service_id: String) -> CategoryCC? {
         var data: CategoryCC?
         Database.shared.database?.inTransaction({ fmdb, rollback in
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select id, service_id, service_name, description, parent, is_tablet from SERVICE_BANK where service_id = '\(service_id)'"), cursor.next() {
-                data = CategoryCC(id: cursor.string(forColumnIndex: 0) ?? "",
-                                  service_id: cursor.string(forColumnIndex: 1) ?? "",
-                                  service_name: cursor.string(forColumnIndex: 2) ?? "",
-                                  parent: cursor.string(forColumnIndex: 4) ?? "",
-                                  description: cursor.string(forColumnIndex: 3) ?? "",
-                                  is_tablet: cursor.string(forColumnIndex: 5) ?? "")
-                cursor.close()
+            do {
+                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select id, service_id, service_name, description, parent, is_tablet from SERVICE_BANK where service_id = '\(service_id)'"), cursor.next() {
+                    data = CategoryCC(id: cursor.string(forColumnIndex: 0) ?? "",
+                                      service_id: cursor.string(forColumnIndex: 1) ?? "",
+                                      service_name: cursor.string(forColumnIndex: 2) ?? "",
+                                      parent: cursor.string(forColumnIndex: 4) ?? "",
+                                      description: cursor.string(forColumnIndex: 3) ?? "",
+                                      is_tablet: cursor.string(forColumnIndex: 5) ?? "")
+                    cursor.close()
+                }
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         return data

+ 58 - 48
appbuilder-ios/NexilisLite/NexilisLite/Source/Model/Chat.swift

@@ -78,13 +78,18 @@ public class Chat: Model {
     public static func getMessageFromSearch(text: String = "") -> [String] {
         var messages: [String] = []
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            let query = "select message_id FROM MESSAGE where message_text LIKE '%\(text)%'"
-            if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: query) {
-                while cursorData.next() {
-                    let data = cursorData.string(forColumnIndex: 0) ?? ""
-                    messages.append(data)
+            do {
+                let query = "select message_id FROM MESSAGE where message_text LIKE '%\(text)%'"
+                if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: query) {
+                    while cursorData.next() {
+                        let data = cursorData.string(forColumnIndex: 0) ?? ""
+                        messages.append(data)
+                    }
+                    cursorData.close()
                 }
-                cursorData.close()
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         return messages
@@ -105,49 +110,54 @@ public class Chat: Model {
     public static func getData(messageId: String = "") -> [Chat] {
         var chats: [Chat] = []
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            let query = """
-                        select m.f_pin, ms.l_pin, ms.message_id, ms.counter, m.message_text, m.server_date, m.image_id, m.video_id, m.file_id, m.attachment_flag, m.message_scope_id, b.first_name || ' ' || ifnull(b.last_name, '') name, b.image_id profile, b.official_account, m.status, m.credential, m.lock from MESSAGE_SUMMARY ms, MESSAGE m, BUDDY b where ms.message_id = m.message_id and ms.l_pin = b.f_pin \(messageId.isEmpty ? "" : " and m.message_id = '\(messageId)'")
-                        union
-                        select m.f_pin, ms.l_pin, ms.message_id, ms.counter, m.message_text, m.server_date, m.image_id, m.video_id, m.file_id, m.attachment_flag, m.message_scope_id, 'Bot' name, '' profile, '', m.status, m.credential, m.lock from MESSAGE_SUMMARY ms, MESSAGE m where ms.message_id = m.message_id and ms.l_pin = '-999' \(messageId.isEmpty ? "" : " and m.message_id = '\(messageId)'")
-                        union
-                        select m.f_pin, ms.l_pin, ms.message_id, ms.counter, m.message_text, m.server_date, m.image_id, m.video_id, m.file_id, m.attachment_flag, m.message_scope_id, b.f_name || ' (\("Lounge".localized()))', b.image_id profile, b.official, m.status, m.credential, m.lock from MESSAGE_SUMMARY ms, MESSAGE m, GROUPZ b where ms.message_id = m.message_id and ms.l_pin = b.group_id \(messageId.isEmpty ? "" : " and m.message_id = '\(messageId)'")
-                        union
-                        select m.f_pin, ms.l_pin, ms.message_id, ms.counter, m.message_text, m.server_date, m.image_id, m.video_id, m.file_id, m.attachment_flag, m.message_scope_id, c.f_name || ' (' || b.title || ')', c.image_id profile, '', m.status, m.credential, m.lock from MESSAGE_SUMMARY ms, MESSAGE m, DISCUSSION_FORUM b, GROUPZ c where ms.message_id = m.message_id and ms.l_pin = b.chat_id and b.group_id = c.group_id \(messageId.isEmpty ? "" : " and m.message_id = '\(messageId)'")
-                        order by 6 desc
-                        """
-            if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: query) {
-                while cursorData.next() {
-                    let chat = Chat(fpin: cursorData.string(forColumnIndex: 0) ?? "",
-                                    pin: cursorData.string(forColumnIndex: 1) ?? "",
-                                    messageId: cursorData.string(forColumnIndex: 2) ?? "",
-                                    counter: cursorData.string(forColumnIndex: 3) ?? "",
-                                    messageText: cursorData.string(forColumnIndex: 4) ?? "",
-                                    serverDate: cursorData.string(forColumnIndex: 5) ?? "",
-                                    image: cursorData.string(forColumnIndex: 6) ?? "",
-                                    video: cursorData.string(forColumnIndex: 7) ?? "",
-                                    file: cursorData.string(forColumnIndex: 8) ?? "",
-                                    attachmentFlag: cursorData.string(forColumnIndex: 9) ?? "",
-                                    messageScope: cursorData.string(forColumnIndex: 10) ?? "",
-                                    name: cursorData.string(forColumnIndex: 11) ?? "",
-                                    profile: cursorData.string(forColumnIndex: 12) ?? "",
-                                    official: cursorData.string(forColumnIndex: 13) ?? "",
-                                    status: cursorData.string(forColumnIndex: 14) ?? "",
-                                    credential: cursorData.string(forColumnIndex: 15) ?? "",
-                                    lock: cursorData.string(forColumnIndex: 16) ?? "")
-                    chats.append(chat)
+            do {
+                let query = """
+                            select m.f_pin, ms.l_pin, ms.message_id, ms.counter, m.message_text, m.server_date, m.image_id, m.video_id, m.file_id, m.attachment_flag, m.message_scope_id, b.first_name || ' ' || ifnull(b.last_name, '') name, b.image_id profile, b.official_account, m.status, m.credential, m.lock from MESSAGE_SUMMARY ms, MESSAGE m, BUDDY b where ms.message_id = m.message_id and ms.l_pin = b.f_pin \(messageId.isEmpty ? "" : " and m.message_id = '\(messageId)'")
+                            union
+                            select m.f_pin, ms.l_pin, ms.message_id, ms.counter, m.message_text, m.server_date, m.image_id, m.video_id, m.file_id, m.attachment_flag, m.message_scope_id, 'Bot' name, '' profile, '', m.status, m.credential, m.lock from MESSAGE_SUMMARY ms, MESSAGE m where ms.message_id = m.message_id and ms.l_pin = '-999' \(messageId.isEmpty ? "" : " and m.message_id = '\(messageId)'")
+                            union
+                            select m.f_pin, ms.l_pin, ms.message_id, ms.counter, m.message_text, m.server_date, m.image_id, m.video_id, m.file_id, m.attachment_flag, m.message_scope_id, b.f_name || ' (\("Lounge".localized()))', b.image_id profile, b.official, m.status, m.credential, m.lock from MESSAGE_SUMMARY ms, MESSAGE m, GROUPZ b where ms.message_id = m.message_id and ms.l_pin = b.group_id \(messageId.isEmpty ? "" : " and m.message_id = '\(messageId)'")
+                            union
+                            select m.f_pin, ms.l_pin, ms.message_id, ms.counter, m.message_text, m.server_date, m.image_id, m.video_id, m.file_id, m.attachment_flag, m.message_scope_id, c.f_name || ' (' || b.title || ')', c.image_id profile, '', m.status, m.credential, m.lock from MESSAGE_SUMMARY ms, MESSAGE m, DISCUSSION_FORUM b, GROUPZ c where ms.message_id = m.message_id and ms.l_pin = b.chat_id and b.group_id = c.group_id \(messageId.isEmpty ? "" : " and m.message_id = '\(messageId)'")
+                            order by 6 desc
+                            """
+                if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: query) {
+                    while cursorData.next() {
+                        let chat = Chat(fpin: cursorData.string(forColumnIndex: 0) ?? "",
+                                        pin: cursorData.string(forColumnIndex: 1) ?? "",
+                                        messageId: cursorData.string(forColumnIndex: 2) ?? "",
+                                        counter: cursorData.string(forColumnIndex: 3) ?? "",
+                                        messageText: cursorData.string(forColumnIndex: 4) ?? "",
+                                        serverDate: cursorData.string(forColumnIndex: 5) ?? "",
+                                        image: cursorData.string(forColumnIndex: 6) ?? "",
+                                        video: cursorData.string(forColumnIndex: 7) ?? "",
+                                        file: cursorData.string(forColumnIndex: 8) ?? "",
+                                        attachmentFlag: cursorData.string(forColumnIndex: 9) ?? "",
+                                        messageScope: cursorData.string(forColumnIndex: 10) ?? "",
+                                        name: cursorData.string(forColumnIndex: 11) ?? "",
+                                        profile: cursorData.string(forColumnIndex: 12) ?? "",
+                                        official: cursorData.string(forColumnIndex: 13) ?? "",
+                                        status: cursorData.string(forColumnIndex: 14) ?? "",
+                                        credential: cursorData.string(forColumnIndex: 15) ?? "",
+                                        lock: cursorData.string(forColumnIndex: 16) ?? "")
+                        chats.append(chat)
+                    }
+                    cursorData.close()
+    //                if chats.count == 0 {
+    //                    if let cursorCounter = Database.shared.getRecords(fmdb: fmdb, query: "SELECT SUM(counter) FROM MESSAGE_SUMMARY"), cursorCounter.next() {
+    //                        if cursorCounter.int(forColumnIndex: 0) != 0 {
+    //                            _ = Database.shared.updateAllRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", cvalues: [
+    //                                "counter" : 0
+    //                            ])
+    //                            NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reloadTabChats"), object: nil, userInfo: nil)
+    //                        }
+    //                        cursorCounter.close()
+    //                    }
+    //                }
                 }
-                cursorData.close()
-//                if chats.count == 0 {
-//                    if let cursorCounter = Database.shared.getRecords(fmdb: fmdb, query: "SELECT SUM(counter) FROM MESSAGE_SUMMARY"), cursorCounter.next() {
-//                        if cursorCounter.int(forColumnIndex: 0) != 0 {
-//                            _ = Database.shared.updateAllRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", cvalues: [
-//                                "counter" : 0
-//                            ])
-//                            NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reloadTabChats"), object: nil, userInfo: nil)
-//                        }
-//                        cursorCounter.close()
-//                    }
-//                }
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         return chats

+ 66 - 41
appbuilder-ios/NexilisLite/NexilisLite/Source/Model/Group.swift

@@ -64,18 +64,23 @@ public class Group: Model {
         }
         var group: Group?
         Database.shared.database?.inTransaction({ fmdb, rollback in
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select group_id, f_name, image_id, quote, created_by, created_date, parent, group_type, is_open, official from GROUPZ where group_id = '\(group_id)'"), cursor.next() {
-                group = Group(id: cursor.string(forColumnIndex: 0) ?? "",
-                              name: cursor.string(forColumnIndex: 1) ?? "",
-                              profile: cursor.string(forColumnIndex: 2) ?? "",
-                              quote: cursor.string(forColumnIndex: 3) ?? "",
-                              by: cursor.string(forColumnIndex: 4) ?? "",
-                              date: cursor.string(forColumnIndex: 5) ?? "",
-                              parent: cursor.string(forColumnIndex: 6) ?? "",
-                              groupType: cursor.string(forColumnIndex: 7) ?? "",
-                              isOpen: cursor.string(forColumnIndex: 8) ?? "",
-                              official: cursor.string(forColumnIndex: 9) ?? "")
-                cursor.close()
+            do {
+                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select group_id, f_name, image_id, quote, created_by, created_date, parent, group_type, is_open, official from GROUPZ where group_id = '\(group_id)'"), cursor.next() {
+                    group = Group(id: cursor.string(forColumnIndex: 0) ?? "",
+                                  name: cursor.string(forColumnIndex: 1) ?? "",
+                                  profile: cursor.string(forColumnIndex: 2) ?? "",
+                                  quote: cursor.string(forColumnIndex: 3) ?? "",
+                                  by: cursor.string(forColumnIndex: 4) ?? "",
+                                  date: cursor.string(forColumnIndex: 5) ?? "",
+                                  parent: cursor.string(forColumnIndex: 6) ?? "",
+                                  groupType: cursor.string(forColumnIndex: 7) ?? "",
+                                  isOpen: cursor.string(forColumnIndex: 8) ?? "",
+                                  official: cursor.string(forColumnIndex: 9) ?? "")
+                    cursor.close()
+                }
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         return group
@@ -109,11 +114,16 @@ public class Topic: Model {
         }
         var topic: Topic?
         Database.shared.database?.inTransaction({ fmdb, rollback in
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select chat_id, title, thumb from DISCUSSION_FORUM where chat_id = '\(topic_id)'"), cursor.next() {
-                topic = Topic(chatId: cursor.string(forColumnIndex: 0) ?? "",
-                              title: cursor.string(forColumnIndex: 1) ?? "",
-                              thumb: cursor.string(forColumnIndex: 2) ?? "")
-                cursor.close()
+            do {
+                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select chat_id, title, thumb from DISCUSSION_FORUM where chat_id = '\(topic_id)'"), cursor.next() {
+                    topic = Topic(chatId: cursor.string(forColumnIndex: 0) ?? "",
+                                  title: cursor.string(forColumnIndex: 1) ?? "",
+                                  thumb: cursor.string(forColumnIndex: 2) ?? "")
+                    cursor.close()
+                }
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         return topic
@@ -138,15 +148,20 @@ public class Member: User {
     public static func getAllMember(group_id: String) -> [Member] {
         var members: [Member] = []
         Database.shared.database?.inTransaction({ fmdb, rollback in
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin, first_name, last_name from GROUPZ_MEMBER where group_id = '\(group_id)' OR group_id = (select group_id from DISCUSSION_FORUM where chat_id = '\(group_id)')") {
-                while cursor.next() {
-                    members.append(Member(pin: cursor.string(forColumnIndex: 0) ?? "",
-                                          firstName: cursor.string(forColumnIndex: 1) ?? "",
-                                          lastName: cursor.string(forColumnIndex: 2) ?? "",
-                                          thumb: "",
-                                          position: ""))
+            do {
+                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin, first_name, last_name from GROUPZ_MEMBER where group_id = '\(group_id)' OR group_id = (select group_id from DISCUSSION_FORUM where chat_id = '\(group_id)')") {
+                    while cursor.next() {
+                        members.append(Member(pin: cursor.string(forColumnIndex: 0) ?? "",
+                                              firstName: cursor.string(forColumnIndex: 1) ?? "",
+                                              lastName: cursor.string(forColumnIndex: 2) ?? "",
+                                              thumb: "",
+                                              position: ""))
+                    }
+                    cursor.close()
                 }
-                cursor.close()
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         return members
@@ -155,15 +170,20 @@ public class Member: User {
     public static func getMember(f_pin: String) -> Member? {
         var member: Member?
         Database.shared.database?.inTransaction({ fmdb, rollback in
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin, first_name, last_name from GROUPZ_MEMBER where f_pin = '\(f_pin)'") {
-                while cursor.next() {
-                    member = Member(pin: cursor.string(forColumnIndex: 0) ?? "",
-                                    firstName: cursor.string(forColumnIndex: 1) ?? "",
-                                    lastName: cursor.string(forColumnIndex: 2) ?? "",
-                                    thumb: "",
-                                    position: "")
+            do {
+                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin, first_name, last_name from GROUPZ_MEMBER where f_pin = '\(f_pin)'") {
+                    while cursor.next() {
+                        member = Member(pin: cursor.string(forColumnIndex: 0) ?? "",
+                                        firstName: cursor.string(forColumnIndex: 1) ?? "",
+                                        lastName: cursor.string(forColumnIndex: 2) ?? "",
+                                        thumb: "",
+                                        position: "")
+                    }
+                    cursor.close()
                 }
-                cursor.close()
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         return member
@@ -172,15 +192,20 @@ public class Member: User {
     public static func getMemberInGroup(f_pin: String, group_id: String) -> Member? {
         var member: Member?
         Database.shared.database?.inTransaction({ fmdb, rollback in
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin, first_name, last_name from GROUPZ_MEMBER where f_pin = '\(f_pin)' AND (group_id = '\(group_id)' OR group_id = (select group_id from DISCUSSION_FORUM where chat_id = '\(group_id)'))") {
-                while cursor.next() {
-                    member = Member(pin: cursor.string(forColumnIndex: 0) ?? "",
-                                    firstName: cursor.string(forColumnIndex: 1) ?? "",
-                                    lastName: cursor.string(forColumnIndex: 2) ?? "",
-                                    thumb: "",
-                                    position: "")
+            do {
+                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin, first_name, last_name from GROUPZ_MEMBER where f_pin = '\(f_pin)' AND (group_id = '\(group_id)' OR group_id = (select group_id from DISCUSSION_FORUM where chat_id = '\(group_id)'))") {
+                    while cursor.next() {
+                        member = Member(pin: cursor.string(forColumnIndex: 0) ?? "",
+                                        firstName: cursor.string(forColumnIndex: 1) ?? "",
+                                        lastName: cursor.string(forColumnIndex: 2) ?? "",
+                                        thumb: "",
+                                        position: "")
+                    }
+                    cursor.close()
                 }
-                cursor.close()
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         return member

+ 17 - 12
appbuilder-ios/NexilisLite/NexilisLite/Source/Model/Group_NM.swift

@@ -62,18 +62,23 @@ public class GroupNM: Model {
         }
         var group: GroupNM?
         Database.shared.database?.inTransaction({ fmdb, rollback in
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select group_id, f_name, image_id, quote, created_by, created_date, parent, group_type, is_open, official from GROUP_NM where group_id = '\(group_id)'"), cursor.next() {
-                group = GroupNM(id: cursor.string(forColumnIndex: 0) ?? "",
-                              name: cursor.string(forColumnIndex: 1) ?? "",
-                              profile: cursor.string(forColumnIndex: 2) ?? "",
-                              quote: cursor.string(forColumnIndex: 3) ?? "",
-                              by: cursor.string(forColumnIndex: 4) ?? "",
-                              date: cursor.string(forColumnIndex: 5) ?? "",
-                              parent: cursor.string(forColumnIndex: 6) ?? "",
-                              groupType: cursor.string(forColumnIndex: 7) ?? "",
-                              isOpen: cursor.string(forColumnIndex: 8) ?? "",
-                              official: cursor.string(forColumnIndex: 9) ?? "")
-                cursor.close()
+            do {
+                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select group_id, f_name, image_id, quote, created_by, created_date, parent, group_type, is_open, official from GROUP_NM where group_id = '\(group_id)'"), cursor.next() {
+                    group = GroupNM(id: cursor.string(forColumnIndex: 0) ?? "",
+                                    name: cursor.string(forColumnIndex: 1) ?? "",
+                                    profile: cursor.string(forColumnIndex: 2) ?? "",
+                                    quote: cursor.string(forColumnIndex: 3) ?? "",
+                                    by: cursor.string(forColumnIndex: 4) ?? "",
+                                    date: cursor.string(forColumnIndex: 5) ?? "",
+                                    parent: cursor.string(forColumnIndex: 6) ?? "",
+                                    groupType: cursor.string(forColumnIndex: 7) ?? "",
+                                    isOpen: cursor.string(forColumnIndex: 8) ?? "",
+                                    official: cursor.string(forColumnIndex: 9) ?? "")
+                    cursor.close()
+                }
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         return group

+ 73 - 53
appbuilder-ios/NexilisLite/NexilisLite/Source/Model/User.swift

@@ -87,14 +87,19 @@ public class User: Model {
         var position = ""
         if fmdb == nil {
             Database.shared.database?.inTransaction({ fmdb, rollback in
-                var groupId = ""
-                if let cursorGroup = Database.shared.getRecords(fmdb: fmdb, query: "SELECT group_id FROM GROUPZ where group_type = 1 AND official = 1"), cursorGroup.next() {
-                    groupId = cursorGroup.string(forColumnIndex: 0) ?? ""
-                    cursorGroup.close()
-                }
-                if let cursorIsAdmin = Database.shared.getRecords(fmdb: fmdb, query: "SELECT position FROM GROUPZ_MEMBER where group_id = '\(groupId)' AND f_pin = '\(User.getMyPin()!)'"), cursorIsAdmin.next() {
-                    position = cursorIsAdmin.string(forColumnIndex: 0) ?? ""
-                    cursorIsAdmin.close()
+                do {
+                    var groupId = ""
+                    if let cursorGroup = Database.shared.getRecords(fmdb: fmdb, query: "SELECT group_id FROM GROUPZ where group_type = 1 AND official = 1"), cursorGroup.next() {
+                        groupId = cursorGroup.string(forColumnIndex: 0) ?? ""
+                        cursorGroup.close()
+                    }
+                    if let cursorIsAdmin = Database.shared.getRecords(fmdb: fmdb, query: "SELECT position FROM GROUPZ_MEMBER where group_id = '\(groupId)' AND f_pin = '\(User.getMyPin()!)'"), cursorIsAdmin.next() {
+                        position = cursorIsAdmin.string(forColumnIndex: 0) ?? ""
+                        cursorIsAdmin.close()
+                    }
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
                 }
             })
         } else {
@@ -148,27 +153,32 @@ public class User: Model {
             }
         } else {
             Database.shared.database?.inTransaction({ fmdb, rollback in
-                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin, first_name, last_name, image_id, user_type, privacy_flag, offline_mode, ex_block, device_id, official_account from BUDDY where f_pin = '\(pin)' OR device_id = '\(pin)'"), cursor.next() {
-                    user = User(pin: cursor.string(forColumnIndex: 0) ?? "",
-                                firstName: cursor.string(forColumnIndex: 1) ?? "",
-                                lastName: cursor.string(forColumnIndex: 2) ?? "",
-                                thumb: cursor.string(forColumnIndex: 3) ?? "",
-                                userType: cursor.string(forColumnIndex: 4) ?? "",
-                                privacy_flag: cursor.string(forColumnIndex: 5) ?? "",
-                                offline_mode: cursor.string(forColumnIndex: 6) ?? "",
-                                ex_block: cursor.string(forColumnIndex: 7) ?? "",
-                                official: cursor.string(forColumnIndex: 9) ?? "",
-                                device_id: cursor.string(forColumnIndex: 8) ?? "")
-                    cursor.close()
-                } else {
-                    user = User(pin: pin,
-                                firstName: "User".localized(),
-                                lastName: "",
-                                thumb: "",
-                                userType: "",
-                                privacy_flag: "",
-                                offline_mode: "",
-                                ex_block: "")
+                do {
+                    if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin, first_name, last_name, image_id, user_type, privacy_flag, offline_mode, ex_block, device_id, official_account from BUDDY where f_pin = '\(pin)' OR device_id = '\(pin)'"), cursor.next() {
+                        user = User(pin: cursor.string(forColumnIndex: 0) ?? "",
+                                    firstName: cursor.string(forColumnIndex: 1) ?? "",
+                                    lastName: cursor.string(forColumnIndex: 2) ?? "",
+                                    thumb: cursor.string(forColumnIndex: 3) ?? "",
+                                    userType: cursor.string(forColumnIndex: 4) ?? "",
+                                    privacy_flag: cursor.string(forColumnIndex: 5) ?? "",
+                                    offline_mode: cursor.string(forColumnIndex: 6) ?? "",
+                                    ex_block: cursor.string(forColumnIndex: 7) ?? "",
+                                    official: cursor.string(forColumnIndex: 9) ?? "",
+                                    device_id: cursor.string(forColumnIndex: 8) ?? "")
+                        cursor.close()
+                    } else {
+                        user = User(pin: pin,
+                                    firstName: "User".localized(),
+                                    lastName: "",
+                                    thumb: "",
+                                    userType: "",
+                                    privacy_flag: "",
+                                    offline_mode: "",
+                                    ex_block: "")
+                    }
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
                 }
             })
         }
@@ -196,18 +206,23 @@ public class User: Model {
             }
         } else {
             Database.shared.database?.inTransaction({ fmdb, rollback in
-                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin, first_name, last_name, image_id, user_type, privacy_flag, offline_mode, ex_block, device_id, official_account from BUDDY where f_pin = '\(pin)' OR device_id = '\(pin)'"), cursor.next() {
-                    user = User(pin: cursor.string(forColumnIndex: 0) ?? "",
-                                firstName: cursor.string(forColumnIndex: 1) ?? "",
-                                lastName: cursor.string(forColumnIndex: 2) ?? "",
-                                thumb: cursor.string(forColumnIndex: 3) ?? "",
-                                userType: cursor.string(forColumnIndex: 4) ?? "",
-                                privacy_flag: cursor.string(forColumnIndex: 5) ?? "",
-                                offline_mode: cursor.string(forColumnIndex: 6) ?? "",
-                                ex_block: cursor.string(forColumnIndex: 7) ?? "",
-                                official: cursor.string(forColumnIndex: 9) ?? "",
-                                device_id: cursor.string(forColumnIndex: 8) ?? "")
-                    cursor.close()
+                do {
+                    if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin, first_name, last_name, image_id, user_type, privacy_flag, offline_mode, ex_block, device_id, official_account from BUDDY where f_pin = '\(pin)' OR device_id = '\(pin)'"), cursor.next() {
+                        user = User(pin: cursor.string(forColumnIndex: 0) ?? "",
+                                    firstName: cursor.string(forColumnIndex: 1) ?? "",
+                                    lastName: cursor.string(forColumnIndex: 2) ?? "",
+                                    thumb: cursor.string(forColumnIndex: 3) ?? "",
+                                    userType: cursor.string(forColumnIndex: 4) ?? "",
+                                    privacy_flag: cursor.string(forColumnIndex: 5) ?? "",
+                                    offline_mode: cursor.string(forColumnIndex: 6) ?? "",
+                                    ex_block: cursor.string(forColumnIndex: 7) ?? "",
+                                    official: cursor.string(forColumnIndex: 9) ?? "",
+                                    device_id: cursor.string(forColumnIndex: 8) ?? "")
+                        cursor.close()
+                    }
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
                 }
             })
         }
@@ -248,18 +263,23 @@ public class User: Model {
             }
         } else {
             Database.shared.database?.inTransaction({ fmdb, rollback in
-                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin, first_name, last_name, image_id, user_type, privacy_flag, offline_mode, ex_block, device_id, official_account from BUDDY where LOWER(first_name) = '\(firstName.lowercased())' AND LOWER(last_name) = '\(lastName.lowercased())'"), cursor.next() {
-                    user = User(pin: cursor.string(forColumnIndex: 0) ?? "",
-                                firstName: cursor.string(forColumnIndex: 1) ?? "",
-                                lastName: cursor.string(forColumnIndex: 2) ?? "",
-                                thumb: cursor.string(forColumnIndex: 3) ?? "",
-                                userType: cursor.string(forColumnIndex: 4) ?? "",
-                                privacy_flag: cursor.string(forColumnIndex: 5) ?? "",
-                                offline_mode: cursor.string(forColumnIndex: 6) ?? "",
-                                ex_block: cursor.string(forColumnIndex: 7) ?? "",
-                                official: cursor.string(forColumnIndex: 9) ?? "",
-                                device_id: cursor.string(forColumnIndex: 8) ?? "")
-                    cursor.close()
+                do {
+                    if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin, first_name, last_name, image_id, user_type, privacy_flag, offline_mode, ex_block, device_id, official_account from BUDDY where LOWER(first_name) = '\(firstName.lowercased())' AND LOWER(last_name) = '\(lastName.lowercased())'"), cursor.next() {
+                        user = User(pin: cursor.string(forColumnIndex: 0) ?? "",
+                                    firstName: cursor.string(forColumnIndex: 1) ?? "",
+                                    lastName: cursor.string(forColumnIndex: 2) ?? "",
+                                    thumb: cursor.string(forColumnIndex: 3) ?? "",
+                                    userType: cursor.string(forColumnIndex: 4) ?? "",
+                                    privacy_flag: cursor.string(forColumnIndex: 5) ?? "",
+                                    offline_mode: cursor.string(forColumnIndex: 6) ?? "",
+                                    ex_block: cursor.string(forColumnIndex: 7) ?? "",
+                                    official: cursor.string(forColumnIndex: 9) ?? "",
+                                    device_id: cursor.string(forColumnIndex: 8) ?? "")
+                        cursor.close()
+                    }
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
                 }
             })
         }

+ 13 - 8
appbuilder-ios/NexilisLite/NexilisLite/Source/Model/WorkingArea.swift

@@ -31,15 +31,20 @@ public class WorkingArea: Model {
     public static func getData(name: String) -> [WorkingArea] {
         var data: [WorkingArea] = []
         Database.shared.database?.inTransaction({ fmdb, rollback in
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select id, area_id, name, parent, level from WORKING_AREA where name LIKE '%\(name.lowercased())%'") {
-                while cursor.next() {
-                    data.append(WorkingArea(id: cursor.string(forColumnIndex: 0) ?? "",
-                                           area_id: cursor.string(forColumnIndex: 1) ?? "",
-                                           name: cursor.string(forColumnIndex: 2) ?? "",
-                                           parent: cursor.string(forColumnIndex: 3) ?? "",
-                                           level: cursor.string(forColumnIndex: 4) ?? ""))
+            do {
+                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select id, area_id, name, parent, level from WORKING_AREA where name LIKE '%\(name.lowercased())%'") {
+                    while cursor.next() {
+                        data.append(WorkingArea(id: cursor.string(forColumnIndex: 0) ?? "",
+                                                area_id: cursor.string(forColumnIndex: 1) ?? "",
+                                                name: cursor.string(forColumnIndex: 2) ?? "",
+                                                parent: cursor.string(forColumnIndex: 3) ?? "",
+                                                level: cursor.string(forColumnIndex: 4) ?? ""))
+                    }
+                    cursor.close()
                 }
-                cursor.close()
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         return data

+ 304 - 404
appbuilder-ios/NexilisLite/NexilisLite/Source/Nexilis.swift

@@ -145,8 +145,6 @@ public class Nexilis: NSObject {
         } catch {
         }
         
-        Database.shared.openDatabase()
-        
         IncomingThread.default.run()
         
         imageCache.countLimit = 100
@@ -155,40 +153,14 @@ public class Nexilis: NSObject {
         DispatchQueue.global().async {
             do {
                 let address = Nexilis.getAddressNew(apiKey:apiKey)
-                //print("ADDRESS \(address)")
                 if address.isEmpty {
                     return
                 }
-    //            SecureUserDefaults.shared.set(address, forKey: "address")
-    //            SecureUserDefaults.shared.set(address[0], forKey: "server")
-    //
                 Nexilis.dispatch = DispatchGroup()
                 Nexilis.dispatch?.enter()
-    //                server = a[0]
-    //                SecureUserDefaults.shared.set(server, forKey: "server")
-    //            }
-    //            var ip = ""
-    //            var port = 0
-    //            if let s = server {
-    //                let data = s.split(separator: ":")
-    //                ip = String(data[0])
-    //                if let p = Int(data[1]) {
-    //                    port = p
-    //                }
-    //            }
                 Nexilis.ADDRESS = address.components(separatedBy: ":")[0]
                 Nexilis.PORT = Int(address.components(separatedBy: ":")[1]) ?? 0
-//                print("sGetVersion \(API.sGetVersion())")
-//                print("IP PORT \(Nexilis.ADDRESS) <> \(Nexilis.PORT)")
                 var id = Utils.getConnectionID()
-//                    try API.initConnection(bSwitchIP: false, sAPIK: apiKey, aAppMain: nil, cbiI: Callback(), sTCPAddr: Nexilis.ADDRESS, nTCPPort: Nexilis.PORT, sUserID: device_id, sStartWH: "09:00")
-//                } else if let me = User.getMyPin() {
-//                    try API.initConnection(bSwitchIP: false, sAPIK: apiKey, aAppMain: nil, cbiI: Callback(), sTCPAddr: Nexilis.ADDRESS, nTCPPort: Nexilis.PORT, sUserID: me, sStartWH: "09:00")
-//                } else {
-//                    let uuid = UIDevice.current.identifierForVendor?.uuidString ?? "UNK-DEVICE"
-//                    try API.initConnection(bSwitchIP: false, sAPIK: apiKey, aAppMain: nil, cbiI: Callback(), sTCPAddr: Nexilis.ADDRESS, nTCPPort: Nexilis.PORT, sUserID: uuid, sStartWH: "09:00")
-//                    id = uuid
-//                }
                 if id.isEmpty {
                     let sDID = UIDevice.current.identifierForVendor?.uuidString ?? "UNK-DEVICE"
                     id = String(sDID[sDID.index(sDID.endIndex, offsetBy: -5)...])
@@ -200,14 +172,12 @@ public class Nexilis: NSObject {
                 Nexilis.dispatch?.wait()
                 Nexilis.dispatch = nil
                 
-    //            Nexilis.initiateAudio()
                 if(User.getMyPin() == nil){
                     if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getSignUpApi(api: apiKey, p_pin: id), timeout: 30 * 1000){
                         id = response.getBody(key: CoreMessage_TMessageKey.F_PIN, default_value: "")
                         let enable_signup = (response.getBody(key: CoreMessage_TMessageKey.IS_ENABLED_ANONYMOUS, default_value: "0")) == "1"
                         Utils.setForceAnonymous(value: enable_signup)
                         if(!id.isEmpty) {
-//                            Nexilis.changeUser(f_pin: id)
                             SecureUserDefaults.shared.set(id, forKey: "me")
                         }
                     }
@@ -218,28 +188,40 @@ public class Nexilis: NSObject {
                     SecureUserDefaults.shared.set(apiKey, forKey: "apiKey")
                 }
                 
+                getPullPrefs()
                 getFeatureAccess()
                 
                 if let me = User.getMyPin() {
-                    if Utils.getForceAnonymous() || (!Utils.getForceAnonymous() && Utils.getSetProfile()) {
+                    if !Utils.getForceAnonymous() && Utils.getSetProfile() {
+                        Database.shared.openDatabase()
                         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                            if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT * FROM BUDDY where f_pin = '\(me)' ") {
-                                if !cursorData.next() {
-                                    _ = Nexilis.write(message: CoreMessage_TMessageBank.getPostRegistration(p_pin: me))
+                            do {
+                                if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT * FROM BUDDY where f_pin = '\(me)' ") {
+                                    if !cursorData.next() {
+                                        _ = Nexilis.write(message: CoreMessage_TMessageBank.getPostRegistration(p_pin: me))
+                                    }
+                                    cursorData.close()
                                 }
-                                cursorData.close()
+                            } catch {
+                                rollback.pointee = true
+                                print("Access database error: \(error.localizedDescription)")
                             }
                         })
                         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                            if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT image_id FROM GROUPZ where group_type = 1 AND official = 1"), cursorData.next() {
-                                do {
-                                    let documentDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
-                                    let file = documentDir.appendingPathComponent(cursorData.string(forColumnIndex: 0)!)
-                                    if !FileManager().fileExists(atPath: file.path) {
-                                        Download().startHTTP(forKey: cursorData.string(forColumnIndex: 0)!) { (name, progress) in}
-                                    }
-                                } catch {}
-                                cursorData.close()
+                            do {
+                                if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT image_id FROM GROUPZ where group_type = 1 AND official = 1"), cursorData.next() {
+                                    do {
+                                        let documentDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
+                                        let file = documentDir.appendingPathComponent(cursorData.string(forColumnIndex: 0)!)
+                                        if !FileManager().fileExists(atPath: file.path) {
+                                            Download().startHTTP(forKey: cursorData.string(forColumnIndex: 0)!) { (name, progress) in}
+                                        }
+                                    } catch {}
+                                    cursorData.close()
+                                }
+                            } catch {
+                                rollback.pointee = true
+                                print("Access database error: \(error.localizedDescription)")
                             }
                         })
                     } else if isShowForceSignIn && !Utils.getForceAnonymous() && !Utils.getSetProfile() {
@@ -249,7 +231,6 @@ public class Nexilis: NSObject {
                     getPullWorkingArea()
                     getPullGroupNoMember()
                     delegate.onSuccess(userId: me)
-                    getPullDefaultCC()
                     DispatchQueue.main.async {
                         var viewController = UIApplication.shared.windows.first?.rootViewController
                         var notNull = false
@@ -350,33 +331,14 @@ public class Nexilis: NSObject {
         }
     }
     
-    private static func getPullDefaultCC() {
+    private static func getPullPrefs() {
         DispatchQueue.global().async {
-            if let response = Nexilis.writeSync(message: getPrefs(key: "default_cc"), timeout: 30 * 1000) {
-                if response.mBodies[CoreMessage_TMessageKey.ERRCOD] == "00" {
-                    let data = response.getBody(key: CoreMessage_TMessageKey.DATA)
-                    if let json = try! JSONSerialization.jsonObject(with: data.data(using: String.Encoding.utf8)!, options: []) as? [[String: Any?]] {
-                        if json.count > 0 , let default_cc = json[0]["default_cc"] as? String {
-                            Utils.setDefaultCC(value: default_cc)
-                        }
-                    }
-                }
-            }
+            _ = Nexilis.write(message: CoreMessage_TMessageBank.getPrefs())
         }
     }
     
-    private static func getPrefs(key: String) -> TMessage {
-        let tMessage = NexilisLite.TMessage()
-        let me = User.getMyPin()
-        tMessage.mCode = "PPR"
-        tMessage.mStatus = CoreMessage_TMessageUtil.getTID()
-        tMessage.mBodies[CoreMessage_TMessageKey.F_PIN] = me
-        tMessage.mBodies[CoreMessage_TMessageKey.KEY] = key
-        return tMessage
-    }
-    
     private static func getPullGroupNoMember() {
-        DispatchQueue.global().asyncAfter(deadline: .now(), execute: {
+        DispatchQueue.global().async {
             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.pullGroupNoMember(), timeout: 30 * 1000), response.isOk() {
                 let data = response.getBody(key: CoreMessage_TMessageKey.DATA)
                 //print("KUACAU \(data)")
@@ -410,151 +372,49 @@ public class Nexilis: NSObject {
                                 }
                             } catch {
                                 rollback.pointee = true
-                                //print(error)
+                                print("Access database error: \(error.localizedDescription)")
                             }
                         })
                     }
                 }
             }
-        })
+        }
     }
     
     private static func getServiceBank() {
-        DispatchQueue.global().asyncAfter(deadline: .now(), execute: {
+        DispatchQueue.global().async {
             _ = Nexilis.write(message: CoreMessage_TMessageBank.getServiceBank())
-        })
+        }
     }
     
     private static func getFeatureAccess() {
-        DispatchQueue.global().asyncAfter(deadline: .now(), execute: {
+        DispatchQueue.global().async {
             Utils.postDataWithCookiesAndUserAgent(from: URL(string: Utils.getDomainOpr() + "get_feature_access_new")!) { data, response, error in
                 if let data = data, let responseString = String(data: data, encoding: .utf8) {
                     if let jsonArray = try? JSONSerialization.jsonObject(with: responseString.data(using: String.Encoding.utf8)!, options: JSONSerialization.ReadingOptions()) as? [AnyObject] {
                         do {
                             var jsonFA: [String: Any] = [:]
                             for jsonData in jsonArray {
-                                if jsonData["admin_features"]! != nil {
-                                    jsonFA["admin_features"] = jsonData["admin_features"]!
-                                }
-                                if jsonData["audio_call"]! != nil {
-                                    jsonFA["audio_call"] = jsonData["audio_call"]!
-                                }
-                                if jsonData["audio_call_add"]! != nil {
-                                    jsonFA["audio_call_add"] = jsonData["audio_call_add"]!
-                                }
-                                if jsonData["backup_restore"]! != nil {
-                                    jsonFA["backup_restore"] = jsonData["backup_restore"]!
-                                }
-                                if jsonData["backup_restore"]! != nil {
-                                    jsonFA["backup_restore"] = jsonData["backup_restore"]!
-                                }
-                                if jsonData["battery_optimization"]! != nil {
-                                    jsonFA["battery_optimization"] = jsonData["battery_optimization"]!
-                                }
-                                if jsonData["call_center"]! != nil {
-                                    jsonFA["call_center"] = jsonData["call_center"]!
-                                }
-                                if jsonData["email"]! != nil {
-                                    jsonFA["email"] = jsonData["email"]!
-                                }
-                                if jsonData["live_streaming"]! != nil {
-                                    jsonFA["live_streaming"] = jsonData["live_streaming"]!
-                                }
-                                if jsonData["live_streaming_view"]! != nil {
-                                    jsonFA["live_streaming_view"] = jsonData["live_streaming_view"]!
-                                }
-                                if jsonData["logout"]! != nil {
-                                    jsonFA["logout"] = jsonData["logout"]!
-                                }
-                                if jsonData["online_seminar"]! != nil {
-                                    jsonFA["online_seminar"] = jsonData["online_seminar"]!
-                                }
-                                if jsonData["sms"]! != nil {
-                                    jsonFA["sms"] = jsonData["sms"]!
-                                }
-                                if jsonData["video_call"]! != nil {
-                                    jsonFA["video_call"] = jsonData["video_call"]!
-                                }
-                                if jsonData["video_call_add"]! != nil {
-                                    jsonFA["video_call_add"] = jsonData["video_call_add"]!
-                                }
-                                if jsonData["web"]! != nil {
-                                    jsonFA["web"] = jsonData["web"]!
-                                }
-                                if jsonData["change_profile_name"]! != nil {
-                                    jsonFA["change_profile_name"] = jsonData["change_profile_name"]!
-                                }
-                                if jsonData["change_profile_photo"]! != nil {
-                                    jsonFA["change_profile_photo"] = jsonData["change_profile_photo"]!
-                                }
-                                if jsonData["instant_messaging"]! != nil {
-                                    jsonFA["instant_messaging"] = jsonData["instant_messaging"]!
-                                }
-                                if jsonData["battery_optimization_force"]! != nil {
-                                    jsonFA["battery_optimization_force"] = jsonData["battery_optimization_force"]!
-                                }
+                                var tmp = jsonData as! [String: Any]
+                                tmp.removeValue(forKey: "action")
+                                tmp.removeValue(forKey: "alert_title")
+                                tmp.removeValue(forKey: "alert_message")
+                                jsonFA[Array(tmp.keys)[0]] = Array(tmp.values)[0]
                                 if jsonData["upload_max_retry"]! != nil {
                                     let umr = jsonData["upload_max_retry"] as? Int
                                     Utils.setMaxRetryUpload(value: "\(umr ?? 0)")
-                                    jsonFA["upload_max_retry"] = jsonData["upload_max_retry"]!
+                                    jsonFA[Array(tmp.keys)[0]] = Array(tmp.values)[0]
                                 }
                                 if jsonData["upload_max_time"]! != nil {
                                     let umt = jsonData["upload_max_time"] as? Int64
                                     Utils.setMaxRetryTimeUpload(value: "\(umt ?? 0)")
-                                    jsonFA["upload_max_time"] = jsonData["upload_max_time"]!
-                                }
-                                if jsonData["show_security_shield_dialog"]! != nil {
-                                    jsonFA["show_security_shield_dialog"] = jsonData["show_security_shield_dialog"]!
-                                }
-                                if jsonData["logging_state"]! != nil {
-                                    jsonFA["logging_state"] = jsonData["logging_state"]!
-                                }
-                                if jsonData["smartbot"]! != nil {
-                                    jsonFA["smartbot"] = jsonData["smartbot"]!
-                                }
-                                if jsonData["message_counter"]! != nil {
-                                    jsonFA["message_counter"] = jsonData["message_counter"]!
-                                }
-                                if jsonData["secure_folder"]! != nil {
-                                    jsonFA["secure_folder"] = jsonData["secure_folder"]!
-                                }
-                                if jsonData["ls_broadcast_type"]! != nil {
-                                    jsonFA["ls_broadcast_type"] = jsonData["ls_broadcast_type"]!
-                                }
-                                if jsonData["force_exit"]! != nil {
-                                    jsonFA["force_exit"] = jsonData["force_exit"]!
-                                }
-                                if jsonData["periodic_worker"]! != nil {
-                                    jsonFA["periodic_worker"] = jsonData["periodic_worker"]!
-                                }
-                                if jsonData["cc_instant_messaging"]! != nil {
-                                    jsonFA["cc_instant_messaging"] = jsonData["cc_instant_messaging"]!
-                                }
-                                if jsonData["cc_audio_call"]! != nil {
-                                    jsonFA["cc_audio_call"] = jsonData["cc_audio_call"]!
-                                }
-                                if jsonData["cc_video_call"]! != nil {
-                                    jsonFA["cc_video_call"] = jsonData["cc_video_call"]!
-                                }
-                                if jsonData["cc_smartbot"]! != nil {
-                                    jsonFA["cc_smartbot"] = jsonData["cc_smartbot"]!
-                                }
-                                if jsonData["cc_email"]! != nil {
-                                    jsonFA["cc_email"] = jsonData["cc_email"]!
-                                }
-                                if jsonData["cc_sms"]! != nil {
-                                    jsonFA["cc_sms"] = jsonData["cc_sms"]!
-                                }
-                                if jsonData["cc_gsm_call"]! != nil {
-                                    jsonFA["cc_gsm_call"] = jsonData["cc_gsm_call"]!
-                                }
-                                if jsonData["cc_whatsapp"]! != nil {
-                                    jsonFA["cc_whatsapp"] = jsonData["cc_whatsapp"]!
+                                    jsonFA[Array(tmp.keys)[0]] = Array(tmp.values)[0]
                                 }
                                 if jsonData["default_fb"]! != nil {
                                     if !Utils.getAfterConfigFB() {
                                         Utils.setConfigModeFB(value: jsonData["default_fb"] as! String)
                                     }
+                                    jsonFA[Array(tmp.keys)[0]] = Array(tmp.values)[0]
                                 }
                             }
                             if let convertJsonFA = try? JSONSerialization.data(withJSONObject: jsonFA, options: .prettyPrinted) {
@@ -567,7 +427,7 @@ public class Nexilis: NSObject {
                     }
                 }
             }
-        })
+        }
     }
     
     public static func checkingAccess(key: String) -> Bool {
@@ -614,7 +474,7 @@ public class Nexilis: NSObject {
                                 }
                             } catch {
                                 rollback.pointee = true
-                                //print(error)
+                                print("Access database error: \(error.localizedDescription)")
                             }
                         })
                     }
@@ -665,7 +525,7 @@ public class Nexilis: NSObject {
                     ], replace: true)
                 } catch {
                     rollback.pointee = true
-                    //print(error)
+                    print("Access database error: \(error.localizedDescription)")
                 }
             })
             if officer == idMe {
@@ -1365,140 +1225,145 @@ public class Nexilis: NSObject {
             return
         }
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select message_id from MESSAGE where message_id = '\(message_id)'") {
-                if cursor.next() {
-                    //print("message exist")
-                    return
-                }
-                cursor.close()
-            }
-            let l_pin = message.getBody(key : CoreMessage_TMessageKey.L_PIN, default_value : "")
-            let scope = message.getBody(key : CoreMessage_TMessageKey.MESSAGE_SCOPE_ID, default_value : "3")
-            let status = message.getBody(key : CoreMessage_TMessageKey.STATUS, default_value : "")
-            let chat_id = message.getBody(key : CoreMessage_TMessageKey.CHAT_ID, default_value : "")
-            let broadcast_flag = message.getBody(key: CoreMessage_TMessageKey.BROADCAST_FLAG, default_value: "0")
-            let is_call_center = message.getBody(key: CoreMessage_TMessageKey.IS_CALL_CENTER, default_value: "0")
-            let call_center_id = message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID, default_value: "")
-            //print("prepare save db")
             do {
-                _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                    "message_id" : message_id,
-                    "f_pin" : f_pin,
-                    "f_display_name" : message.getBody(key : CoreMessage_TMessageKey.F_DISPLAY_NAME, default_value : ""),
-                    "l_pin" : l_pin,
-                    "l_user_id" : message.getBody(key : CoreMessage_TMessageKey.L_USER_ID, default_value : ""),
-                    "message_scope_id" : scope,
-                    "server_date" : message.getBody(key: CoreMessage_TMessageKey.SERVER_DATE, default_value : String(Date().currentTimeMillis())),
-                    "status" : status,
-                    "message_text" : message.getBody(key : CoreMessage_TMessageKey.MESSAGE_TEXT, default_value : "").toNormalString(),
-                    "audio_id" : message.getBody(key : CoreMessage_TMessageKey.AUDIO_ID, default_value : ""),
-                    "video_id" : message.getBody(key : CoreMessage_TMessageKey.VIDEO_ID, default_value : ""),
-                    "image_id" : message.getBody(key : CoreMessage_TMessageKey.IMAGE_ID, default_value : ""),
-                    "file_id" : message.getBody(key : CoreMessage_TMessageKey.FILE_ID, default_value : ""),
-                    "thumb_id" : message.getBody(key : CoreMessage_TMessageKey.THUMB_ID, default_value : ""),
-                    "opposite_pin" : message.getBody(key : CoreMessage_TMessageKey.OPPOSITE_PIN, default_value : ""),
-                    "format" : message.getBody(key : CoreMessage_TMessageKey.FORMAT, default_value : ""),
-                    "blog_id" : message.getBody(key : CoreMessage_TMessageKey.BLOG_ID, default_value : ""),
-                    "read_receipts" : message.getBody(key: CoreMessage_TMessageKey.READ_RECEIPTS, default_value:  "0"),
-                    "chat_id" : chat_id,
-                    "account_type" : message.getBody(key : CoreMessage_TMessageKey.BUSINESS_CATEGORY, default_value : "1"),
-                    "credential" : message.getBody(key : CoreMessage_TMessageKey.CREDENTIAL, default_value : ""),
-                    "reff_id" : message.getBody(key : CoreMessage_TMessageKey.REF_ID, default_value : ""),
-                    "message_large_text" : message.getBody(key : CoreMessage_TMessageKey.BODY, default_value : "").toNormalString(),
-                    "attachment_flag" : message.getBody(key: CoreMessage_TMessageKey.ATTACHMENT_FLAG, default_value:  "0"),
-                    "local_timestamp" : message.getBody(key: CoreMessage_TMessageKey.LOCAL_TIMESTAMP, default_value : String(Date().currentTimeMillis())),
-                    "broadcast_flag" : broadcast_flag,
-                    "is_call_center" : is_call_center,
-                    "call_center_id" : call_center_id
-                ], replace: true)
-            } catch {
-                rollback.pointee = true
-                //print(error)
-            }
-            
-            if withStatus {
+                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select message_id from MESSAGE where message_id = '\(message_id)'") {
+                    if cursor.next() {
+                        //print("message exist")
+                        return
+                    }
+                    cursor.close()
+                }
+                let l_pin = message.getBody(key : CoreMessage_TMessageKey.L_PIN, default_value : "")
+                let scope = message.getBody(key : CoreMessage_TMessageKey.MESSAGE_SCOPE_ID, default_value : "3")
+                let status = message.getBody(key : CoreMessage_TMessageKey.STATUS, default_value : "")
+                let chat_id = message.getBody(key : CoreMessage_TMessageKey.CHAT_ID, default_value : "")
+                let broadcast_flag = message.getBody(key: CoreMessage_TMessageKey.BROADCAST_FLAG, default_value: "0")
+                let is_call_center = message.getBody(key: CoreMessage_TMessageKey.IS_CALL_CENTER, default_value: "0")
+                let call_center_id = message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID, default_value: "")
+                //print("prepare save db")
                 do {
-                    if scope == "4" {
-                        for pin in getGroupMembers(fmdb: fmdb, l_pin: l_pin) {
-                            if f_pin == pin { continue }
+                    _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                        "message_id" : message_id,
+                        "f_pin" : f_pin,
+                        "f_display_name" : message.getBody(key : CoreMessage_TMessageKey.F_DISPLAY_NAME, default_value : ""),
+                        "l_pin" : l_pin,
+                        "l_user_id" : message.getBody(key : CoreMessage_TMessageKey.L_USER_ID, default_value : ""),
+                        "message_scope_id" : scope,
+                        "server_date" : message.getBody(key: CoreMessage_TMessageKey.SERVER_DATE, default_value : String(Date().currentTimeMillis())),
+                        "status" : status,
+                        "message_text" : message.getBody(key : CoreMessage_TMessageKey.MESSAGE_TEXT, default_value : "").toNormalString(),
+                        "audio_id" : message.getBody(key : CoreMessage_TMessageKey.AUDIO_ID, default_value : ""),
+                        "video_id" : message.getBody(key : CoreMessage_TMessageKey.VIDEO_ID, default_value : ""),
+                        "image_id" : message.getBody(key : CoreMessage_TMessageKey.IMAGE_ID, default_value : ""),
+                        "file_id" : message.getBody(key : CoreMessage_TMessageKey.FILE_ID, default_value : ""),
+                        "thumb_id" : message.getBody(key : CoreMessage_TMessageKey.THUMB_ID, default_value : ""),
+                        "opposite_pin" : message.getBody(key : CoreMessage_TMessageKey.OPPOSITE_PIN, default_value : ""),
+                        "format" : message.getBody(key : CoreMessage_TMessageKey.FORMAT, default_value : ""),
+                        "blog_id" : message.getBody(key : CoreMessage_TMessageKey.BLOG_ID, default_value : ""),
+                        "read_receipts" : message.getBody(key: CoreMessage_TMessageKey.READ_RECEIPTS, default_value:  "0"),
+                        "chat_id" : chat_id,
+                        "account_type" : message.getBody(key : CoreMessage_TMessageKey.BUSINESS_CATEGORY, default_value : "1"),
+                        "credential" : message.getBody(key : CoreMessage_TMessageKey.CREDENTIAL, default_value : ""),
+                        "reff_id" : message.getBody(key : CoreMessage_TMessageKey.REF_ID, default_value : ""),
+                        "message_large_text" : message.getBody(key : CoreMessage_TMessageKey.BODY, default_value : "").toNormalString(),
+                        "attachment_flag" : message.getBody(key: CoreMessage_TMessageKey.ATTACHMENT_FLAG, default_value:  "0"),
+                        "local_timestamp" : message.getBody(key: CoreMessage_TMessageKey.LOCAL_TIMESTAMP, default_value : String(Date().currentTimeMillis())),
+                        "broadcast_flag" : broadcast_flag,
+                        "is_call_center" : is_call_center,
+                        "call_center_id" : call_center_id
+                    ], replace: true)
+                } catch {
+                    rollback.pointee = true
+                    //print(error)
+                }
+                
+                if withStatus {
+                    do {
+                        if scope == "4" {
+                            for pin in getGroupMembers(fmdb: fmdb, l_pin: l_pin) {
+                                if f_pin == pin { continue }
+                                _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
+                                    "message_id" : message_id,
+                                    "status" : status,
+                                    "f_pin" : pin,
+                                    "last_update" : Date().currentTimeMillis()
+                                ], replace: true)
+                            }
+                        } else {
                             _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
                                 "message_id" : message_id,
                                 "status" : status,
-                                "f_pin" : pin,
+                                "f_pin" : l_pin,
                                 "last_update" : Date().currentTimeMillis()
                             ], replace: true)
                         }
-                    } else {
-                        _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
-                            "message_id" : message_id,
-                            "status" : status,
-                            "f_pin" : l_pin,
-                            "last_update" : Date().currentTimeMillis()
-                        ], replace: true)
+                    } catch {
+                        rollback.pointee = true
+                        //print(error)
                     }
-                } catch {
-                    rollback.pointee = true
-                    //print(error)
                 }
-            }
-            var pin = l_pin
-            if l_pin == me {
-                pin = f_pin
-            }
-            if !chat_id.isEmpty {
-                pin = chat_id
-            }
-            var counter : Int? = nil
-            if !withStatus {
-                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select counter from MESSAGE_SUMMARY where l_pin = '\(pin)'"), cursor.next() {
-                    counter = Int(cursor.int(forColumnIndex: 0))
-                    counter! += 1
-                    cursor.close()
-                    //print("select db message summary")
+                var pin = l_pin
+                if l_pin == me {
+                    pin = f_pin
                 }
-                if counter == nil {
-                    counter = 1
-                    //print("set counter message summary")
+                if !chat_id.isEmpty {
+                    pin = chat_id
                 }
-            }
-            if counter == nil {
-                counter = 0
-            }
-            if is_call_center == "0" {
-                do {
-                    var queryGetLastMessageId = "SELECT message_id FROM MESSAGE where f_pin = '\(pin)' OR l_pin = '\(pin)' order by server_date desc LIMIT 1"
-                    if scope == "4" {
-                        queryGetLastMessageId = "SELECT message_id FROM MESSAGE where l_pin = '\(pin)' AND chat_id = '' order by server_date desc LIMIT 1"
-                        if !chat_id.isEmpty {
-                            queryGetLastMessageId = "SELECT message_id FROM MESSAGE where chat_id = '\(pin)' order by server_date desc LIMIT 1"
-                        }
+                var counter : Int? = nil
+                if !withStatus {
+                    if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select counter from MESSAGE_SUMMARY where l_pin = '\(pin)'"), cursor.next() {
+                        counter = Int(cursor.int(forColumnIndex: 0))
+                        counter! += 1
+                        cursor.close()
+                        //print("select db message summary")
                     }
-                    var messageId = ""
-                    if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: queryGetLastMessageId), cursorData.next() {
-                        messageId = cursorData.string(forColumnIndex: 0) ?? ""
-                        cursorData.close()
+                    if counter == nil {
+                        counter = 1
+                        //print("set counter message summary")
                     }
-                    if !messageId.isEmpty {
-                        _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", cvalues: [
-                            "l_pin" : pin,
-                            "message_id" : messageId,
-                            "counter" : counter!
-                        ], replace: true)
+                }
+                if counter == nil {
+                    counter = 0
+                }
+                if is_call_center == "0" {
+                    do {
+                        var queryGetLastMessageId = "SELECT message_id FROM MESSAGE where f_pin = '\(pin)' OR l_pin = '\(pin)' order by server_date desc LIMIT 1"
+                        if scope == "4" {
+                            queryGetLastMessageId = "SELECT message_id FROM MESSAGE where l_pin = '\(pin)' AND chat_id = '' order by server_date desc LIMIT 1"
+                            if !chat_id.isEmpty {
+                                queryGetLastMessageId = "SELECT message_id FROM MESSAGE where chat_id = '\(pin)' order by server_date desc LIMIT 1"
+                            }
+                        }
+                        var messageId = ""
+                        if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: queryGetLastMessageId), cursorData.next() {
+                            messageId = cursorData.string(forColumnIndex: 0) ?? ""
+                            cursorData.close()
+                        }
+                        if !messageId.isEmpty {
+                            _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", cvalues: [
+                                "l_pin" : pin,
+                                "message_id" : messageId,
+                                "counter" : counter!
+                            ], replace: true)
+                        }
+                    } catch {
+                        rollback.pointee = true
+                        //print(error)
                     }
-                } catch {
-                    rollback.pointee = true
-                    //print(error)
                 }
-            }
-            if !withStatus {
-                DispatchQueue.main.async {
-                    if let delegate = Nexilis.shared.messageDelegate, Utils.getSetProfile() {
-                        message.mBodies[CoreMessage_TMessageKey.MESSAGE_TEXT] = message.getBody(key : CoreMessage_TMessageKey.MESSAGE_TEXT, default_value : "").toNormalString()
-                        delegate.onReceive(message: message)
+                if !withStatus {
+                    DispatchQueue.main.async {
+                        if let delegate = Nexilis.shared.messageDelegate, Utils.getSetProfile() {
+                            message.mBodies[CoreMessage_TMessageKey.MESSAGE_TEXT] = message.getBody(key : CoreMessage_TMessageKey.MESSAGE_TEXT, default_value : "").toNormalString()
+                            delegate.onReceive(message: message)
+                        }
                     }
                 }
+                //print("insert db message summary \(message_id)")
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
-            //print("insert db message summary \(message_id)")
         })
         
     }
@@ -1512,9 +1377,14 @@ public class Nexilis: NSObject {
         let message_id = me + CoreMessage_TMessageUtil.getTID()
         
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select user_id from BUDDY where f_pin = '\(me)'"), cursor.next() {
-                user_id = cursor.string(forColumnIndex: 0)
-                cursor.close()
+            do {
+                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select user_id from BUDDY where f_pin = '\(me)'"), cursor.next() {
+                    user_id = cursor.string(forColumnIndex: 0)
+                    cursor.close()
+                }
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
@@ -1548,17 +1418,22 @@ public class Nexilis: NSObject {
                 ], replace: true)
             } catch {
                 rollback.pointee = true
-                //print(error)
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         let pin = "-999"
         var counter : Int? = nil
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select counter from MESSAGE_SUMMARY where l_pin = '\(pin)'"), cursor.next() {
-                counter = Int(cursor.int(forColumnIndex: 0))
-                counter! += 1
-                cursor.close()
-                //print("select db message summary")
+            do {
+                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select counter from MESSAGE_SUMMARY where l_pin = '\(pin)'"), cursor.next() {
+                    counter = Int(cursor.int(forColumnIndex: 0))
+                    counter! += 1
+                    cursor.close()
+                    //print("select db message summary")
+                }
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         if counter == nil {
@@ -1574,7 +1449,7 @@ public class Nexilis: NSObject {
                 ], replace: true)
             } catch {
                 rollback.pointee = true
-                //print(error)
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         //print("insert db message summary \(message_id)")
@@ -1593,67 +1468,72 @@ public class Nexilis: NSObject {
         guard !l_pin.isEmpty else {
             return
         }
-        Database.shared.database?.inTransaction({ (fmdb, rollbac) in
-            if message_id.starts(with: "-1") || message_id.starts(with: "-2") {
-                for s in message_id.split(separator: ",") {
-                    let t = s.trimmingCharacters(in: .whitespaces)
-                    if t == "-1" || t == "-2" {
-                        continue
+        Database.shared.database?.inTransaction({ (fmdb, rollback) in
+            do {
+                if message_id.starts(with: "-1") || message_id.starts(with: "-2") {
+                    for s in message_id.split(separator: ",") {
+                        let t = s.trimmingCharacters(in: .whitespaces)
+                        if t == "-1" || t == "-2" {
+                            continue
+                        }
+                        if let cursorStatus = Database.shared.getRecords(fmdb: fmdb, query: "SELECT status FROM MESSAGE_STATUS where message_id = '\(t)'"), cursorStatus.next() {
+                            let lastStatus = cursorStatus.int(forColumnIndex: 0)
+                            if lastStatus < Int(status)! {
+                                if status == "3" {
+                                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
+                                        "status" : status,
+                                        "time_delivered" : String(Date().currentTimeMillis()),
+                                        "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(t)' and f_pin = '\(l_pin)'")
+                                } else if status == "4" {
+                                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
+                                        "status" : status,
+                                        "time_read" : String(Date().currentTimeMillis()),
+                                        "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(t)' and f_pin = '\(l_pin)'")
+                                } else if status == "8" {
+                                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
+                                        "status" : status,
+                                        "time_ack" : String(Date().currentTimeMillis()),
+                                        "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(t)' and f_pin = '\(l_pin)'")
+                                } else {
+                                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
+                                        "status" : status,
+                                        "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(t)' and f_pin = '\(l_pin)'")
+                                }
+                            }
+                            cursorStatus.close()
+                        }
                     }
-                    if let cursorStatus = Database.shared.getRecords(fmdb: fmdb, query: "SELECT status FROM MESSAGE_STATUS where message_id = '\(t)'"), cursorStatus.next() {
+                } else {
+                    if let cursorStatus = Database.shared.getRecords(fmdb: fmdb, query: "SELECT status FROM MESSAGE_STATUS where message_id = '\(message_id)'"), cursorStatus.next() {
                         let lastStatus = cursorStatus.int(forColumnIndex: 0)
                         if lastStatus < Int(status)! {
                             if status == "3" {
                                 _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
-                                                                    "status" : status,
-                                                                    "time_delivered" : String(Date().currentTimeMillis()),
-                                                                    "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(t)' and f_pin = '\(l_pin)'")
+                                    "status" : status,
+                                    "time_delivered" : String(Date().currentTimeMillis()),
+                                    "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(message_id)' and f_pin = '\(l_pin)'")
                             } else if status == "4" {
                                 _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
-                                                                    "status" : status,
-                                                                    "time_read" : String(Date().currentTimeMillis()),
-                                                                    "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(t)' and f_pin = '\(l_pin)'")
+                                    "status" : status,
+                                    "time_read" : String(Date().currentTimeMillis()),
+                                    "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(message_id)' and f_pin = '\(l_pin)'")
                             } else if status == "8" {
                                 _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
-                                                                    "status" : status,
-                                                                    "time_ack" : String(Date().currentTimeMillis()),
-                                                                    "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(t)' and f_pin = '\(l_pin)'")
+                                    "status" : status,
+                                    "time_ack" : String(Date().currentTimeMillis()),
+                                    "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(message_id)' and f_pin = '\(l_pin)'")
                             } else {
                                 _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
-                                                                    "status" : status,
-                                                                    "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(t)' and f_pin = '\(l_pin)'")
+                                    "status" : status,
+                                    "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(message_id)' and f_pin = '\(l_pin)'")
                             }
                         }
                         cursorStatus.close()
                     }
                 }
-            } else {
-                if let cursorStatus = Database.shared.getRecords(fmdb: fmdb, query: "SELECT status FROM MESSAGE_STATUS where message_id = '\(message_id)'"), cursorStatus.next() {
-                    let lastStatus = cursorStatus.int(forColumnIndex: 0)
-                    if lastStatus < Int(status)! {
-                        if status == "3" {
-                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
-                                                                "status" : status,
-                                                                "time_delivered" : String(Date().currentTimeMillis()),
-                                                                "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(message_id)' and f_pin = '\(l_pin)'")
-                        } else if status == "4" {
-                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
-                                                                "status" : status,
-                                                                "time_read" : String(Date().currentTimeMillis()),
-                                                                "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(message_id)' and f_pin = '\(l_pin)'")
-                        } else if status == "8" {
-                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
-                                                                "status" : status,
-                                                                "time_ack" : String(Date().currentTimeMillis()),
-                                                                "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(message_id)' and f_pin = '\(l_pin)'")
-                        } else {
-                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
-                                                                "status" : status,
-                                                                "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(message_id)' and f_pin = '\(l_pin)'")
-                        }
-                    }
-                    cursorStatus.close()
-                }
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
     }
@@ -1726,7 +1606,7 @@ public class Nexilis: NSObject {
                                 }
                             } catch {
                                 rollback.pointee = true
-                                //print(error)
+                                print("Access database error: \(error.localizedDescription)")
                             }
                         })
                     }
@@ -3530,14 +3410,19 @@ extension Nexilis: MessageDelegate {
                     }
                     if(nameUser == nil) {
                         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT first_name, last_name, image_id FROM BUDDY WHERE f_pin='\(String(describing: sender))'") {
-                                while cursor.next() {
-                                    let first_name = cursor.string(forColumnIndex: 0)!
-                                    let last_name = cursor.string(forColumnIndex: 1)!
-                                    nameUser = "\(first_name) \(last_name)".trimmingCharacters(in: .whitespaces)
-                                    profile = cursor.string(forColumnIndex: 2)!
+                            do {
+                                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT first_name, last_name, image_id FROM BUDDY WHERE f_pin='\(String(describing: sender))'") {
+                                    while cursor.next() {
+                                        let first_name = cursor.string(forColumnIndex: 0)!
+                                        let last_name = cursor.string(forColumnIndex: 1)!
+                                        nameUser = "\(first_name) \(last_name)".trimmingCharacters(in: .whitespaces)
+                                        profile = cursor.string(forColumnIndex: 2)!
+                                    }
+                                    cursor.close()
                                 }
-                                cursor.close()
+                            } catch {
+                                rollback.pointee = true
+                                print("Access database error: \(error.localizedDescription)")
                             }
                         })
                     }
@@ -3553,12 +3438,17 @@ extension Nexilis: MessageDelegate {
                         topicGroup = "Lounge"
                     } else {
                         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT title FROM DISCUSSION_FORUM WHERE chat_id='\(idTopic!)'") {
-                                while cursor.next() {
-                                    let title = cursor.string(forColumnIndex: 0)
-                                    topicGroup = title
+                            do {
+                                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT title FROM DISCUSSION_FORUM WHERE chat_id='\(idTopic!)'") {
+                                    while cursor.next() {
+                                        let title = cursor.string(forColumnIndex: 0)
+                                        topicGroup = title
+                                    }
+                                    cursor.close()
                                 }
-                                cursor.close()
+                            } catch {
+                                rollback.pointee = true
+                                print("Access database error: \(error.localizedDescription)")
                             }
                         })
                     }
@@ -3574,18 +3464,23 @@ extension Nexilis: MessageDelegate {
                         }
                     }
                     Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                        if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_name, image_id FROM GROUPZ WHERE group_id='\(idGroup)'") {
-                            while cursor.next() {
-                                let f_name = cursor.string(forColumnIndex: 0)
-                                var senderName = message.getBody(key: CoreMessage_TMessageKey.F_DISPLAY_NAME)
-                                if senderName.isEmpty {
-                                    senderName = "Bot"
-                                }
-                                nameUser =
+                        do {
+                            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_name, image_id FROM GROUPZ WHERE group_id='\(idGroup)'") {
+                                while cursor.next() {
+                                    let f_name = cursor.string(forColumnIndex: 0)
+                                    var senderName = message.getBody(key: CoreMessage_TMessageKey.F_DISPLAY_NAME)
+                                    if senderName.isEmpty {
+                                        senderName = "Bot"
+                                    }
+                                    nameUser =
                                     "\(senderName) \u{2022} \(f_name!)(\(topicGroup!))"
-                                profile = cursor.string(forColumnIndex: 1)!
+                                    profile = cursor.string(forColumnIndex: 1)!
+                                }
+                                cursor.close()
                             }
-                            cursor.close()
+                        } catch {
+                            rollback.pointee = true
+                            print("Access database error: \(error.localizedDescription)")
                         }
                     })
                     if idTopic == "Lounge" {
@@ -3744,37 +3639,42 @@ extension Nexilis: MessageDelegate {
                             floating.dismiss()
                         }
                         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                            if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT first_name, last_name FROM BUDDY where f_pin = '\(User.getMyPin()!)'"), cursorData.next() {
-                                if (cursorData.string(forColumnIndex: 0)! + " " + cursorData.string(forColumnIndex: 1)!).trimmingCharacters(in: .whitespaces) == "USR\(User.getMyPin()!)" {
-                                    let alert = LibAlertController(title: "Change Profile".localized(), message: "You must change your name to use this feature".localized(), preferredStyle: .alert)
-                                    alert.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: {(_) in
-                                        let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "signupsignin") as! SignUpSignIn
-                                        controller.forceLogin = true
-                                        let navigationController = CustomNavigationController(rootViewController: controller)
-                                        navigationController.modalPresentationStyle = .fullScreen
-                                        navigationController.navigationBar.tintColor = .white
-                                        navigationController.navigationBar.barTintColor = UIApplication.shared.visibleViewController?.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
-                                        navigationController.navigationBar.isTranslucent = false
-                                        navigationController.navigationBar.overrideUserInterfaceStyle = .dark
-                                        navigationController.navigationBar.barStyle = .black
-                                        let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
-                                        UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
-                                        let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
-                                        navigationController.navigationBar.titleTextAttributes = textAttributes
+                            do {
+                                if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT first_name, last_name FROM BUDDY where f_pin = '\(User.getMyPin()!)'"), cursorData.next() {
+                                    if (cursorData.string(forColumnIndex: 0)! + " " + cursorData.string(forColumnIndex: 1)!).trimmingCharacters(in: .whitespaces) == "USR\(User.getMyPin()!)" {
+                                        let alert = LibAlertController(title: "Change Profile".localized(), message: "You must change your name to use this feature".localized(), preferredStyle: .alert)
+                                        alert.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: {(_) in
+                                            let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "signupsignin") as! SignUpSignIn
+                                            controller.forceLogin = true
+                                            let navigationController = CustomNavigationController(rootViewController: controller)
+                                            navigationController.modalPresentationStyle = .fullScreen
+                                            navigationController.navigationBar.tintColor = .white
+                                            navigationController.navigationBar.barTintColor = UIApplication.shared.visibleViewController?.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
+                                            navigationController.navigationBar.isTranslucent = false
+                                            navigationController.navigationBar.overrideUserInterfaceStyle = .dark
+                                            navigationController.navigationBar.barStyle = .black
+                                            let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
+                                            UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
+                                            let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
+                                            navigationController.navigationBar.titleTextAttributes = textAttributes
+                                            if UIApplication.shared.visibleViewController?.navigationController != nil {
+                                                UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
+                                            } else {
+                                                UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
+                                            }
+                                        }))
                                         if UIApplication.shared.visibleViewController?.navigationController != nil {
-                                            UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
+                                            UIApplication.shared.visibleViewController?.navigationController?.present(alert, animated: true, completion: nil)
                                         } else {
-                                            UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
+                                            UIApplication.shared.visibleViewController?.present(alert, animated: true, completion: nil)
                                         }
-                                    }))
-                                    if UIApplication.shared.visibleViewController?.navigationController != nil {
-                                        UIApplication.shared.visibleViewController?.navigationController?.present(alert, animated: true, completion: nil)
-                                    } else {
-                                        UIApplication.shared.visibleViewController?.present(alert, animated: true, completion: nil)
                                     }
+                                    cursorData.close()
+                                    return
                                 }
-                                cursorData.close()
-                                return
+                            } catch {
+                                rollback.pointee = true
+                                print("Access database error: \(error.localizedDescription)")
                             }
                         })
                         if message.getBody(key: messageScopeId) == "3" || message.getBody(key: messageScopeId) == "18" || message.getBody(key: messageScopeId) == "5" {

+ 127 - 92
appbuilder-ios/NexilisLite/NexilisLite/Source/OutgoingThread.swift

@@ -25,22 +25,27 @@ class OutgoingThread {
     
     init() {
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select message, id from OUTGOING") {
-                while cursor.next() {
-                    if let message = cursor.string(forColumnIndex: 0) {
-                        if let cursorMessage = Database.shared.getRecords(fmdb: fmdb, query: "select message_id from MESSAGE where message_id = '\(cursor.string(forColumnIndex: 1)!)'") {
-                            if cursorMessage.next() {
-                                addQueue(message: TMessage(data: message))
+            do {
+                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select message, id from OUTGOING") {
+                    while cursor.next() {
+                        if let message = cursor.string(forColumnIndex: 0) {
+                            if let cursorMessage = Database.shared.getRecords(fmdb: fmdb, query: "select message_id from MESSAGE where message_id = '\(cursor.string(forColumnIndex: 1)!)'") {
+                                if cursorMessage.next() {
+                                    addQueue(message: TMessage(data: message))
+                                } else {
+                                    delOutgoing(fmdb: fmdb, messageId: cursor.string(forColumnIndex: 1)!)
+                                }
+                                cursorMessage.close()
                             } else {
                                 delOutgoing(fmdb: fmdb, messageId: cursor.string(forColumnIndex: 1)!)
                             }
-                            cursorMessage.close()
-                        } else {
-                            delOutgoing(fmdb: fmdb, messageId: cursor.string(forColumnIndex: 1)!)
                         }
                     }
+                    cursor.close()
                 }
-                cursor.close()
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
     }
@@ -69,7 +74,7 @@ class OutgoingThread {
                         ], replace: true)
                     } catch {
                         rollback.pointee = true
-                        //print(error)
+                        print("Access database error: \(error.localizedDescription)")
                     }
                 })
             }
@@ -180,10 +185,15 @@ class OutgoingThread {
                                         //print("sendChat", response.toLogString())
                                         let messageId = response.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID)
                                         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                                                "status" : response.getBody(key: CoreMessage_TMessageKey.STATUS, default_value: "2")
-                                            ], _where: "message_id = '\(messageId)'")
-                                            self.delOutgoing(fmdb: fmdb, messageId: messageId)
+                                            do {
+                                                _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                                                    "status" : response.getBody(key: CoreMessage_TMessageKey.STATUS, default_value: "2")
+                                                ], _where: "message_id = '\(messageId)'")
+                                                self.delOutgoing(fmdb: fmdb, messageId: messageId)
+                                            } catch {
+                                                rollback.pointee = true
+                                                print("Access database error: \(error.localizedDescription)")
+                                            }
                                         })
                                     } else {
                                         self.retryUpload(message: message, fileName: fileName)
@@ -208,10 +218,15 @@ class OutgoingThread {
                                 //print("sendChat", response.toLogString())
                                 let messageId = response.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID)
                                 Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                                        "status" : response.getBody(key: CoreMessage_TMessageKey.STATUS, default_value: "2")
-                                    ], _where: "message_id = '\(messageId)'")
-                                    self.delOutgoing(fmdb: fmdb, messageId: messageId)
+                                    do {
+                                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                                            "status" : response.getBody(key: CoreMessage_TMessageKey.STATUS, default_value: "2")
+                                        ], _where: "message_id = '\(messageId)'")
+                                        self.delOutgoing(fmdb: fmdb, messageId: messageId)
+                                    } catch {
+                                        rollback.pointee = true
+                                        print("Access database error: \(error.localizedDescription)")
+                                    }
                                 })
                             } else {
                                 self.retryUpload(message: message, fileName: fileName)
@@ -227,10 +242,15 @@ class OutgoingThread {
                 //print("sendChat", response.toLogString())
                 let messageId = response.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID)
                 Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                        "status" : response.getBody(key: CoreMessage_TMessageKey.STATUS, default_value: "2")
-                    ], _where: "message_id = '\(messageId)'")
-                    self.delOutgoing(fmdb: fmdb, messageId: messageId)
+                    do {
+                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                            "status" : response.getBody(key: CoreMessage_TMessageKey.STATUS, default_value: "2")
+                        ], _where: "message_id = '\(messageId)'")
+                        self.delOutgoing(fmdb: fmdb, messageId: messageId)
+                    } catch {
+                        rollback.pointee = true
+                        print("Access database error: \(error.localizedDescription)")
+                    }
                 })
             } else {
                 InquiryThread.default.addQueue(message: message)
@@ -259,13 +279,18 @@ class OutgoingThread {
         } catch {}
         if countRetry >= Int(maxRetry)! {
             Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                    "status" : "0"
-                ], _where: "message_id = '\(message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID))'")
-                _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
-                    "status" : "0"
-                ], _where: "message_id = '\(message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID))'")
-                self.delOutgoing(fmdb: fmdb, messageId: message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID))
+                do {
+                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                        "status" : "0"
+                    ], _where: "message_id = '\(message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID))'")
+                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
+                        "status" : "0"
+                    ], _where: "message_id = '\(message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID))'")
+                    self.delOutgoing(fmdb: fmdb, messageId: message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID))
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
+                }
             })
             var dataMessage: [AnyHashable : Any] = [:]
             dataMessage["message_id"] = message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID)
@@ -282,13 +307,18 @@ class OutgoingThread {
                 if timeRetry != 0 {
                     if (timeRetry + Int(maxRetryTime)!) <= Date().currentTimeMillis() {
                         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                                "status" : "0"
-                            ], _where: "message_id = '\(message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID))'")
-                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
-                                "status" : "0"
-                            ], _where: "message_id = '\(message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID))'")
-                            self.delOutgoing(fmdb: fmdb, messageId: message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID))
+                            do {
+                                _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                                    "status" : "0"
+                                ], _where: "message_id = '\(message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID))'")
+                                _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
+                                    "status" : "0"
+                                ], _where: "message_id = '\(message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID))'")
+                                self.delOutgoing(fmdb: fmdb, messageId: message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID))
+                            } catch {
+                                rollback.pointee = true
+                                print("Access database error: \(error.localizedDescription)")
+                            }
                         })
                         var dataMessage: [AnyHashable : Any] = [:]
                         dataMessage["message_id"] = message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID)
@@ -313,66 +343,71 @@ class OutgoingThread {
         let type = message.getBody(key: CoreMessage_TMessageKey.DELETE_MESSAGE_FLAG)
         
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            if type == "1" {
-                _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                    "message_text" : "🚫 _This message was deleted_",
-                    "lock" : "1",
-                    "thumb_id" : "",
-                    "image_id" : "",
-                    "file_id" : "",
-                    "audio_id" : "",
-                    "video_id" : "",
-                    "reff_id" : "",
-                    "attachment_flag" : 0,
-                    "is_stared" : "0",
-                    "credential" : "0",
-                    "read_receipts" : "4"
-                ], _where: "message_id = '\(messageId)'")
-                if let package = Nexilis.write(message: message) {
-                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "OUTGOING", cvalues: [
-                        "package" : package
-                    ], _where: "id = '\(messageId)'")
-                }
-                if let delegate = Nexilis.shared.messageDelegate {
-                    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reloadTabChats"), object: nil, userInfo: nil)
-                    delegate.onMessage(message: message)
-                }
-            } else {
-                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE", _where: "message_id = '\(messageId)'")
-                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "message_id = '\(messageId)'")
-                let l_pin = message.getBody(key: CoreMessage_TMessageKey.L_PIN)
-                let chat = message.getBody(key: CoreMessage_TMessageKey.CHAT_ID)
-                let scope = message.getBody(key: CoreMessage_TMessageKey.SCOPE_ID)
-                do {
-                    var pin = l_pin
-                    if !chat.isEmpty {
-                        pin = chat
+            do {
+                if type == "1" {
+                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                        "message_text" : "🚫 _This message was deleted_",
+                        "lock" : "1",
+                        "thumb_id" : "",
+                        "image_id" : "",
+                        "file_id" : "",
+                        "audio_id" : "",
+                        "video_id" : "",
+                        "reff_id" : "",
+                        "attachment_flag" : 0,
+                        "is_stared" : "0",
+                        "credential" : "0",
+                        "read_receipts" : "4"
+                    ], _where: "message_id = '\(messageId)'")
+                    if let package = Nexilis.write(message: message) {
+                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "OUTGOING", cvalues: [
+                            "package" : package
+                        ], _where: "id = '\(messageId)'")
                     }
-                    var queryGetLastMessageId = "SELECT message_id FROM MESSAGE where f_pin = '\(pin)' OR l_pin = '\(pin)' order by server_date desc LIMIT 1"
-                    if scope == "4" {
-                        queryGetLastMessageId = "SELECT message_id FROM MESSAGE where l_pin = '\(pin)' AND chat_id = '' order by server_date desc LIMIT 1"
+                    if let delegate = Nexilis.shared.messageDelegate {
+                        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reloadTabChats"), object: nil, userInfo: nil)
+                        delegate.onMessage(message: message)
+                    }
+                } else {
+                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE", _where: "message_id = '\(messageId)'")
+                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "message_id = '\(messageId)'")
+                    let l_pin = message.getBody(key: CoreMessage_TMessageKey.L_PIN)
+                    let chat = message.getBody(key: CoreMessage_TMessageKey.CHAT_ID)
+                    let scope = message.getBody(key: CoreMessage_TMessageKey.SCOPE_ID)
+                    do {
+                        var pin = l_pin
                         if !chat.isEmpty {
-                            queryGetLastMessageId = "SELECT message_id FROM MESSAGE where chat_id = '\(pin)' order by server_date desc LIMIT 1"
+                            pin = chat
                         }
+                        var queryGetLastMessageId = "SELECT message_id FROM MESSAGE where f_pin = '\(pin)' OR l_pin = '\(pin)' order by server_date desc LIMIT 1"
+                        if scope == "4" {
+                            queryGetLastMessageId = "SELECT message_id FROM MESSAGE where l_pin = '\(pin)' AND chat_id = '' order by server_date desc LIMIT 1"
+                            if !chat.isEmpty {
+                                queryGetLastMessageId = "SELECT message_id FROM MESSAGE where chat_id = '\(pin)' order by server_date desc LIMIT 1"
+                            }
+                        }
+                        var messageId = ""
+                        if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: queryGetLastMessageId), cursorData.next() {
+                            messageId = cursorData.string(forColumnIndex: 0) ?? ""
+                            cursorData.close()
+                        }
+                        if !messageId.isEmpty {
+                            _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", cvalues: [
+                                "l_pin" : pin,
+                                "message_id" : messageId,
+                                "counter" : 0
+                            ], replace: true)
+                        }
+                        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reloadTabChats"), object: nil, userInfo: nil)
+                    } catch {
+                        rollback.pointee = true
+                        //print(error)
                     }
-                    var messageId = ""
-                    if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: queryGetLastMessageId), cursorData.next() {
-                        messageId = cursorData.string(forColumnIndex: 0) ?? ""
-                        cursorData.close()
-                    }
-                    if !messageId.isEmpty {
-                        _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", cvalues: [
-                            "l_pin" : pin,
-                            "message_id" : messageId,
-                            "counter" : 0
-                        ], replace: true)
-                    }
-                    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reloadTabChats"), object: nil, userInfo: nil)
-                } catch {
-                    rollback.pointee = true
-                    //print(error)
+                    self.delOutgoing(fmdb: fmdb, messageId: messageId)
                 }
-                self.delOutgoing(fmdb: fmdb, messageId: messageId)
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
     }

+ 106 - 62
appbuilder-ios/NexilisLite/NexilisLite/Source/Utils.swift

@@ -12,6 +12,7 @@ import NotificationBannerSwift
 import nuSDKService
 import CoreLocation
 import CryptoKit
+import LocalAuthentication
 //import var CommonCrypto.CC_MD5_DIGEST_LENGTH
 //import func CommonCrypto.CC_MD5
 //import typealias CommonCrypto.CC_LONG
@@ -522,6 +523,7 @@ public final class Utils {
         let apiKey: String = SecureUserDefaults.shared.value(forKey: "apiKey") ?? ""
         let f_pin: String = User.getMyPin() ?? ""
         let parameters = [
+            "app_id": APIS.getAppNm(),
             "apikey": apiKey,
             "f_pin": f_pin
         ]
@@ -579,98 +581,98 @@ public final class Utils {
     }
     
     public static func setValueInitialApp(data: String) {
-        if let jsonArray = try! JSONSerialization.jsonObject(with: data.data(using: String.Encoding.utf8)!, options: JSONSerialization.ReadingOptions()) as? [AnyObject] {
+        if let jsonArray = try! JSONSerialization.jsonObject(with: data.data(using: String.Encoding.utf8)!, options: JSONSerialization.ReadingOptions()) as? [[String: Any?]] {
             do {
                 for json in jsonArray {
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "app_builder_url_first_tab" {
-                        Utils.setURLFirstTab(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "app_builder_url_first_tab" {
+                        Utils.setURLFirstTab(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "app_builder_url_third_tab" {
-                        Utils.setURLThirdTab(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "app_builder_url_third_tab" {
+                        Utils.setURLThirdTab(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "app_builder_custom_tab" {
-                        Utils.setCustomTab(cust: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "app_builder_custom_tab" {
+                        Utils.setCustomTab(cust: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "app_builder_url_base" {
-                        Utils.setURLBase(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "app_builder_url_base" {
+                        Utils.setURLBase(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "app_builder_url_qms" {
-                        Utils.setURLQMS(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "app_builder_url_qms" {
+                        Utils.setURLQMS(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "app_builder_icon_dock" {
-                        Utils.setIconDock(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "app_builder_icon_dock" {
+                        Utils.setIconDock(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "app_builder_icon_ss" {
-                        Utils.setIconSS(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "app_builder_icon_ss" {
+                        Utils.setIconSS(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "app_builder_background" {
-                        Utils.setBackground(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "app_builder_background" {
+                        Utils.setBackground(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "app_builder_url_privacy_policy" {
-                        Utils.setURLPrivacyPolicy(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "app_builder_url_privacy_policy" {
+                        Utils.setURLPrivacyPolicy(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "app_builder_enable_privacy_policy" {
-                        Utils.setEnablePrivacyPolicy(value: json[CoreMessage_TMessageKey.VALUE] as! String == "1" ? true : false)
+                    if Array(json.keys)[0] == "app_builder_enable_privacy_policy" {
+                        Utils.setEnablePrivacyPolicy(value: Array(json.values)[0] as! String == "1" ? true : false)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "pb_fb_icon_center_self_mode2" {
-                        Utils.setIconCenterAnim2(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "pb_fb_icon_center_self_mode2" {
+                        Utils.setIconCenterAnim2(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "pb_fb_icon_center_self_mode4" {
-                        Utils.setIconCenterAnim4(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "pb_fb_icon_center_self_mode4" {
+                        Utils.setIconCenterAnim4(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "app_builder_ac_theme" {
-                        Utils.setACTheme(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "app_builder_ac_theme" {
+                        Utils.setACTheme(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "app_builder_button_url" {
-                        Utils.setButtonURL(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "app_builder_button_url" {
+                        Utils.setButtonURL(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "app_builder_custom_buttons" {
-                        Utils.setCustomButtons(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "app_builder_custom_buttons" {
+                        Utils.setCustomButtons(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "app_builder_enable_mobile_builder" {
-                        Utils.setEnableMobileBuilder(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "app_builder_enable_mobile_builder" {
+                        Utils.setEnableMobileBuilder(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "app_builder_enable_mobile_builder" {
-                        Utils.setEnableMobileBuilder(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "app_builder_enable_mobile_builder" {
+                        Utils.setEnableMobileBuilder(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "fb_config_mode" {
-                        Utils.setConfigModeFB(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "fb_config_mode" {
+                        Utils.setConfigModeFB(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "app_builder_button_icon" {
-                        Utils.setCustomFBIcon(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "app_builder_button_icon" {
+                        Utils.setCustomFBIcon(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "fb_floating_anim" {
-                        Utils.setFloatingAnim(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "fb_floating_anim" {
+                        Utils.setFloatingAnim(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "fb_icon_with_bg" {
-                        Utils.setFBIconBg(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "fb_icon_with_bg" {
+                        Utils.setFBIconBg(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "fb_item_with_bg" {
-                        Utils.setFBItemBg(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "fb_item_with_bg" {
+                        Utils.setFBItemBg(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "user_agent" {
-                        Utils.setUserAgent(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "user_agent" {
+                        Utils.setUserAgent(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "app_builder_background_light" {
-                        Utils.setBackgroundLight(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "app_builder_background_light" {
+                        Utils.setBackgroundLight(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "app_builder_background_dark" {
-                        Utils.setBackgroundDark(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "app_builder_background_dark" {
+                        Utils.setBackgroundDark(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "sms_center" {
-                        Utils.setSMSCenter(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "sms_center" {
+                        Utils.setSMSCenter(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "whatsapp_center" {
-                        Utils.setWhatsappCenter(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "whatsapp_center" {
+                        Utils.setWhatsappCenter(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "call_center" {
-                        Utils.setCallCenter(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "call_center" {
+                        Utils.setCallCenter(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "enable_valid_trans" {
-                        Utils.setValidTrans(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "enable_valid_trans" {
+                        Utils.setValidTrans(value: Array(json.values)[0] as! String)
                     }
-                    if json[CoreMessage_TMessageKey.KEY] as! String == "chatbot_greetings" {
-                        Utils.setValidTrans(value: json[CoreMessage_TMessageKey.VALUE] as! String)
+                    if Array(json.keys)[0] == "chatbot_greetings" {
+                        Utils.setValidTrans(value: Array(json.values)[0] as! String)
                     }
                 }
             } catch {
@@ -1161,7 +1163,10 @@ public final class Utils {
                 if result == errSecSuccess {
                     let encrypt = try MasterKeyUtil.shared.encryptD(data: keyData)
                     setPassEncDB(value: encrypt.base64EncodedString())
-                    return keyData.base64EncodedString()
+                    
+                    let keyTemp = keyData.base64EncodedString()
+                    keyData.resetBytes(in: 0..<keyData.count)
+                    return keyTemp
                     
                 } else {
                     print("Error generating random bytes: \(result)")
@@ -1175,6 +1180,45 @@ public final class Utils {
             return nil
         }
     }
+    
+    public static func shouldRequestAuthentication() -> Bool {
+        if let lastAuthTime: Date = SecureUserDefaults.shared.value(forKey: "lastAuthenticationTime") {
+            let elapsedTime = Date().timeIntervalSince(lastAuthTime)
+            return elapsedTime > (60 * 5)
+        }
+        return true
+    }
+
+    public static func authenticateWithBiometrics(completion: @escaping (Bool, String?) -> Void) {
+        guard shouldRequestAuthentication() else {
+            completion(true, nil)
+            return
+        }
+
+        let context = LAContext()
+        let reason = "Authenticate to access secure data"
+
+        if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) {
+            context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, error in
+                if success {
+                    // Store the time of successful authentication
+                    SecureUserDefaults.shared.set(Date(), forKey: "lastAuthenticationTime")
+                    completion(true, nil)
+                } else {
+                    let errorMessage = error?.localizedDescription ?? "Authentication failed"
+                    completion(false, errorMessage)
+                }
+            }
+        } else {
+            completion(false, "Biometric authentication is not available")
+        }
+    }
+    
+    static func showAlert(title: String, message: String) {
+        let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
+        alertController.addAction(UIAlertAction(title: "OK", style: .default))
+        UIApplication.shared.visibleViewController?.present(alertController, animated: true)
+    }
 }
 public extension UIImage {
     var jpeg: Data? { jpegData(compressionQuality: 1) }  // QUALITY min = 0 / max = 1

+ 41 - 16
appbuilder-ios/NexilisLite/NexilisLite/Source/View/BNIView/BNIBookingWebView.swift

@@ -199,9 +199,14 @@ public class BNIBookingWebView: UIViewController, WKNavigationDelegate, UIScroll
                         if response.isOk() {
                             DispatchQueue.main.async {
                                 Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
-                                        "ex_block" : "1"
-                                    ], _where: "f_pin = '\(param1)'")
+                                    do {
+                                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
+                                            "ex_block" : "1"
+                                        ], _where: "f_pin = '\(param1)'")
+                                    } catch {
+                                        rollback.pointee = true
+                                        print("Access database error: \(error.localizedDescription)")
+                                    }
                                 })
                             }
                         }
@@ -213,9 +218,14 @@ public class BNIBookingWebView: UIViewController, WKNavigationDelegate, UIScroll
                         if response.isOk() {
                             DispatchQueue.main.async {
                                 Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
-                                        "ex_block" : "0"
-                                    ], _where: "f_pin = '\(param1)'")
+                                    do {
+                                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
+                                            "ex_block" : "0"
+                                        ], _where: "f_pin = '\(param1)'")
+                                    } catch {
+                                        rollback.pointee = true
+                                        print("Access database error: \(error.localizedDescription)")
+                                    }
                                 })
                             }
                         }
@@ -240,9 +250,14 @@ public class BNIBookingWebView: UIViewController, WKNavigationDelegate, UIScroll
                         if response.isOk() {
                             DispatchQueue.main.async {
                                 Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
-                                        "ex_block" : "1"
-                                    ], _where: "f_pin = '\(param1)'")
+                                    do {
+                                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
+                                            "ex_block" : "1"
+                                        ], _where: "f_pin = '\(param1)'")
+                                    } catch {
+                                        rollback.pointee = true
+                                        print("Access database error: \(error.localizedDescription)")
+                                    }
                                 })
                             }
                         }
@@ -254,9 +269,14 @@ public class BNIBookingWebView: UIViewController, WKNavigationDelegate, UIScroll
                         if response.isOk() {
                             DispatchQueue.main.async {
                                 Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
-                                        "ex_block" : "0"
-                                    ], _where: "f_pin = '\(param1)'")
+                                    do {
+                                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
+                                            "ex_block" : "0"
+                                        ], _where: "f_pin = '\(param1)'")
+                                    } catch {
+                                        rollback.pointee = true
+                                        print("Access database error: \(error.localizedDescription)")
+                                    }
                                 })
                             }
                         }
@@ -370,10 +390,15 @@ public class BNIBookingWebView: UIViewController, WKNavigationDelegate, UIScroll
                 }
             }
             Database.shared.database?.inTransaction({ fmdb, rollback in
-                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ", _where: "")
-                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ_MEMBER", _where: "")
-                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "DISCUSSION_FORUM", _where: "")
-                _ = Nexilis.write(message: CoreMessage_TMessageBank.getPostRegistration(p_pin: User.getMyPin() ?? ""))
+                do {
+                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ", _where: "")
+                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ_MEMBER", _where: "")
+                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "DISCUSSION_FORUM", _where: "")
+                    _ = Nexilis.write(message: CoreMessage_TMessageBank.getPostRegistration(p_pin: User.getMyPin() ?? ""))
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
+                }
             })
             let alert = LibAlertController(title: "Successfully changed".localized(), message: "Please open the app again to see the changes".localized(), preferredStyle: .alert)
             alert.addAction(UIAlertAction(title: "OK".localized(), style: .default, handler: {(_) in

+ 13 - 8
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Call/AudioViewController.swift

@@ -62,15 +62,20 @@ class AudioViewController: UIViewController {
             self.pin = pin
             
             Database.shared.database?.inTransaction({ fmdb, rollback in
-                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select FIRST_NAME || ' ' || ifnull(LAST_NAME, ''), IMAGE_ID from BUDDY where F_PIN = '\(pin)'"), cursor.next() {
-                    name.text = cursor.string(forColumnIndex: 0)?.trimmingCharacters(in: .whitespaces)
-                    if let image = cursor.string(forColumnIndex: 1), !image.isEmpty {
-                        profile.setImage(name: image)
-                        profile.contentMode = .scaleAspectFill
+                do {
+                    if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select FIRST_NAME || ' ' || ifnull(LAST_NAME, ''), IMAGE_ID from BUDDY where F_PIN = '\(pin)'"), cursor.next() {
+                        name.text = cursor.string(forColumnIndex: 0)?.trimmingCharacters(in: .whitespaces)
+                        if let image = cursor.string(forColumnIndex: 1), !image.isEmpty {
+                            profile.setImage(name: image)
+                            profile.contentMode = .scaleAspectFill
+                        }
+                        
+                        //
+                        cursor.close()
                     }
-                    
-                    //
-                    cursor.close()
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
                 }
             })
             

+ 2 - 2
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Call/QmeraAudioConference.swift

@@ -334,7 +334,7 @@ class QmeraAudioConference: UIViewController {
                             ], replace: true)
                         } catch {
                             rollback.pointee = true
-                            //print(error)
+                            print("Access database error: \(error.localizedDescription)")
                         }
                     })
                     SecureUserDefaults.shared.removeValue(forKey: "onGoingCC")
@@ -370,7 +370,7 @@ class QmeraAudioConference: UIViewController {
                             ], replace: true)
                         } catch {
                             rollback.pointee = true
-                            //print(error)
+                            print("Access database error: \(error.localizedDescription)")
                         }
                     })
                     if requester == idMe {

+ 13 - 8
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Call/QmeraAudioViewController.swift

@@ -344,12 +344,17 @@ class QmeraAudioViewController: UIViewController {
         var user: User?
         DispatchQueue.global().async {
             Database.shared.database?.inTransaction({ fmdb, rollback in
-                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin, first_name, last_name, image_id from BUDDY where f_pin = '\(self.data)'"), cursor.next() {
-                    user = User(pin: cursor.string(forColumnIndex: 0) ?? "",
-                                firstName: cursor.string(forColumnIndex: 1) ?? "",
-                                lastName: cursor.string(forColumnIndex: 2) ?? "",
-                                thumb: cursor.string(forColumnIndex: 3) ?? "")
-                    cursor.close()
+                do {
+                    if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin, first_name, last_name, image_id from BUDDY where f_pin = '\(self.data)'"), cursor.next() {
+                        user = User(pin: cursor.string(forColumnIndex: 0) ?? "",
+                                    firstName: cursor.string(forColumnIndex: 1) ?? "",
+                                    lastName: cursor.string(forColumnIndex: 2) ?? "",
+                                    thumb: cursor.string(forColumnIndex: 3) ?? "")
+                        cursor.close()
+                    }
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
                 }
             })
         }
@@ -653,7 +658,7 @@ class QmeraAudioViewController: UIViewController {
                                 ], replace: true)
                             } catch {
                                 rollback.pointee = true
-                                //print(error)
+                                print("Access database error: \(error.localizedDescription)")
                             }
                         })
                     }
@@ -690,7 +695,7 @@ class QmeraAudioViewController: UIViewController {
                             ], replace: true)
                         } catch {
                             rollback.pointee = true
-                            //print(error)
+                            print("Access database error: \(error.localizedDescription)")
                         }
                     })
                     if officer == idMe {

+ 18 - 13
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Call/QmeraCallContactViewController.swift

@@ -100,21 +100,26 @@ class QmeraCallContactViewController: UITableViewController {
                 query = "SELECT f_pin, first_name, last_name, image_id, user_type, official_account, ex_offmp FROM BUDDY where f_pin <> '\(User.getMyPin()!)' order by 2 collate nocase asc"
             }
             Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: query) {
-                    while cursor.next() {
-                        let user = User(pin: cursor.string(forColumnIndex: 0) ?? "",
-                                        firstName: cursor.string(forColumnIndex: 1) ?? "",
-                                        lastName: cursor.string(forColumnIndex: 2) ?? "",
-                                        thumb: cursor.string(forColumnIndex: 3) ?? "",
-                                        userType: cursor.string(forColumnIndex: 4) ?? "",
-                                        official: cursor.string(forColumnIndex: 5) ?? "",
-                                        ex_offmp: cursor.string(forColumnIndex: 6) ?? "")
-                        if (user.firstName + " " + user.lastName).trimmingCharacters(in: .whitespaces) == "USR\(user.pin)" {
-                            continue
+                do {
+                    if let cursor = Database.shared.getRecords(fmdb: fmdb, query: query) {
+                        while cursor.next() {
+                            let user = User(pin: cursor.string(forColumnIndex: 0) ?? "",
+                                            firstName: cursor.string(forColumnIndex: 1) ?? "",
+                                            lastName: cursor.string(forColumnIndex: 2) ?? "",
+                                            thumb: cursor.string(forColumnIndex: 3) ?? "",
+                                            userType: cursor.string(forColumnIndex: 4) ?? "",
+                                            official: cursor.string(forColumnIndex: 5) ?? "",
+                                            ex_offmp: cursor.string(forColumnIndex: 6) ?? "")
+                            if (user.firstName + " " + user.lastName).trimmingCharacters(in: .whitespaces) == "USR\(user.pin)" {
+                                continue
+                            }
+                            contacts.append(user)
                         }
-                        contacts.append(user)
+                        cursor.close()
                     }
-                    cursor.close()
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
                 }
             })
             var dataContacts = contacts.filter { !self.selectedUser.contains($0) }

+ 48 - 43
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Call/QmeraVideoViewController.swift

@@ -176,26 +176,39 @@ class QmeraVideoViewController: UIViewController {
     func getDataProfile(fPin: String) {
         let query = "SELECT f_pin, first_name, last_name, official_account, image_id, device_id, offline_mode, user_type FROM BUDDY where f_pin = '\(fPin)'"
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: query) {
-                var row: [String: String?] = [:]
-                if cursorData.next() {
-                    row["f_pin"] = cursorData.string(forColumnIndex: 0)
-                    var name = ""
-                    if let firstname = cursorData.string(forColumnIndex: 1) {
-                        name = firstname
-                    }
-                    if let lastname = cursorData.string(forColumnIndex: 2) {
-                        name = name + " " + lastname
-                    }
-                    row["name"] = name
-                    row["picture"] = cursorData.string(forColumnIndex: 4)
-                    row["isOfficial"] = cursorData.string(forColumnIndex: 3)
-                    row["deviceId"] = cursorData.string(forColumnIndex: 5)
-                    row["isOffline"] = cursorData.string(forColumnIndex: 6)
-                    row["user_type"] = cursorData.string(forColumnIndex: 7)
-                    if fPin != User.getMyPin() {
+            do {
+                if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: query) {
+                    var row: [String: String?] = [:]
+                    if cursorData.next() {
+                        row["f_pin"] = cursorData.string(forColumnIndex: 0)
+                        var name = ""
+                        if let firstname = cursorData.string(forColumnIndex: 1) {
+                            name = firstname
+                        }
+                        if let lastname = cursorData.string(forColumnIndex: 2) {
+                            name = name + " " + lastname
+                        }
+                        row["name"] = name
+                        row["picture"] = cursorData.string(forColumnIndex: 4)
+                        row["isOfficial"] = cursorData.string(forColumnIndex: 3)
+                        row["deviceId"] = cursorData.string(forColumnIndex: 5)
+                        row["isOffline"] = cursorData.string(forColumnIndex: 6)
+                        row["user_type"] = cursorData.string(forColumnIndex: 7)
+                        if fPin != User.getMyPin() {
+                            dataPerson.append(row)
+                        }
+                    } else {
+                        var row: [String: String?] = [:]
+                        row["f_pin"] = fPin
+                        row["name"] = "User".localized()
+                        row["picture"] = ""
+                        row["isOfficial"] = ""
+                        row["deviceId"] = ""
+                        row["isOffline"] = ""
+                        row["user_type"] = ""
                         dataPerson.append(row)
                     }
+                    cursorData.close()
                 } else {
                     var row: [String: String?] = [:]
                     row["f_pin"] = fPin
@@ -206,31 +219,23 @@ class QmeraVideoViewController: UIViewController {
                     row["isOffline"] = ""
                     row["user_type"] = ""
                     dataPerson.append(row)
+    //                if let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getAddFriendQRCode(fpin: fPin)), response.isOk() {
+    //                    self.getDataProfile(fPin: fPin)
+    //                }
+    //                Nexilis.addFriend (fpin: "\(fPin)") { result in
+    //                    if result {
+    //                        self.getDataProfile(fPin: fPin)
+    //                    } else {
+    //                        let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+    //                        imageView.tintColor = .white
+    //                        let banner = FloatingNotificationBanner(title: "Server busy, please try again later".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .center)
+    //                        banner.show()
+    //                    }
+    //                }
                 }
-                cursorData.close()
-            } else {
-                var row: [String: String?] = [:]
-                row["f_pin"] = fPin
-                row["name"] = "User".localized()
-                row["picture"] = ""
-                row["isOfficial"] = ""
-                row["deviceId"] = ""
-                row["isOffline"] = ""
-                row["user_type"] = ""
-                dataPerson.append(row)
-//                if let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getAddFriendQRCode(fpin: fPin)), response.isOk() {
-//                    self.getDataProfile(fPin: fPin)
-//                }
-//                Nexilis.addFriend (fpin: "\(fPin)") { result in
-//                    if result {
-//                        self.getDataProfile(fPin: fPin)
-//                    } else {
-//                        let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
-//                        imageView.tintColor = .white
-//                        let banner = FloatingNotificationBanner(title: "Server busy, please try again later".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .center)
-//                        banner.show()
-//                    }
-//                }
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
     }
@@ -872,7 +877,7 @@ class QmeraVideoViewController: UIViewController {
                         ], replace: true)
                     } catch {
                         rollback.pointee = true
-                        //print(error)
+                        print("Access database error: \(error.localizedDescription)")
                     }
                 })
                 if officer == idMe {

+ 132 - 87
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Chat/ChatGPTBotView.swift

@@ -165,9 +165,14 @@ class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
         chatGPTMessages.append(gptRow)
         
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select user_id from BUDDY where f_pin = '\(me)'"), cursor.next() {
-                user_id = cursor.string(forColumnIndex: 0)
-                cursor.close()
+            do {
+                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select user_id from BUDDY where f_pin = '\(me)'"), cursor.next() {
+                    user_id = cursor.string(forColumnIndex: 0)
+                    cursor.close()
+                }
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
@@ -201,17 +206,22 @@ class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
                 ], replace: true)
             } catch {
                 rollback.pointee = true
-                //print(error)
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         let pin = "-997"
         var counter : Int? = nil
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select counter from MESSAGE_SUMMARY where l_pin = '\(pin)'"), cursor.next() {
-                counter = Int(cursor.int(forColumnIndex: 0))
-                counter! += 0
-                cursor.close()
-                //print("select db message summary")
+            do {
+                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select counter from MESSAGE_SUMMARY where l_pin = '\(pin)'"), cursor.next() {
+                    counter = Int(cursor.int(forColumnIndex: 0))
+                    counter! += 0
+                    cursor.close()
+                    //print("select db message summary")
+                }
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         if counter == nil {
@@ -227,7 +237,7 @@ class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
                 ], replace: true)
             } catch {
                 rollback.pointee = true
-                //print(error)
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         var row: [String: Any?] = [:]
@@ -404,9 +414,14 @@ class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
                                 let server_date = String(Date().currentTimeMillis())
                                 
                                 Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                                    if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select user_id from BUDDY where f_pin = '\(me)'"), cursor.next() {
-                                        user_id = cursor.string(forColumnIndex: 0)
-                                        cursor.close()
+                                    do {
+                                        if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select user_id from BUDDY where f_pin = '\(me)'"), cursor.next() {
+                                            user_id = cursor.string(forColumnIndex: 0)
+                                            cursor.close()
+                                        }
+                                    } catch {
+                                        rollback.pointee = true
+                                        print("Access database error: \(error.localizedDescription)")
                                     }
                                 })
                                 Database.shared.database?.inTransaction({ (fmdb, rollback) in
@@ -440,17 +455,22 @@ class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
                                         ], replace: true)
                                     } catch {
                                         rollback.pointee = true
-                                        //print(error)
+                                        print("Access database error: \(error.localizedDescription)")
                                     }
                                 })
                                 let pin = "-997"
                                 var counter : Int? = nil
                                 Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                                    if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select counter from MESSAGE_SUMMARY where l_pin = '\(pin)'"), cursor.next() {
-                                        counter = Int(cursor.int(forColumnIndex: 0))
-                                        counter! += 1
-                                        cursor.close()
-                                        //print("select db message summary")
+                                    do {
+                                        if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select counter from MESSAGE_SUMMARY where l_pin = '\(pin)'"), cursor.next() {
+                                            counter = Int(cursor.int(forColumnIndex: 0))
+                                            counter! += 1
+                                            cursor.close()
+                                            //print("select db message summary")
+                                        }
+                                    } catch {
+                                        rollback.pointee = true
+                                        print("Access database error: \(error.localizedDescription)")
                                     }
                                 })
                                 if counter == nil {
@@ -466,7 +486,7 @@ class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
                                         ], replace: true)
                                     } catch {
                                         rollback.pointee = true
-                                        //print(error)
+                                        print("Access database error: \(error.localizedDescription)")
                                     }
                                 })
                                 //print("insert db message summary \(message_id)")
@@ -654,64 +674,69 @@ class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
     private func getData() {
         var query = "SELECT message_id, f_pin, l_pin, message_scope_id, server_date, status, message_text, audio_id, video_id, image_id, thumb_id, read_receipts, chat_id, file_id, attachment_flag, reff_id, lock, is_stared, blog_id, credential FROM MESSAGE where (f_pin='\(dataPerson["f_pin"]!!)' or l_pin='\(dataPerson["f_pin"]!!)') AND message_scope_id = '31' order by server_date asc"
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: query) {
-                while cursorData.next() {
-                    var row: [String: Any?] = [:]
-                    row["message_id"] = cursorData.string(forColumnIndex: 0)
-                    row["f_pin"] = cursorData.string(forColumnIndex: 1)
-                    row["l_pin"] = cursorData.string(forColumnIndex: 2)
-                    row["message_scope_id"] = cursorData.string(forColumnIndex: 3)
-                    row["server_date"] = cursorData.string(forColumnIndex: 4)
-                    row["status"] = cursorData.string(forColumnIndex: 5)
-                    row["message_text"] = cursorData.string(forColumnIndex: 6)
-                    row["audio_id"] = cursorData.string(forColumnIndex: 7)
-                    row["video_id"] = cursorData.string(forColumnIndex: 8)
-                    row["image_id"] = cursorData.string(forColumnIndex: 9)
-                    row["thumb_id"] = cursorData.string(forColumnIndex: 10)
-                    row["read_receipts"] = cursorData.string(forColumnIndex: 11)
-                    row["chat_id"] = cursorData.string(forColumnIndex: 12)
-                    row["file_id"] = cursorData.string(forColumnIndex: 13)
-                    row["attachment_flag"] = cursorData.string(forColumnIndex: 14)
-                    row["reff_id"] = cursorData.string(forColumnIndex: 15)
-                    row["lock"] = cursorData.string(forColumnIndex: 16)
-                    row["is_stared"] = cursorData.string(forColumnIndex: 17)
-                    row["blog_id"] = cursorData.string(forColumnIndex: 18)
-                    row["credential"] = cursorData.string(forColumnIndex: 19)
-                    if let cursorStatus = Database.shared.getRecords(fmdb: fmdb, query: "SELECT status FROM MESSAGE_STATUS WHERE message_id='\(row["message_id"] as! String)'") {
-                        while cursorStatus.next() {
-                            row["status"] = cursorStatus.string(forColumnIndex: 0)
-                        }
-                        cursorStatus.close()
-                    }
-                    let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
-                    let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
-                    let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
-                    if let dirPath = paths.first {
-                        let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["video_id"] as! String)
-                        let fileURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["file_id"] as! String)
-                        if ((row["video_id"] as! String) != "") {
-                            if FileManager.default.fileExists(atPath: videoURL.path){
-                                row["progress"] = 100.0
-                            } else {
-                                row["progress"] = 0.0
+            do {
+                if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: query) {
+                    while cursorData.next() {
+                        var row: [String: Any?] = [:]
+                        row["message_id"] = cursorData.string(forColumnIndex: 0)
+                        row["f_pin"] = cursorData.string(forColumnIndex: 1)
+                        row["l_pin"] = cursorData.string(forColumnIndex: 2)
+                        row["message_scope_id"] = cursorData.string(forColumnIndex: 3)
+                        row["server_date"] = cursorData.string(forColumnIndex: 4)
+                        row["status"] = cursorData.string(forColumnIndex: 5)
+                        row["message_text"] = cursorData.string(forColumnIndex: 6)
+                        row["audio_id"] = cursorData.string(forColumnIndex: 7)
+                        row["video_id"] = cursorData.string(forColumnIndex: 8)
+                        row["image_id"] = cursorData.string(forColumnIndex: 9)
+                        row["thumb_id"] = cursorData.string(forColumnIndex: 10)
+                        row["read_receipts"] = cursorData.string(forColumnIndex: 11)
+                        row["chat_id"] = cursorData.string(forColumnIndex: 12)
+                        row["file_id"] = cursorData.string(forColumnIndex: 13)
+                        row["attachment_flag"] = cursorData.string(forColumnIndex: 14)
+                        row["reff_id"] = cursorData.string(forColumnIndex: 15)
+                        row["lock"] = cursorData.string(forColumnIndex: 16)
+                        row["is_stared"] = cursorData.string(forColumnIndex: 17)
+                        row["blog_id"] = cursorData.string(forColumnIndex: 18)
+                        row["credential"] = cursorData.string(forColumnIndex: 19)
+                        if let cursorStatus = Database.shared.getRecords(fmdb: fmdb, query: "SELECT status FROM MESSAGE_STATUS WHERE message_id='\(row["message_id"] as! String)'") {
+                            while cursorStatus.next() {
+                                row["status"] = cursorStatus.string(forColumnIndex: 0)
                             }
-                        } else {
-                            if FileManager.default.fileExists(atPath: fileURL.path){
-                                row["progress"] = 100.0
+                            cursorStatus.close()
+                        }
+                        let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
+                        let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
+                        let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
+                        if let dirPath = paths.first {
+                            let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["video_id"] as! String)
+                            let fileURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["file_id"] as! String)
+                            if ((row["video_id"] as! String) != "") {
+                                if FileManager.default.fileExists(atPath: videoURL.path){
+                                    row["progress"] = 100.0
+                                } else {
+                                    row["progress"] = 0.0
+                                }
                             } else {
-                                row["progress"] = 0.0
+                                if FileManager.default.fileExists(atPath: fileURL.path){
+                                    row["progress"] = 100.0
+                                } else {
+                                    row["progress"] = 0.0
+                                }
                             }
                         }
+                        row["chat_date"] = chatDate(stringDate: row["server_date"] as! String)
+                        row["isSelected"] = false
+                        dataMessages.append(row)
+                        var gptRow : [String: String] = [:]
+                        gptRow["role"] = row["f_pin"] as! String == "-997" ? "assistant" : "user"
+                        gptRow["content"] = row["message_text"] as! String
+                        chatGPTMessages.append(gptRow)
                     }
-                    row["chat_date"] = chatDate(stringDate: row["server_date"] as! String)
-                    row["isSelected"] = false
-                    dataMessages.append(row)
-                    var gptRow : [String: String] = [:]
-                    gptRow["role"] = row["f_pin"] as! String == "-997" ? "assistant" : "user"
-                    gptRow["content"] = row["message_text"] as! String
-                    chatGPTMessages.append(gptRow)
+                    cursorData.close()
                 }
-                cursorData.close()
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
     }
@@ -723,12 +748,17 @@ class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
             alert.addAction(UIAlertAction(title: "Cancel".localized(), style: UIAlertAction.Style.default, handler: nil))
             alert.addAction(UIAlertAction(title: "Delete".localized(), style: .destructive, handler: {(_) in
                 Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE", _where: "f_pin='\(self.dataPerson["f_pin"]!!)' or l_pin='\(self.dataPerson["f_pin"]!!)'")
-                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "l_pin='\(self.dataPerson["f_pin"]!!)'")
-                    let l_pin = self.dataPerson["f_pin"]!!
-                    SecureUserDefaults.shared.removeValue(forKey: "saved_\(l_pin)")
-                    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reloadTabChats"), object: nil, userInfo: nil)
-                    self.navigationController?.popViewController(animated: true)
+                    do {
+                        _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE", _where: "f_pin='\(self.dataPerson["f_pin"]!!)' or l_pin='\(self.dataPerson["f_pin"]!!)'")
+                        _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "l_pin='\(self.dataPerson["f_pin"]!!)'")
+                        let l_pin = self.dataPerson["f_pin"]!!
+                        SecureUserDefaults.shared.removeValue(forKey: "saved_\(l_pin)")
+                        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reloadTabChats"), object: nil, userInfo: nil)
+                        self.navigationController?.popViewController(animated: true)
+                    } catch {
+                        rollback.pointee = true
+                        print("Access database error: \(error.localizedDescription)")
+                    }
                 })
             }))
             self.present(alert, animated: true, completion: nil)
@@ -1035,9 +1065,14 @@ class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
         }
         DispatchQueue.global().async {
             Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                    "status" : "4"
-                ], _where: "message_id = '\(message_id)'")
+                do {
+                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                        "status" : "4"
+                    ], _where: "message_id = '\(message_id)'")
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
+                }
             })
             message.mStatus = CoreMessage_TMessageUtil.getTID()
             message.mBodies[CoreMessage_TMessageKey.L_PIN] = f_pin
@@ -1097,9 +1132,14 @@ class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
     private func updateCounter(counter: Int) {
         DispatchQueue.global().async {
             Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", cvalues: [
-                    "counter" : "\(counter)"
-                ], _where: "l_pin = '\(self.dataPerson["f_pin"]!!)'")
+                do {
+                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", cvalues: [
+                        "counter" : "\(counter)"
+                    ], _where: "l_pin = '\(self.dataPerson["f_pin"]!!)'")
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
+                }
             })
             NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reloadTabChats"), object: nil, userInfo: nil)
         }
@@ -2105,9 +2145,14 @@ extension ChatGPTBotView: UITableViewDelegate, UITableViewDataSource {
             let result = Nexilis.write(message: CoreMessage_TMessageBank.getAckLocationMessage(f_pin: dataMessages[indexPath.row]["f_pin"] as! String, message_id: dataMessages[indexPath.row]["message_id"] as! String, l_pin: dataMessages[indexPath.row]["l_pin"] as! String, server_date: "\(Date().currentTimeMillis())", message_scope_id: dataMessages[indexPath.row]["message_scope_id"] as! String, longitude: "", latitude: "", description: ""))
             if result != nil {
                 Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                        "status" : "8"
-                    ], _where: "message_id = '\(dataMessages[indexPath.row]["message_id"] as! String)'")
+                    do {
+                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                            "status" : "8"
+                        ], _where: "message_id = '\(dataMessages[indexPath.row]["message_id"] as! String)'")
+                    } catch {
+                        rollback.pointee = true
+                        print("Access database error: \(error.localizedDescription)")
+                    }
                 })
                 DispatchQueue.main.async {
                     if let index = self.dataMessages.firstIndex(where: {$0["message_id"] as? String == dataMessages[indexPath.row]["message_id"] as? String}) {

+ 316 - 221
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Chat/EditorGroup.swift

@@ -246,17 +246,22 @@ public class EditorGroup: UIViewController {
                 alert.addAction(UIAlertAction(title: "Delete".localized(), style: .destructive, handler: {(_) in
                     var l_pin = self.dataGroup["group_id"] as! String
                     Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                        if (self.dataTopic["chat_id"] as! String != "") {
-                            l_pin = self.dataTopic["chat_id"] as! String
-                        }
-                        _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE", _where: "(l_pin='\(self.dataGroup["group_id"]!!)' and chat_id='\(self.dataTopic["chat_id"]!!)') and message_scope_id='4'")
-                        _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "l_pin='\(l_pin)'")
-                        SecureUserDefaults.shared.removeValue(forKey: "saved_\(l_pin)")
-                        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reloadTabChats"), object: nil, userInfo: nil)
-                        if self.fromNotification {
-                            self.didTapExit()
-                        } else {
-                            self.navigationController?.popViewController(animated: true)
+                        do {
+                            if (self.dataTopic["chat_id"] as! String != "") {
+                                l_pin = self.dataTopic["chat_id"] as! String
+                            }
+                            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE", _where: "(l_pin='\(self.dataGroup["group_id"]!!)' and chat_id='\(self.dataTopic["chat_id"]!!)') and message_scope_id='4'")
+                            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "l_pin='\(l_pin)'")
+                            SecureUserDefaults.shared.removeValue(forKey: "saved_\(l_pin)")
+                            NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reloadTabChats"), object: nil, userInfo: nil)
+                            if self.fromNotification {
+                                self.didTapExit()
+                            } else {
+                                self.navigationController?.popViewController(animated: true)
+                            }
+                        } catch {
+                            rollback.pointee = true
+                            print("Access database error: \(error.localizedDescription)")
                         }
                     })
                 }))
@@ -293,15 +298,20 @@ public class EditorGroup: UIViewController {
     private func getOfficialGroup() {
         let query = "SELECT group_id, f_name, official, image_id FROM GROUPZ where group_type = 1 AND official = 1"
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: query) {
-                if cursorData.next() {
-                    dataGroup["group_id"] = cursorData.string(forColumnIndex: 0)
-                    dataTopic["chat_id"] = ""
-                    dataGroup["f_name"] = cursorData.string(forColumnIndex: 1)
-                    dataGroup["image_id"] = cursorData.string(forColumnIndex: 3)
-                    dataGroup["official"] = cursorData.string(forColumnIndex: 2)
+            do {
+                if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: query) {
+                    if cursorData.next() {
+                        dataGroup["group_id"] = cursorData.string(forColumnIndex: 0)
+                        dataTopic["chat_id"] = ""
+                        dataGroup["f_name"] = cursorData.string(forColumnIndex: 1)
+                        dataGroup["image_id"] = cursorData.string(forColumnIndex: 3)
+                        dataGroup["official"] = cursorData.string(forColumnIndex: 2)
+                    }
+                    cursorData.close()
                 }
-                cursorData.close()
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
     }
@@ -444,9 +454,14 @@ public class EditorGroup: UIViewController {
                             }
                             DispatchQueue.global().async {
                                 Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                                        "lock" : "2"
-                                    ], _where: "message_id = '\(data.key)'")
+                                    do {
+                                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                                            "lock" : "2"
+                                        ], _where: "message_id = '\(data.key)'")
+                                    } catch {
+                                        rollback.pointee = true
+                                        print("Access database error: \(error.localizedDescription)")
+                                    }
                                 })
                             }
                         }
@@ -484,96 +499,88 @@ public class EditorGroup: UIViewController {
     
     private func getDataGroup(unique_l_pin: String) {
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            if let cursorGroup = Database.shared.getRecords(fmdb: fmdb, query: "SELECT group_id, f_name, image_id, official, parent FROM GROUPZ WHERE group_id='\(unique_l_pin)'"), cursorGroup.next() {
-                dataGroup["group_id"] = cursorGroup.string(forColumnIndex: 0)
-                dataGroup["f_name"] = cursorGroup.string(forColumnIndex: 1)
-                dataGroup["image_id"] = cursorGroup.string(forColumnIndex: 2)
-                dataGroup["official"] = cursorGroup.string(forColumnIndex: 3)
-                dataGroup["parent"] = cursorGroup.string(forColumnIndex: 4)
-                dataTopic["title"] = "Lounge".localized()
-                dataTopic["chat_id"] = ""
-                cursorGroup.close()
-            } else if let cursorTopic = Database.shared.getRecords(fmdb: fmdb, query: "SELECT group_id, title FROM DISCUSSION_FORUM where chat_id = '\(unique_l_pin)'"), cursorTopic.next() {
-                dataGroup["group_id"] = cursorTopic.string(forColumnIndex: 0)
-                dataTopic["title"] = cursorTopic.string(forColumnIndex: 1)
-                dataTopic["chat_id"] = unique_l_pin
-                cursorTopic.close()
-                if let cursorGroup = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_name, image_id, official, parent FROM GROUPZ where group_id = '\(dataGroup["group_id"] as! String)'"), cursorGroup.next() {
-                    dataGroup["f_name"] = cursorGroup.string(forColumnIndex: 0)
-                    dataGroup["image_id"] = cursorGroup.string(forColumnIndex: 1)
-                    dataGroup["official"] = cursorGroup.string(forColumnIndex: 2)
-                    dataGroup["parent"] = cursorGroup.string(forColumnIndex: 3)
+            do {
+                if let cursorGroup = Database.shared.getRecords(fmdb: fmdb, query: "SELECT group_id, f_name, image_id, official, parent FROM GROUPZ WHERE group_id='\(unique_l_pin)'"), cursorGroup.next() {
+                    dataGroup["group_id"] = cursorGroup.string(forColumnIndex: 0)
+                    dataGroup["f_name"] = cursorGroup.string(forColumnIndex: 1)
+                    dataGroup["image_id"] = cursorGroup.string(forColumnIndex: 2)
+                    dataGroup["official"] = cursorGroup.string(forColumnIndex: 3)
+                    dataGroup["parent"] = cursorGroup.string(forColumnIndex: 4)
+                    dataTopic["title"] = "Lounge".localized()
+                    dataTopic["chat_id"] = ""
                     cursorGroup.close()
+                } else if let cursorTopic = Database.shared.getRecords(fmdb: fmdb, query: "SELECT group_id, title FROM DISCUSSION_FORUM where chat_id = '\(unique_l_pin)'"), cursorTopic.next() {
+                    dataGroup["group_id"] = cursorTopic.string(forColumnIndex: 0)
+                    dataTopic["title"] = cursorTopic.string(forColumnIndex: 1)
+                    dataTopic["chat_id"] = unique_l_pin
+                    cursorTopic.close()
+                    if let cursorGroup = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_name, image_id, official, parent FROM GROUPZ where group_id = '\(dataGroup["group_id"] as! String)'"), cursorGroup.next() {
+                        dataGroup["f_name"] = cursorGroup.string(forColumnIndex: 0)
+                        dataGroup["image_id"] = cursorGroup.string(forColumnIndex: 1)
+                        dataGroup["official"] = cursorGroup.string(forColumnIndex: 2)
+                        dataGroup["parent"] = cursorGroup.string(forColumnIndex: 3)
+                        cursorGroup.close()
+                    }
                 }
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
     }
     
     private func getData() {
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            var query = "SELECT message_id, f_pin, l_pin, message_scope_id, server_date, status, message_text, audio_id, video_id, image_id, thumb_id, read_receipts, chat_id, file_id, attachment_flag, reff_id, lock, is_stared, blog_id, credential, is_call_center, call_center_id, opposite_pin FROM MESSAGE where chat_id='' AND l_pin='\(dataGroup["group_id"] as! String)' order by server_date asc"
-            if isHistoryCC {
-                query = "SELECT message_id, f_pin, l_pin, message_scope_id, server_date, status, message_text, audio_id, video_id, image_id, thumb_id, read_receipts, chat_id, file_id, attachment_flag, reff_id, lock, is_stared FROM MESSAGE where call_center_id='\(complaintId)' order by server_date asc"
-            } else if (dataTopic["chat_id"] as! String != "") {
-                query = "SELECT message_id, f_pin, l_pin, message_scope_id, server_date, status, message_text, audio_id, video_id, image_id, thumb_id, read_receipts, chat_id, file_id, attachment_flag, reff_id, lock, is_stared FROM MESSAGE where chat_id='\(dataTopic["chat_id"] as! String)' order by server_date asc"
-            }
-            if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: query) {
-                var tempImages: [ImageGrouping] = []
-                while cursorData.next() {
-                    var row: [String: Any?] = [:]
-                    row["message_id"] = cursorData.string(forColumnIndex: 0)
-                    row["f_pin"] = cursorData.string(forColumnIndex: 1)
-                    row["l_pin"] = cursorData.string(forColumnIndex: 2)
-                    row["message_scope_id"] = cursorData.string(forColumnIndex: 3)
-                    row["server_date"] = cursorData.string(forColumnIndex: 4)
-                    row["status"] = cursorData.string(forColumnIndex: 5)
-                    row["message_text"] = cursorData.string(forColumnIndex: 6)
-                    row["audio_id"] = cursorData.string(forColumnIndex: 7)
-                    row["video_id"] = cursorData.string(forColumnIndex: 8)
-                    row["image_id"] = cursorData.string(forColumnIndex: 9)
-                    row["thumb_id"] = cursorData.string(forColumnIndex: 10)
-                    row["read_receipts"] = cursorData.string(forColumnIndex: 11)
-                    row["chat_id"] = cursorData.string(forColumnIndex: 12)
-                    row["file_id"] = cursorData.string(forColumnIndex: 13)
-                    row["attachment_flag"] = cursorData.string(forColumnIndex: 14)
-                    row["reff_id"] = cursorData.string(forColumnIndex: 15)
-                    row["lock"] = cursorData.string(forColumnIndex: 16)
-                    row["is_stared"] = cursorData.string(forColumnIndex: 17)
-                    row["blog_id"] = cursorData.string(forColumnIndex: 18)
-                    row["credential"] = cursorData.string(forColumnIndex: 19)
-                    row["isSelected"] = false
-                    if row["credential"] != nil && row["credential"] as! String == "1" {
-                        let idMe = User.getMyPin()!
-                        if row["f_pin"] as! String == idMe {
-                            let second = getSecondsDifferenceFromTwoDates(start: Date.init(milliseconds: Int64(row["server_date"] as! String)!), end: Date())
-                            if second > 60 {
-                                listTimerCredential[row["message_id"] as! String] = 0
-                                row["lock"] = "2"
-                                row["reff_id"] = ""
-                                DispatchQueue.global().async {
-                                    Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                                            "lock" : "2"
-                                        ], _where: "message_id = '\(row["message_id"] as! String)'")
-                                    })
-                                }
-                            } else {
-                                let second = 60 - second
-                                listTimerCredential[row["message_id"] as! String] = second
-                            }
-                        } else {
-                            let hasMessageId: String? = SecureUserDefaults.shared.value(forKey: row["message_id"] as! String) ?? nil
-                            if hasMessageId != nil {
-                                let second = getSecondsDifferenceFromTwoDates(start: Date.init(milliseconds: Int64(hasMessageId!)!), end: Date())
+            do {
+                var query = "SELECT message_id, f_pin, l_pin, message_scope_id, server_date, status, message_text, audio_id, video_id, image_id, thumb_id, read_receipts, chat_id, file_id, attachment_flag, reff_id, lock, is_stared, blog_id, credential, is_call_center, call_center_id, opposite_pin FROM MESSAGE where chat_id='' AND l_pin='\(dataGroup["group_id"] as! String)' order by server_date asc"
+                if isHistoryCC {
+                    query = "SELECT message_id, f_pin, l_pin, message_scope_id, server_date, status, message_text, audio_id, video_id, image_id, thumb_id, read_receipts, chat_id, file_id, attachment_flag, reff_id, lock, is_stared FROM MESSAGE where call_center_id='\(complaintId)' order by server_date asc"
+                } else if (dataTopic["chat_id"] as! String != "") {
+                    query = "SELECT message_id, f_pin, l_pin, message_scope_id, server_date, status, message_text, audio_id, video_id, image_id, thumb_id, read_receipts, chat_id, file_id, attachment_flag, reff_id, lock, is_stared FROM MESSAGE where chat_id='\(dataTopic["chat_id"] as! String)' order by server_date asc"
+                }
+                if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: query) {
+                    var tempImages: [ImageGrouping] = []
+                    while cursorData.next() {
+                        var row: [String: Any?] = [:]
+                        row["message_id"] = cursorData.string(forColumnIndex: 0)
+                        row["f_pin"] = cursorData.string(forColumnIndex: 1)
+                        row["l_pin"] = cursorData.string(forColumnIndex: 2)
+                        row["message_scope_id"] = cursorData.string(forColumnIndex: 3)
+                        row["server_date"] = cursorData.string(forColumnIndex: 4)
+                        row["status"] = cursorData.string(forColumnIndex: 5)
+                        row["message_text"] = cursorData.string(forColumnIndex: 6)
+                        row["audio_id"] = cursorData.string(forColumnIndex: 7)
+                        row["video_id"] = cursorData.string(forColumnIndex: 8)
+                        row["image_id"] = cursorData.string(forColumnIndex: 9)
+                        row["thumb_id"] = cursorData.string(forColumnIndex: 10)
+                        row["read_receipts"] = cursorData.string(forColumnIndex: 11)
+                        row["chat_id"] = cursorData.string(forColumnIndex: 12)
+                        row["file_id"] = cursorData.string(forColumnIndex: 13)
+                        row["attachment_flag"] = cursorData.string(forColumnIndex: 14)
+                        row["reff_id"] = cursorData.string(forColumnIndex: 15)
+                        row["lock"] = cursorData.string(forColumnIndex: 16)
+                        row["is_stared"] = cursorData.string(forColumnIndex: 17)
+                        row["blog_id"] = cursorData.string(forColumnIndex: 18)
+                        row["credential"] = cursorData.string(forColumnIndex: 19)
+                        row["isSelected"] = false
+                        if row["credential"] != nil && row["credential"] as! String == "1" {
+                            let idMe = User.getMyPin()!
+                            if row["f_pin"] as! String == idMe {
+                                let second = getSecondsDifferenceFromTwoDates(start: Date.init(milliseconds: Int64(row["server_date"] as! String)!), end: Date())
                                 if second > 60 {
                                     listTimerCredential[row["message_id"] as! String] = 0
                                     row["lock"] = "2"
                                     row["reff_id"] = ""
                                     DispatchQueue.global().async {
                                         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                                                "lock" : "2"
-                                            ], _where: "message_id = '\(row["message_id"] as! String)'")
+                                            do {
+                                                _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                                                    "lock" : "2"
+                                                ], _where: "message_id = '\(row["message_id"] as! String)'")
+                                            } catch {
+                                                rollback.pointee = true
+                                                print("Access database error: \(error.localizedDescription)")
+                                            }
                                         })
                                     }
                                 } else {
@@ -581,77 +588,105 @@ public class EditorGroup: UIViewController {
                                     listTimerCredential[row["message_id"] as! String] = second
                                 }
                             } else {
-                                SecureUserDefaults.shared.set("\(Date().currentTimeMillis())", forKey: row["message_id"] as! String)
-                                listTimerCredential[row["message_id"] as! String] = 60
+                                let hasMessageId: String? = SecureUserDefaults.shared.value(forKey: row["message_id"] as! String) ?? nil
+                                if hasMessageId != nil {
+                                    let second = getSecondsDifferenceFromTwoDates(start: Date.init(milliseconds: Int64(hasMessageId!)!), end: Date())
+                                    if second > 60 {
+                                        listTimerCredential[row["message_id"] as! String] = 0
+                                        row["lock"] = "2"
+                                        row["reff_id"] = ""
+                                        DispatchQueue.global().async {
+                                            Database.shared.database?.inTransaction({ (fmdb, rollback) in
+                                                do {
+                                                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                                                        "lock" : "2"
+                                                    ], _where: "message_id = '\(row["message_id"] as! String)'")
+                                                } catch {
+                                                    rollback.pointee = true
+                                                    print("Access database error: \(error.localizedDescription)")
+                                                }
+                                            })
+                                        }
+                                    } else {
+                                        let second = 60 - second
+                                        listTimerCredential[row["message_id"] as! String] = second
+                                    }
+                                } else {
+                                    SecureUserDefaults.shared.set("\(Date().currentTimeMillis())", forKey: row["message_id"] as! String)
+                                    listTimerCredential[row["message_id"] as! String] = 60
+                                }
                             }
                         }
-                    }
-                    row[TypeDataMessage.is_call_center] = cursorData.string(forColumnIndex: 20)
-                    row[TypeDataMessage.call_center_id] = cursorData.string(forColumnIndex: 21)
-                    row[TypeDataMessage.opposite_pin] = cursorData.string(forColumnIndex: 22)
-                    let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
-                    let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
-                    let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
-                    if let dirPath = paths.first {
-                        let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["video_id"] as! String)
-                        let fileURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["file_id"] as! String)
-                        if ((row["video_id"] as! String) != "") {
-                            if FileManager.default.fileExists(atPath: videoURL.path){
-                                row["progress"] = 100.0
-                            } else {
-                                row["progress"] = 0.0
-                            }
-                        } else {
-                            if FileManager.default.fileExists(atPath: fileURL.path){
-                                row["progress"] = 100.0
+                        row[TypeDataMessage.is_call_center] = cursorData.string(forColumnIndex: 20)
+                        row[TypeDataMessage.call_center_id] = cursorData.string(forColumnIndex: 21)
+                        row[TypeDataMessage.opposite_pin] = cursorData.string(forColumnIndex: 22)
+                        let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
+                        let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
+                        let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
+                        if let dirPath = paths.first {
+                            let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["video_id"] as! String)
+                            let fileURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["file_id"] as! String)
+                            if ((row["video_id"] as! String) != "") {
+                                if FileManager.default.fileExists(atPath: videoURL.path){
+                                    row["progress"] = 100.0
+                                } else {
+                                    row["progress"] = 0.0
+                                }
                             } else {
-                                row["progress"] = 0.0
+                                if FileManager.default.fileExists(atPath: fileURL.path){
+                                    row["progress"] = 100.0
+                                } else {
+                                    row["progress"] = 0.0
+                                }
                             }
                         }
-                    }
-                    row["chat_date"] = chatDate(stringDate: row["server_date"] as! String)
-                    
-                    if (dataMessages.count == 0 || dataMessages.last!["f_pin"] as! String == row["f_pin"] as! String) && tempImages.count <= 30 && row["image_id"] != nil && !(row["image_id"] as! String).isEmpty && (row["message_text"] as! String).isEmpty && (row["reff_id"] as! String).isEmpty && (row["read_receipts"] as! String) != "8" {
-                        if tempImages.count != 0 && getSecondsDifferenceFromTwoDates(start: Date.init(milliseconds: Int64(tempImages.last!.time)!), end: Date.init(milliseconds: Int64(row["server_date"] as! String)!))/60 >= 11 {
-                            if tempImages.count >= 4 {
-                                groupImages[tempImages[0].messageId] = tempImages
-                                if let idxTemp = dataMessages.firstIndex(where: { $0["message_id"] as! String == tempImages[0].messageId }) {
-                                    for _ in 1..<tempImages.count {
-                                        dataMessages.remove(at: idxTemp + 1)
+                        row["chat_date"] = chatDate(stringDate: row["server_date"] as! String)
+                        
+                        if (dataMessages.count == 0 || dataMessages.last!["f_pin"] as! String == row["f_pin"] as! String) && tempImages.count <= 30 && row["image_id"] != nil && !(row["image_id"] as! String).isEmpty && (row["message_text"] as! String).isEmpty && (row["reff_id"] as! String).isEmpty && (row["read_receipts"] as! String) != "8" {
+                            if tempImages.count != 0 && getSecondsDifferenceFromTwoDates(start: Date.init(milliseconds: Int64(tempImages.last!.time)!), end: Date.init(milliseconds: Int64(row["server_date"] as! String)!))/60 >= 11 {
+                                if tempImages.count >= 4 {
+                                    groupImages[tempImages[0].messageId] = tempImages
+                                    if let idxTemp = dataMessages.firstIndex(where: { $0["message_id"] as! String == tempImages[0].messageId }) {
+                                        for _ in 1..<tempImages.count {
+                                            dataMessages.remove(at: idxTemp + 1)
+                                        }
                                     }
                                 }
+                                tempImages.removeAll()
+                            }
+                            tempImages.append(ImageGrouping(messageId: row["message_id"] as! String, thumbId: row["thumb_id"] as! String, imageId: row["image_id"] as! String, status: row["status"] as! String, time: row["server_date"] as! String, lPin: row["l_pin"] as! String, dataMessage: row, dataPerson: [:], dataGroup: dataGroup, dataTopic: dataTopic))
+                        } else if tempImages.count >= 4 {
+                            groupImages[tempImages[0].messageId] = tempImages
+                            if let idxTemp = dataMessages.firstIndex(where: { $0["message_id"] as! String == tempImages[0].messageId }) {
+                                for _ in 1..<tempImages.count {
+                                    dataMessages.remove(at: idxTemp + 1)
+                                }
                             }
                             tempImages.removeAll()
+                        } else if tempImages.count != 0 {
+                            tempImages.removeAll()
+                        }
+                        dataMessages.append(row)
+                    }
+    //                if isHistoryCC {
+    //                    dataMessages.remove(at: 0)
+    //                }
+                    if tempImages.count >= 4 {
+                        if tempImages.count > 30 {
+                            tempImages.removeSubrange(30..<tempImages.count)
                         }
-                        tempImages.append(ImageGrouping(messageId: row["message_id"] as! String, thumbId: row["thumb_id"] as! String, imageId: row["image_id"] as! String, status: row["status"] as! String, time: row["server_date"] as! String, lPin: row["l_pin"] as! String, dataMessage: row, dataPerson: [:], dataGroup: dataGroup, dataTopic: dataTopic))
-                    } else if tempImages.count >= 4 {
                         groupImages[tempImages[0].messageId] = tempImages
                         if let idxTemp = dataMessages.firstIndex(where: { $0["message_id"] as! String == tempImages[0].messageId }) {
                             for _ in 1..<tempImages.count {
                                 dataMessages.remove(at: idxTemp + 1)
                             }
                         }
-                        tempImages.removeAll()
-                    } else if tempImages.count != 0 {
-                        tempImages.removeAll()
-                    }
-                    dataMessages.append(row)
-                }
-//                if isHistoryCC {
-//                    dataMessages.remove(at: 0)
-//                }
-                if tempImages.count >= 4 {
-                    if tempImages.count > 30 {
-                        tempImages.removeSubrange(30..<tempImages.count)
-                    }
-                    groupImages[tempImages[0].messageId] = tempImages
-                    if let idxTemp = dataMessages.firstIndex(where: { $0["message_id"] as! String == tempImages[0].messageId }) {
-                        for _ in 1..<tempImages.count {
-                            dataMessages.remove(at: idxTemp + 1)
-                        }
                     }
+                    cursorData.close()
                 }
-                cursorData.close()
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
     }
@@ -667,13 +702,18 @@ public class EditorGroup: UIViewController {
     private func getRealStatus(messageId: String) -> String {
         var status = "1"
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            if let cursorStatus = Database.shared.getRecords(fmdb: fmdb, query: "SELECT status, f_pin FROM MESSAGE_STATUS WHERE message_id='\(messageId)'") {
-                var listStatus: [Int] = []
-                while cursorStatus.next() {
-                    listStatus.append(Int(cursorStatus.string(forColumnIndex: 0)!)!)
+            do {
+                if let cursorStatus = Database.shared.getRecords(fmdb: fmdb, query: "SELECT status, f_pin FROM MESSAGE_STATUS WHERE message_id='\(messageId)'") {
+                    var listStatus: [Int] = []
+                    while cursorStatus.next() {
+                        listStatus.append(Int(cursorStatus.string(forColumnIndex: 0)!)!)
+                    }
+                    cursorStatus.close()
+                    status = "\(listStatus.min() ?? 2)"
                 }
-                cursorStatus.close()
-                status = "\(listStatus.min() ?? 2)"
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         return status
@@ -983,9 +1023,14 @@ public class EditorGroup: UIViewController {
                                 }
                                 DispatchQueue.global().async {
                                     Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                                            "lock" : "2"
-                                        ], _where: "message_id = '\(row["message_id"] as! String)'")
+                                        do {
+                                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                                                "lock" : "2"
+                                            ], _where: "message_id = '\(row["message_id"] as! String)'")
+                                        } catch {
+                                            rollback.pointee = true
+                                            print("Access database error: \(error.localizedDescription)")
+                                        }
                                     })
                                 }
                             }
@@ -1668,9 +1713,14 @@ public class EditorGroup: UIViewController {
                     }
                     DispatchQueue.global().async {
                         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                                "lock" : "2"
-                            ], _where: "message_id = '\(messageId)'")
+                            do {
+                                _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                                    "lock" : "2"
+                                ], _where: "message_id = '\(messageId)'")
+                            } catch {
+                                rollback.pointee = true
+                                print("Access database error: \(error.localizedDescription)")
+                            }
                         })
                     }
                 }
@@ -1733,13 +1783,18 @@ public class EditorGroup: UIViewController {
     private func updateCounter(counter: Int) {
         DispatchQueue.global().async {
             Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                var l_pin = self.dataGroup["group_id"]!!
-                if (self.dataTopic["chat_id"] as! String != "") {
-                    l_pin = self.dataTopic["chat_id"] as! String
+                do {
+                    var l_pin = self.dataGroup["group_id"]!!
+                    if (self.dataTopic["chat_id"] as! String != "") {
+                        l_pin = self.dataTopic["chat_id"] as! String
+                    }
+                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", cvalues: [
+                        "counter" : "\(counter)"
+                    ], _where: "l_pin = '\(l_pin)'")
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
                 }
-                _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", cvalues: [
-                    "counter" : "\(counter)"
-                ], _where: "l_pin = '\(l_pin)'")
             })
             NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reloadTabChats"), object: nil, userInfo: nil)
         }
@@ -1843,9 +1898,14 @@ public class EditorGroup: UIViewController {
         }
         DispatchQueue.global().async {
             Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                    "status" : "4"
-                ], _where: "message_id = '\(message_id)'")
+                do {
+                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                        "status" : "4"
+                    ], _where: "message_id = '\(message_id)'")
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
+                }
             })
             message.mStatus = CoreMessage_TMessageUtil.getTID()
             message.mBodies[CoreMessage_TMessageKey.L_PIN] = f_pin
@@ -2216,34 +2276,39 @@ extension EditorGroup: UITextViewDelegate {
         }
         listMentionWithText.removeAll()
         Database.shared.database?.inTransaction({ fmdb, rollback in
-            let idMe = User.getMyPin()!
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_pin, first_name || ' ' || ifnull(last_name, '') name FROM GROUPZ_MEMBER where group_id='\(self.dataGroup["group_id"] as! String)' AND f_pin <> '\(idMe)' AND name LIKE '%\(text)%'") {
-                while cursor.next() {
-                    let user = User(pin: "")
-                    user.pin = cursor.string(forColumnIndex: 0) ?? ""
-                    user.firstName = cursor.string(forColumnIndex: 1) ?? ""
-                    if !user.pin.isEmpty {
-                        let userFromBuddy = User.getDataCanNil(pin: user.pin, fmdb: fmdb)
-                        if userFromBuddy != nil {
-                            listMentionWithText.append(userFromBuddy!)
-                        } else {
-                            listMentionWithText.append(user)
+            do {
+                let idMe = User.getMyPin()!
+                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_pin, first_name || ' ' || ifnull(last_name, '') name FROM GROUPZ_MEMBER where group_id='\(self.dataGroup["group_id"] as! String)' AND f_pin <> '\(idMe)' AND name LIKE '%\(text)%'") {
+                    while cursor.next() {
+                        let user = User(pin: "")
+                        user.pin = cursor.string(forColumnIndex: 0) ?? ""
+                        user.firstName = cursor.string(forColumnIndex: 1) ?? ""
+                        if !user.pin.isEmpty {
+                            let userFromBuddy = User.getDataCanNil(pin: user.pin, fmdb: fmdb)
+                            if userFromBuddy != nil {
+                                listMentionWithText.append(userFromBuddy!)
+                            } else {
+                                listMentionWithText.append(user)
+                            }
                         }
                     }
+                    cursor.close()
                 }
-                cursor.close()
-            }
-            listMentionWithText.removeAll(where: { listMentionInTextField.contains($0) })
-            if listMentionWithText.count > 0 {
-                if listMentionWithText.count < 5 {
-                    self.heightTableMention.constant = CGFloat(44 * listMentionWithText.count)
+                listMentionWithText.removeAll(where: { listMentionInTextField.contains($0) })
+                if listMentionWithText.count > 0 {
+                    if listMentionWithText.count < 5 {
+                        self.heightTableMention.constant = CGFloat(44 * listMentionWithText.count)
+                    } else {
+                        self.heightTableMention.constant = 44 * 4
+                    }
+                    tableMention.reloadData()
                 } else {
-                    self.heightTableMention.constant = 44 * 4
+                    self.heightTableMention.constant = 44
+                    self.hideMention()
                 }
-                tableMention.reloadData()
-            } else {
-                self.heightTableMention.constant = 44
-                self.hideMention()
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
     }
@@ -2276,13 +2341,18 @@ extension EditorGroup: UITextViewDelegate {
                 }
                 var dataURL = ""
                 Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                    if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select data_link from LINK_PREVIEW where link='\(text)'") {
-                        while cursor.next() {
-                            if let data = cursor.string(forColumnIndex: 0) {
-                                dataURL = data
+                    do {
+                        if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select data_link from LINK_PREVIEW where link='\(text)'") {
+                            while cursor.next() {
+                                if let data = cursor.string(forColumnIndex: 0) {
+                                    dataURL = data
+                                }
                             }
+                            cursor.close()
                         }
-                        cursor.close()
+                    } catch {
+                        rollback.pointee = true
+                        print("Access database error: \(error.localizedDescription)")
                     }
                 })
                 if !dataURL.isEmpty {
@@ -2328,7 +2398,7 @@ extension EditorGroup: UITextViewDelegate {
                                 ], replace: true)
                             } catch {
                                 rollback.pointee = true
-                                //print(error)
+                                print("Access database error: \(error.localizedDescription)")
                             }
                         })
                         if self.showingLink != text {
@@ -2535,9 +2605,14 @@ extension EditorGroup: UIContextMenuInteractionDelegate {
                 }
                 DispatchQueue.global().async {
                     Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                            "is_stared" : 1
-                        ], _where: "message_id = '\(dataMessages[indexPath!.row]["message_id"] as! String)'")
+                        do {
+                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                                "is_stared" : 1
+                            ], _where: "message_id = '\(dataMessages[indexPath!.row]["message_id"] as! String)'")
+                        } catch {
+                            rollback.pointee = true
+                            print("Access database error: \(error.localizedDescription)")
+                        }
                     })
                 }
                 let idx = self.dataMessages.firstIndex(where: { $0["message_id"] as! String == dataMessages[indexPath!.row]["message_id"] as! String})
@@ -2553,9 +2628,14 @@ extension EditorGroup: UIContextMenuInteractionDelegate {
                 }
                 DispatchQueue.global().async {
                     Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                            "is_stared" : 0
-                        ], _where: "message_id = '\(dataMessages[indexPath!.row]["message_id"] as! String)'")
+                        do {
+                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                                "is_stared" : 0
+                            ], _where: "message_id = '\(dataMessages[indexPath!.row]["message_id"] as! String)'")
+                        } catch {
+                            rollback.pointee = true
+                            print("Access database error: \(error.localizedDescription)")
+                        }
                     })
                 }
                 let idx = self.dataMessages.firstIndex(where: { $0["message_id"] as! String == dataMessages[indexPath!.row]["message_id"] as! String})
@@ -2692,12 +2772,17 @@ extension EditorGroup: UIContextMenuInteractionDelegate {
                 }
             }
             Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                    "status" : "1"
-                ], _where: "message_id = '\(messageId)'")
-                _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
-                    "status" : "1"
-                ], _where: "message_id = '\(messageId)'")
+                do {
+                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                        "status" : "1"
+                    ], _where: "message_id = '\(messageId)'")
+                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
+                        "status" : "1"
+                    ], _where: "message_id = '\(messageId)'")
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
+                }
             })
             let message = CoreMessage_TMessageBank.sendMessage(message_id: messageId,
                                                                l_pin: dataMessages[indexPath!.row][TypeDataMessage.l_pin] as! String,
@@ -4493,11 +4578,16 @@ extension EditorGroup: UITableViewDelegate, UITableViewDataSource {
                 }
                 var dataURL = ""
                 Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                    if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select data_link from LINK_PREVIEW where link='\(text)'"), cursor.next() {
-                        if let data = cursor.string(forColumnIndex: 0) {
-                            dataURL = data
+                    do {
+                        if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select data_link from LINK_PREVIEW where link='\(text)'"), cursor.next() {
+                            if let data = cursor.string(forColumnIndex: 0) {
+                                dataURL = data
+                            }
+                            cursor.close()
                         }
-                        cursor.close()
+                    } catch {
+                        rollback.pointee = true
+                        print("Access database error: \(error.localizedDescription)")
                     }
                 })
                 if dataURL.isEmpty {
@@ -4536,7 +4626,7 @@ extension EditorGroup: UITableViewDelegate, UITableViewDataSource {
                                 }
                             } catch {
                                 rollback.pointee = true
-                                //print(error)
+                                print("Access database error: \(error.localizedDescription)")
                             }
                         })
                     }, onError: { error in
@@ -4836,9 +4926,14 @@ extension EditorGroup: UITableViewDelegate, UITableViewDataSource {
             let result = Nexilis.write(message: CoreMessage_TMessageBank.getAckLocationMessage(f_pin: dataMessages[indexPath.row]["f_pin"] as! String, message_id: dataMessages[indexPath.row]["message_id"] as! String, l_pin: opposite_pin, server_date: "\(Date().currentTimeMillis())", message_scope_id: dataMessages[indexPath.row]["message_scope_id"] as! String, longitude: "", latitude: "", description: ""))
             if result != nil {
                 Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                        "status" : "8"
-                    ], _where: "message_id = '\(dataMessages[indexPath.row]["message_id"] as! String)'")
+                    do {
+                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                            "status" : "8"
+                        ], _where: "message_id = '\(dataMessages[indexPath.row]["message_id"] as! String)'")
+                    } catch {
+                        rollback.pointee = true
+                        print("Access database error: \(error.localizedDescription)")
+                    }
                 })
                 DispatchQueue.main.async {
                     if let index = self.dataMessages.firstIndex(where: {$0["message_id"] as? String == dataMessages[indexPath.row]["message_id"] as? String}) {

+ 396 - 281
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Chat/EditorPersonal.swift

@@ -238,10 +238,15 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
         if isContactCenter && !isRequestContactCenter && !onGoingCC {
             var companyName = ""
             Database.shared.database?.inTransaction({ fmdb, rollback in
-                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT first_name, last_name FROM BUDDY where official_account = '1'"), cursor.next() {
-                    companyName = cursor.string(forColumnIndex: 0)! + " " + cursor.string(forColumnIndex: 1)!
-                    companyName = companyName.trimmingCharacters(in: .whitespaces)
-                    cursor.close()
+                do {
+                    if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT first_name, last_name FROM BUDDY where official_account = '1'"), cursor.next() {
+                        companyName = cursor.string(forColumnIndex: 0)! + " " + cursor.string(forColumnIndex: 1)!
+                        companyName = companyName.trimmingCharacters(in: .whitespaces)
+                        cursor.close()
+                    }
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
                 }
             })
             self.dateStartCC = "\(Date().currentTimeMillis())"
@@ -298,15 +303,20 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                 alert.addAction(UIAlertAction(title: "Cancel".localized(), style: UIAlertAction.Style.default, handler: nil))
                 alert.addAction(UIAlertAction(title: "Delete".localized(), style: .destructive, handler: {(_) in
                     Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                        _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE", _where: "(f_pin='\(self.dataPerson["f_pin"]!!)' or l_pin='\(self.dataPerson["f_pin"]!!)') and (message_scope_id='3' or message_scope_id='18') and is_call_center = 0")
-                        _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "l_pin='\(self.dataPerson["f_pin"]!!)'")
-                        let l_pin = self.dataPerson["f_pin"]!!
-                        SecureUserDefaults.shared.removeValue(forKey: "saved_\(l_pin)")
-                        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reloadTabChats"), object: nil, userInfo: nil)
-                        if self.fromNotification {
-                            self.didTapExit()
-                        } else {
-                            self.navigationController?.popViewController(animated: true)
+                        do {
+                            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE", _where: "(f_pin='\(self.dataPerson["f_pin"]!!)' or l_pin='\(self.dataPerson["f_pin"]!!)') and (message_scope_id='3' or message_scope_id='18') and is_call_center = 0")
+                            _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "l_pin='\(self.dataPerson["f_pin"]!!)'")
+                            let l_pin = self.dataPerson["f_pin"]!!
+                            SecureUserDefaults.shared.removeValue(forKey: "saved_\(l_pin)")
+                            NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reloadTabChats"), object: nil, userInfo: nil)
+                            if self.fromNotification {
+                                self.didTapExit()
+                            } else {
+                                self.navigationController?.popViewController(animated: true)
+                            }
+                        } catch {
+                            rollback.pointee = true
+                            print("Access database error: \(error.localizedDescription)")
                         }
                     })
                 }))
@@ -346,9 +356,14 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                         } else {
                             DispatchQueue.main.async { [self] in
                                 Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
-                                        "ex_block" : "0"
-                                    ], _where: "f_pin = '\(self.dataPerson["f_pin"]!!)'")
+                                    do {
+                                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
+                                            "ex_block" : "0"
+                                        ], _where: "f_pin = '\(self.dataPerson["f_pin"]!!)'")
+                                    } catch {
+                                        rollback.pointee = true
+                                        print("Access database error: \(error.localizedDescription)")
+                                    }
                                 })
                                 containerAction.subviews.forEach({ $0.removeFromSuperview() })
                                 containerAction.removeFromSuperview()
@@ -381,9 +396,14 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                         } else {
                             DispatchQueue.main.async { [self] in
                                 Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
-                                        "ex_block" : "1"
-                                    ], _where: "f_pin = '\(self.dataPerson["f_pin"]!!)'")
+                                    do {
+                                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
+                                            "ex_block" : "1"
+                                        ], _where: "f_pin = '\(self.dataPerson["f_pin"]!!)'")
+                                    } catch {
+                                        rollback.pointee = true
+                                        print("Access database error: \(error.localizedDescription)")
+                                    }
                                 })
                                 setRightButtonItem()
                                 changeAppBar()
@@ -586,9 +606,14 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                             }
                             DispatchQueue.global().async {
                                 Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                                        "lock" : "2"
-                                    ], _where: "message_id = '\(data.key)'")
+                                    do {
+                                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                                            "lock" : "2"
+                                        ], _where: "message_id = '\(data.key)'")
+                                    } catch {
+                                        rollback.pointee = true
+                                        print("Access database error: \(error.localizedDescription)")
+                                    }
                                 })
                             }
                         }
@@ -780,27 +805,32 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
             query = "SELECT group_id, f_name, official, image_id FROM GROUPZ where group_type = 1 AND official = 1"
         }
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: query) {
-                if cursorData.next() {
-                    dataPerson["f_pin"] = cursorData.string(forColumnIndex: 0)
-                    dataPerson["name"] = cursorData.string(forColumnIndex: 1)?.trimmingCharacters(in: .whitespaces)
-                    dataPerson["picture"] = cursorData.string(forColumnIndex: 3)
-                    dataPerson["isOfficial"] = cursorData.string(forColumnIndex: 2)
-                    if isContactCenter && isRequestContactCenter {
-                        dataPerson["user_type"] = "0"
+            do {
+                if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: query) {
+                    if cursorData.next() {
+                        dataPerson["f_pin"] = cursorData.string(forColumnIndex: 0)
+                        dataPerson["name"] = cursorData.string(forColumnIndex: 1)?.trimmingCharacters(in: .whitespaces)
+                        dataPerson["picture"] = cursorData.string(forColumnIndex: 3)
+                        dataPerson["isOfficial"] = cursorData.string(forColumnIndex: 2)
+                        if isContactCenter && isRequestContactCenter {
+                            dataPerson["user_type"] = "0"
+                        } else {
+                            dataPerson["user_type"] = cursorData.string(forColumnIndex: 6)
+                        }
                     } else {
-                        dataPerson["user_type"] = cursorData.string(forColumnIndex: 6)
+                        dataPerson["f_pin"] = "-999"
+                        dataPerson["name"] = "Bot"
+                        dataPerson["picture"] = ""
+                        dataPerson["isOfficial"] = ""
+                        dataPerson["deviceId"] = ""
+                        dataPerson["isOffline"] = "0"
+                        dataPerson["user_type"] = "0"
                     }
-                } else {
-                    dataPerson["f_pin"] = "-999"
-                    dataPerson["name"] = "Bot"
-                    dataPerson["picture"] = ""
-                    dataPerson["isOfficial"] = ""
-                    dataPerson["deviceId"] = ""
-                    dataPerson["isOffline"] = "0"
-                    dataPerson["user_type"] = "0"
+                    cursorData.close()
                 }
-                cursorData.close()
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
     }
@@ -810,93 +840,80 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
         let queryCount = "SELECT COUNT(*) FROM MESSAGE where (f_pin='\(dataPerson["f_pin"]!!)' or l_pin='\(dataPerson["f_pin"]!!)') AND (message_scope_id = '3' OR message_scope_id = '18') AND is_call_center = 0"
         let query = "SELECT message_id, f_pin, l_pin, message_scope_id, server_date, status, message_text, audio_id, video_id, image_id, thumb_id, read_receipts, chat_id, file_id, attachment_flag, reff_id, lock, is_stared, blog_id, credential, is_call_center, call_center_id, opposite_pin FROM MESSAGE where (f_pin='\(dataPerson["f_pin"]!!)' or l_pin='\(dataPerson["f_pin"]!!)') AND (message_scope_id = '3' OR message_scope_id = '18') AND is_call_center = 0 order by server_date asc LIMIT CASE WHEN (\(queryCount))-\(dataMessages.count)>=20 THEN 20*\(multipleOffsetUp-1) ELSE (\(queryCount))-\(dataMessages.count) END OFFSET CASE WHEN (\(queryCount))>=\(20*multipleOffsetUp) THEN (\(queryCount))-\(20*multipleOffsetUp) ELSE 0 END"
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: query) {
-                var tempData: [[String: Any?]] = []
-                while cursorData.next() {
-                    var row: [String: Any?] = [:]
-                    row["message_id"] = cursorData.string(forColumnIndex: 0)
-                    row["f_pin"] = cursorData.string(forColumnIndex: 1)
-                    row["l_pin"] = cursorData.string(forColumnIndex: 2)
-                    row["message_scope_id"] = cursorData.string(forColumnIndex: 3)
-                    row["server_date"] = cursorData.string(forColumnIndex: 4)
-                    row["status"] = cursorData.string(forColumnIndex: 5)
-                    row["message_text"] = cursorData.string(forColumnIndex: 6)
-                    row["audio_id"] = cursorData.string(forColumnIndex: 7)
-                    row["video_id"] = cursorData.string(forColumnIndex: 8)
-                    row["image_id"] = cursorData.string(forColumnIndex: 9)
-                    row["thumb_id"] = cursorData.string(forColumnIndex: 10)
-                    row["read_receipts"] = cursorData.string(forColumnIndex: 11)
-                    row["chat_id"] = cursorData.string(forColumnIndex: 12)
-                    row["file_id"] = cursorData.string(forColumnIndex: 13)
-                    row["attachment_flag"] = cursorData.string(forColumnIndex: 14)
-                    row["reff_id"] = cursorData.string(forColumnIndex: 15)
-                    row["lock"] = cursorData.string(forColumnIndex: 16)
-                    row["is_stared"] = cursorData.string(forColumnIndex: 17)
-                    row["blog_id"] = cursorData.string(forColumnIndex: 18)
-                    row["credential"] = cursorData.string(forColumnIndex: 19)
-                    row[TypeDataMessage.is_call_center] = cursorData.string(forColumnIndex: 20)
-                    row[TypeDataMessage.call_center_id] = cursorData.string(forColumnIndex: 21)
-                    row[TypeDataMessage.opposite_pin] = cursorData.string(forColumnIndex: 22)
-                    if let cursorStatus = Database.shared.getRecords(fmdb: fmdb, query: "SELECT status FROM MESSAGE_STATUS WHERE message_id='\(row["message_id"] as! String)'") {
-                        while cursorStatus.next() {
-                            row["status"] = cursorStatus.string(forColumnIndex: 0)
-                        }
-                        cursorStatus.close()
-                    }
-                    let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
-                    let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
-                    let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
-                    if let dirPath = paths.first {
-                        let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["video_id"] as! String)
-                        let fileURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["file_id"] as! String)
-                        if ((row["video_id"] as! String) != "") {
-                            if FileManager.default.fileExists(atPath: videoURL.path){
-                                row["progress"] = 100.0
-                            } else {
-                                row["progress"] = 0.0
-                            }
-                        } else {
-                            if FileManager.default.fileExists(atPath: fileURL.path){
-                                row["progress"] = 100.0
-                            } else {
-                                row["progress"] = 0.0
+            do {
+                if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: query) {
+                    var tempData: [[String: Any?]] = []
+                    while cursorData.next() {
+                        var row: [String: Any?] = [:]
+                        row["message_id"] = cursorData.string(forColumnIndex: 0)
+                        row["f_pin"] = cursorData.string(forColumnIndex: 1)
+                        row["l_pin"] = cursorData.string(forColumnIndex: 2)
+                        row["message_scope_id"] = cursorData.string(forColumnIndex: 3)
+                        row["server_date"] = cursorData.string(forColumnIndex: 4)
+                        row["status"] = cursorData.string(forColumnIndex: 5)
+                        row["message_text"] = cursorData.string(forColumnIndex: 6)
+                        row["audio_id"] = cursorData.string(forColumnIndex: 7)
+                        row["video_id"] = cursorData.string(forColumnIndex: 8)
+                        row["image_id"] = cursorData.string(forColumnIndex: 9)
+                        row["thumb_id"] = cursorData.string(forColumnIndex: 10)
+                        row["read_receipts"] = cursorData.string(forColumnIndex: 11)
+                        row["chat_id"] = cursorData.string(forColumnIndex: 12)
+                        row["file_id"] = cursorData.string(forColumnIndex: 13)
+                        row["attachment_flag"] = cursorData.string(forColumnIndex: 14)
+                        row["reff_id"] = cursorData.string(forColumnIndex: 15)
+                        row["lock"] = cursorData.string(forColumnIndex: 16)
+                        row["is_stared"] = cursorData.string(forColumnIndex: 17)
+                        row["blog_id"] = cursorData.string(forColumnIndex: 18)
+                        row["credential"] = cursorData.string(forColumnIndex: 19)
+                        row[TypeDataMessage.is_call_center] = cursorData.string(forColumnIndex: 20)
+                        row[TypeDataMessage.call_center_id] = cursorData.string(forColumnIndex: 21)
+                        row[TypeDataMessage.opposite_pin] = cursorData.string(forColumnIndex: 22)
+                        if let cursorStatus = Database.shared.getRecords(fmdb: fmdb, query: "SELECT status FROM MESSAGE_STATUS WHERE message_id='\(row["message_id"] as! String)'") {
+                            while cursorStatus.next() {
+                                row["status"] = cursorStatus.string(forColumnIndex: 0)
                             }
+                            cursorStatus.close()
                         }
-                    }
-                    row["chat_date"] = chatDate(stringDate: row["server_date"] as! String)
-                    row["isSelected"] = false
-                    if row["credential"] != nil && row["credential"] as! String == "1" {
-                        let idMe = User.getMyPin()!
-                        if row["f_pin"] as! String == idMe {
-                            let second = getSecondsDifferenceFromTwoDates(start: Date.init(milliseconds: Int64(row["server_date"] as! String)!), end: Date())
-                            if second > 60 {
-                                listTimerCredential[row["message_id"] as! String] = 0
-                                row["lock"] = "2"
-                                row["reff_id"] = ""
-                                DispatchQueue.global().async {
-                                    Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                                            "lock" : "2"
-                                        ], _where: "message_id = '\(row["message_id"] as! String)'")
-                                    })
+                        let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
+                        let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
+                        let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
+                        if let dirPath = paths.first {
+                            let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["video_id"] as! String)
+                            let fileURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["file_id"] as! String)
+                            if ((row["video_id"] as! String) != "") {
+                                if FileManager.default.fileExists(atPath: videoURL.path){
+                                    row["progress"] = 100.0
+                                } else {
+                                    row["progress"] = 0.0
                                 }
                             } else {
-                                let second = 60 - second
-                                listTimerCredential[row["message_id"] as! String] = second
+                                if FileManager.default.fileExists(atPath: fileURL.path){
+                                    row["progress"] = 100.0
+                                } else {
+                                    row["progress"] = 0.0
+                                }
                             }
-                        } else {
-                            let hasMessageId: String? = SecureUserDefaults.shared.value(forKey: row["message_id"] as! String) ?? nil
-                            if hasMessageId != nil {
-                                let second = getSecondsDifferenceFromTwoDates(start: Date.init(milliseconds: Int64(hasMessageId!)!), end: Date())
+                        }
+                        row["chat_date"] = chatDate(stringDate: row["server_date"] as! String)
+                        row["isSelected"] = false
+                        if row["credential"] != nil && row["credential"] as! String == "1" {
+                            let idMe = User.getMyPin()!
+                            if row["f_pin"] as! String == idMe {
+                                let second = getSecondsDifferenceFromTwoDates(start: Date.init(milliseconds: Int64(row["server_date"] as! String)!), end: Date())
                                 if second > 60 {
                                     listTimerCredential[row["message_id"] as! String] = 0
                                     row["lock"] = "2"
                                     row["reff_id"] = ""
                                     DispatchQueue.global().async {
                                         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                                                "lock" : "2"
-                                            ], _where: "message_id = '\(row["message_id"] as! String)'")
+                                            do {
+                                                _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                                                    "lock" : "2"
+                                                ], _where: "message_id = '\(row["message_id"] as! String)'")
+                                            } catch {
+                                                rollback.pointee = true
+                                                print("Access database error: \(error.localizedDescription)")
+                                            }
                                         })
                                     }
                                 } else {
@@ -904,29 +921,57 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                                     listTimerCredential[row["message_id"] as! String] = second
                                 }
                             } else {
-                                SecureUserDefaults.shared.set("\(Date().currentTimeMillis())", forKey: row["message_id"] as! String)
-                                listTimerCredential[row["message_id"] as! String] = 60
+                                let hasMessageId: String? = SecureUserDefaults.shared.value(forKey: row["message_id"] as! String) ?? nil
+                                if hasMessageId != nil {
+                                    let second = getSecondsDifferenceFromTwoDates(start: Date.init(milliseconds: Int64(hasMessageId!)!), end: Date())
+                                    if second > 60 {
+                                        listTimerCredential[row["message_id"] as! String] = 0
+                                        row["lock"] = "2"
+                                        row["reff_id"] = ""
+                                        DispatchQueue.global().async {
+                                            Database.shared.database?.inTransaction({ (fmdb, rollback) in
+                                                do {
+                                                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                                                        "lock" : "2"
+                                                    ], _where: "message_id = '\(row["message_id"] as! String)'")
+                                                } catch {
+                                                    rollback.pointee = true
+                                                    print("Access database error: \(error.localizedDescription)")
+                                                }
+                                            })
+                                        }
+                                    } else {
+                                        let second = 60 - second
+                                        listTimerCredential[row["message_id"] as! String] = second
+                                    }
+                                } else {
+                                    SecureUserDefaults.shared.set("\(Date().currentTimeMillis())", forKey: row["message_id"] as! String)
+                                    listTimerCredential[row["message_id"] as! String] = 60
+                                }
                             }
                         }
-                    }
-                    tempData.append(row)
-                }
-                if tempData.count != 0 && (dataMessages.firstIndex(where: { $0["message_id"] as? String == tempData[0]["message_id"] as? String }) == nil) {
-                    let lastIndex = tempData.count - 1
-                    for i in 0..<tempData.count {
-                        tableChatView.beginUpdates()
-                        dataMessages.insert(tempData[lastIndex - i], at: 0)
-                        if dataMessages.firstIndex(where: { $0["chat_date"] as? String == tempData[lastIndex - i]["chat_date"] as? String }) != nil {
-                            tableChatView.insertRows(at: [IndexPath(row: 0, section: currentIndexpath!.section)], with: .top)
-                        } else {
-                            tableChatView.insertSections(IndexSet(integer: 0), with: .top)
-                            tableChatView.insertRows(at: [IndexPath(row: 0, section: 0)], with: .top)
+                        tempData.append(row)
+                    }
+                    if tempData.count != 0 && (dataMessages.firstIndex(where: { $0["message_id"] as? String == tempData[0]["message_id"] as? String }) == nil) {
+                        let lastIndex = tempData.count - 1
+                        for i in 0..<tempData.count {
+                            tableChatView.beginUpdates()
+                            dataMessages.insert(tempData[lastIndex - i], at: 0)
+                            if dataMessages.firstIndex(where: { $0["chat_date"] as? String == tempData[lastIndex - i]["chat_date"] as? String }) != nil {
+                                tableChatView.insertRows(at: [IndexPath(row: 0, section: currentIndexpath!.section)], with: .top)
+                            } else {
+                                tableChatView.insertSections(IndexSet(integer: 0), with: .top)
+                                tableChatView.insertRows(at: [IndexPath(row: 0, section: 0)], with: .top)
+                            }
+                            tableChatView.endUpdates()
                         }
-                        tableChatView.endUpdates()
                     }
+                    cursorData.close()
+                    gettingDataMessage = false
                 }
-                cursorData.close()
-                gettingDataMessage = false
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
     }
@@ -970,93 +1015,80 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
             }
         }
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: query) {
-                var tempImages: [ImageGrouping] = []
-                while cursorData.next() {
-                    var row: [String: Any?] = [:]
-                    row["message_id"] = cursorData.string(forColumnIndex: 0)
-                    row["f_pin"] = cursorData.string(forColumnIndex: 1)
-                    row["l_pin"] = cursorData.string(forColumnIndex: 2)
-                    row["message_scope_id"] = cursorData.string(forColumnIndex: 3)
-                    row["server_date"] = cursorData.string(forColumnIndex: 4)
-                    row["status"] = cursorData.string(forColumnIndex: 5)
-                    row["message_text"] = cursorData.string(forColumnIndex: 6)
-                    row["audio_id"] = cursorData.string(forColumnIndex: 7)
-                    row["video_id"] = cursorData.string(forColumnIndex: 8)
-                    row["image_id"] = cursorData.string(forColumnIndex: 9)
-                    row["thumb_id"] = cursorData.string(forColumnIndex: 10)
-                    row["read_receipts"] = cursorData.string(forColumnIndex: 11)
-                    row["chat_id"] = cursorData.string(forColumnIndex: 12)
-                    row["file_id"] = cursorData.string(forColumnIndex: 13)
-                    row["attachment_flag"] = cursorData.string(forColumnIndex: 14)
-                    row["reff_id"] = cursorData.string(forColumnIndex: 15)
-                    row["lock"] = cursorData.string(forColumnIndex: 16)
-                    row["is_stared"] = cursorData.string(forColumnIndex: 17)
-                    row["blog_id"] = cursorData.string(forColumnIndex: 18)
-                    row["credential"] = cursorData.string(forColumnIndex: 19)
-                    row[TypeDataMessage.is_call_center] = cursorData.string(forColumnIndex: 20)
-                    row[TypeDataMessage.call_center_id] = cursorData.string(forColumnIndex: 21)
-                    row[TypeDataMessage.opposite_pin] = cursorData.string(forColumnIndex: 22)
-                    if let cursorStatus = Database.shared.getRecords(fmdb: fmdb, query: "SELECT status FROM MESSAGE_STATUS WHERE message_id='\(row["message_id"] as! String)'") {
-                        while cursorStatus.next() {
-                            row["status"] = cursorStatus.string(forColumnIndex: 0)
-                        }
-                        cursorStatus.close()
-                    }
-                    let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
-                    let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
-                    let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
-                    if let dirPath = paths.first {
-                        let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["video_id"] as! String)
-                        let fileURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["file_id"] as! String)
-                        if ((row["video_id"] as! String) != "") {
-                            if FileManager.default.fileExists(atPath: videoURL.path){
-                                row["progress"] = 100.0
-                            } else {
-                                row["progress"] = 0.0
-                            }
-                        } else {
-                            if FileManager.default.fileExists(atPath: fileURL.path){
-                                row["progress"] = 100.0
-                            } else {
-                                row["progress"] = 0.0
+            do {
+                if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: query) {
+                    var tempImages: [ImageGrouping] = []
+                    while cursorData.next() {
+                        var row: [String: Any?] = [:]
+                        row["message_id"] = cursorData.string(forColumnIndex: 0)
+                        row["f_pin"] = cursorData.string(forColumnIndex: 1)
+                        row["l_pin"] = cursorData.string(forColumnIndex: 2)
+                        row["message_scope_id"] = cursorData.string(forColumnIndex: 3)
+                        row["server_date"] = cursorData.string(forColumnIndex: 4)
+                        row["status"] = cursorData.string(forColumnIndex: 5)
+                        row["message_text"] = cursorData.string(forColumnIndex: 6)
+                        row["audio_id"] = cursorData.string(forColumnIndex: 7)
+                        row["video_id"] = cursorData.string(forColumnIndex: 8)
+                        row["image_id"] = cursorData.string(forColumnIndex: 9)
+                        row["thumb_id"] = cursorData.string(forColumnIndex: 10)
+                        row["read_receipts"] = cursorData.string(forColumnIndex: 11)
+                        row["chat_id"] = cursorData.string(forColumnIndex: 12)
+                        row["file_id"] = cursorData.string(forColumnIndex: 13)
+                        row["attachment_flag"] = cursorData.string(forColumnIndex: 14)
+                        row["reff_id"] = cursorData.string(forColumnIndex: 15)
+                        row["lock"] = cursorData.string(forColumnIndex: 16)
+                        row["is_stared"] = cursorData.string(forColumnIndex: 17)
+                        row["blog_id"] = cursorData.string(forColumnIndex: 18)
+                        row["credential"] = cursorData.string(forColumnIndex: 19)
+                        row[TypeDataMessage.is_call_center] = cursorData.string(forColumnIndex: 20)
+                        row[TypeDataMessage.call_center_id] = cursorData.string(forColumnIndex: 21)
+                        row[TypeDataMessage.opposite_pin] = cursorData.string(forColumnIndex: 22)
+                        if let cursorStatus = Database.shared.getRecords(fmdb: fmdb, query: "SELECT status FROM MESSAGE_STATUS WHERE message_id='\(row["message_id"] as! String)'") {
+                            while cursorStatus.next() {
+                                row["status"] = cursorStatus.string(forColumnIndex: 0)
                             }
+                            cursorStatus.close()
                         }
-                    }
-                    row["chat_date"] = chatDate(stringDate: row["server_date"] as! String)
-                    row["isSelected"] = false
-                    if row["credential"] != nil && row["credential"] as! String == "1" {
-                        let idMe = User.getMyPin()!
-                        if row["f_pin"] as! String == idMe {
-                            let second = getSecondsDifferenceFromTwoDates(start: Date.init(milliseconds: Int64(row["server_date"] as! String)!), end: Date())
-                            if second > 60 {
-                                listTimerCredential[row["message_id"] as! String] = 0
-                                row["lock"] = "2"
-                                row["reff_id"] = ""
-                                DispatchQueue.global().async {
-                                    Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                                            "lock" : "2"
-                                        ], _where: "message_id = '\(row["message_id"] as! String)'")
-                                    })
+                        let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
+                        let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
+                        let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
+                        if let dirPath = paths.first {
+                            let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["video_id"] as! String)
+                            let fileURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["file_id"] as! String)
+                            if ((row["video_id"] as! String) != "") {
+                                if FileManager.default.fileExists(atPath: videoURL.path){
+                                    row["progress"] = 100.0
+                                } else {
+                                    row["progress"] = 0.0
                                 }
                             } else {
-                                let second = 60 - second
-                                listTimerCredential[row["message_id"] as! String] = second
+                                if FileManager.default.fileExists(atPath: fileURL.path){
+                                    row["progress"] = 100.0
+                                } else {
+                                    row["progress"] = 0.0
+                                }
                             }
-                        } else {
-                            let hasMessageId: String? = SecureUserDefaults.shared.value(forKey: row["message_id"] as! String) ?? nil
-                            if hasMessageId != nil {
-                                let second = getSecondsDifferenceFromTwoDates(start: Date.init(milliseconds: Int64(hasMessageId!)!), end: Date())
+                        }
+                        row["chat_date"] = chatDate(stringDate: row["server_date"] as! String)
+                        row["isSelected"] = false
+                        if row["credential"] != nil && row["credential"] as! String == "1" {
+                            let idMe = User.getMyPin()!
+                            if row["f_pin"] as! String == idMe {
+                                let second = getSecondsDifferenceFromTwoDates(start: Date.init(milliseconds: Int64(row["server_date"] as! String)!), end: Date())
                                 if second > 60 {
                                     listTimerCredential[row["message_id"] as! String] = 0
                                     row["lock"] = "2"
                                     row["reff_id"] = ""
                                     DispatchQueue.global().async {
                                         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                                                "lock" : "2"
-                                            ], _where: "message_id = '\(row["message_id"] as! String)'")
+                                            do {
+                                                _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                                                    "lock" : "2"
+                                                ], _where: "message_id = '\(row["message_id"] as! String)'")
+                                            } catch {
+                                                rollback.pointee = true
+                                                print("Access database error: \(error.localizedDescription)")
+                                            }
                                         })
                                     }
                                 } else {
@@ -1064,49 +1096,77 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                                     listTimerCredential[row["message_id"] as! String] = second
                                 }
                             } else {
-                                SecureUserDefaults.shared.set("\(Date().currentTimeMillis())", forKey: row["message_id"] as! String)
-                                listTimerCredential[row["message_id"] as! String] = 60
+                                let hasMessageId: String? = SecureUserDefaults.shared.value(forKey: row["message_id"] as! String) ?? nil
+                                if hasMessageId != nil {
+                                    let second = getSecondsDifferenceFromTwoDates(start: Date.init(milliseconds: Int64(hasMessageId!)!), end: Date())
+                                    if second > 60 {
+                                        listTimerCredential[row["message_id"] as! String] = 0
+                                        row["lock"] = "2"
+                                        row["reff_id"] = ""
+                                        DispatchQueue.global().async {
+                                            Database.shared.database?.inTransaction({ (fmdb, rollback) in
+                                                do {
+                                                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                                                        "lock" : "2"
+                                                    ], _where: "message_id = '\(row["message_id"] as! String)'")
+                                                } catch {
+                                                    rollback.pointee = true
+                                                    print("Access database error: \(error.localizedDescription)")
+                                                }
+                                            })
+                                        }
+                                    } else {
+                                        let second = 60 - second
+                                        listTimerCredential[row["message_id"] as! String] = second
+                                    }
+                                } else {
+                                    SecureUserDefaults.shared.set("\(Date().currentTimeMillis())", forKey: row["message_id"] as! String)
+                                    listTimerCredential[row["message_id"] as! String] = 60
+                                }
                             }
                         }
-                    }
-                    if (dataMessages.count == 0 || dataMessages.last!["f_pin"] as! String == row["f_pin"] as! String) && tempImages.count <= 30 && row["image_id"] != nil && !(row["image_id"] as! String).isEmpty && (row["message_text"] as! String).isEmpty && (row["reff_id"] as! String).isEmpty && (row["credential"] as! String) != "1" && (row["read_receipts"] as! String) != "8" {
-                        if tempImages.count != 0 && getSecondsDifferenceFromTwoDates(start: Date.init(milliseconds: Int64(tempImages.last!.time)!), end: Date.init(milliseconds: Int64(row["server_date"] as! String)!))/60 >= 11 {
-                            if tempImages.count >= 4 {
-                                groupImages[tempImages[0].messageId] = tempImages
-                                if let idxTemp = dataMessages.firstIndex(where: { $0["message_id"] as! String == tempImages[0].messageId }) {
-                                    for _ in 1..<tempImages.count {
-                                        dataMessages.remove(at: idxTemp + 1)
+                        if (dataMessages.count == 0 || dataMessages.last!["f_pin"] as! String == row["f_pin"] as! String) && tempImages.count <= 30 && row["image_id"] != nil && !(row["image_id"] as! String).isEmpty && (row["message_text"] as! String).isEmpty && (row["reff_id"] as! String).isEmpty && (row["credential"] as! String) != "1" && (row["read_receipts"] as! String) != "8" {
+                            if tempImages.count != 0 && getSecondsDifferenceFromTwoDates(start: Date.init(milliseconds: Int64(tempImages.last!.time)!), end: Date.init(milliseconds: Int64(row["server_date"] as! String)!))/60 >= 11 {
+                                if tempImages.count >= 4 {
+                                    groupImages[tempImages[0].messageId] = tempImages
+                                    if let idxTemp = dataMessages.firstIndex(where: { $0["message_id"] as! String == tempImages[0].messageId }) {
+                                        for _ in 1..<tempImages.count {
+                                            dataMessages.remove(at: idxTemp + 1)
+                                        }
                                     }
                                 }
+                                tempImages.removeAll()
+                            }
+                            tempImages.append(ImageGrouping(messageId: row["message_id"] as! String, thumbId: row["thumb_id"] as! String, imageId: row["image_id"] as! String, status: row["status"] as! String, time: row["server_date"] as! String, lPin: row["l_pin"] as! String, dataMessage: row, dataPerson: dataPerson, dataGroup: [:], dataTopic: [:]))
+                        } else if tempImages.count >= 4 {
+                            groupImages[tempImages[0].messageId] = tempImages
+                            if let idxTemp = dataMessages.firstIndex(where: { $0["message_id"] as! String == tempImages[0].messageId }) {
+                                for _ in 1..<tempImages.count {
+                                    dataMessages.remove(at: idxTemp + 1)
+                                }
                             }
                             tempImages.removeAll()
+                        } else if tempImages.count != 0 {
+                            tempImages.removeAll()
+                        }
+                        dataMessages.append(row)
+                    }
+                    if tempImages.count >= 4 {
+                        if tempImages.count > 30 {
+                            tempImages.removeSubrange(30..<tempImages.count)
                         }
-                        tempImages.append(ImageGrouping(messageId: row["message_id"] as! String, thumbId: row["thumb_id"] as! String, imageId: row["image_id"] as! String, status: row["status"] as! String, time: row["server_date"] as! String, lPin: row["l_pin"] as! String, dataMessage: row, dataPerson: dataPerson, dataGroup: [:], dataTopic: [:]))
-                    } else if tempImages.count >= 4 {
                         groupImages[tempImages[0].messageId] = tempImages
                         if let idxTemp = dataMessages.firstIndex(where: { $0["message_id"] as! String == tempImages[0].messageId }) {
                             for _ in 1..<tempImages.count {
                                 dataMessages.remove(at: idxTemp + 1)
                             }
                         }
-                        tempImages.removeAll()
-                    } else if tempImages.count != 0 {
-                        tempImages.removeAll()
-                    }
-                    dataMessages.append(row)
-                }
-                if tempImages.count >= 4 {
-                    if tempImages.count > 30 {
-                        tempImages.removeSubrange(30..<tempImages.count)
-                    }
-                    groupImages[tempImages[0].messageId] = tempImages
-                    if let idxTemp = dataMessages.firstIndex(where: { $0["message_id"] as! String == tempImages[0].messageId }) {
-                        for _ in 1..<tempImages.count {
-                            dataMessages.remove(at: idxTemp + 1)
-                        }
                     }
+                    cursorData.close()
                 }
-                cursorData.close()
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
     }
@@ -1377,7 +1437,7 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                                     ], replace: true)
                                 } catch {
                                     rollback.pointee = true
-                                    //print(error)
+                                    print("Access database error: \(error.localizedDescription)")
                                 }
                             })
                         }
@@ -1502,9 +1562,14 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                                 }
                                 DispatchQueue.global().async {
                                     Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                                            "lock" : "2"
-                                        ], _where: "message_id = '\(row["message_id"] as! String)'")
+                                        do {
+                                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                                                "lock" : "2"
+                                            ], _where: "message_id = '\(row["message_id"] as! String)'")
+                                        } catch {
+                                            rollback.pointee = true
+                                            print("Access database error: \(error.localizedDescription)")
+                                        }
                                     })
                                 }
                             }
@@ -2201,7 +2266,7 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                     ], replace: true)
                 } catch {
                     rollback.pointee = true
-                    //print(error)
+                    print("Access database error: \(error.localizedDescription)")
                 }
             })
             if officer == idMe {
@@ -2394,9 +2459,14 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                     }
                     DispatchQueue.global().async {
                         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                                "lock" : "2"
-                            ], _where: "message_id = '\(messageId)'")
+                            do {
+                                _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                                    "lock" : "2"
+                                ], _where: "message_id = '\(messageId)'")
+                            } catch {
+                                rollback.pointee = true
+                                print("Access database error: \(error.localizedDescription)")
+                            }
                         })
                     }
                 }
@@ -2808,9 +2878,14 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                 let valueListGroupImages = listGroupImages.value
                 for i in 0..<valueListGroupImages.count {
                     Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                            "status" : "4"
-                        ], _where: "message_id = '\(valueListGroupImages[i].messageId)'")
+                        do {
+                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                                "status" : "4"
+                            ], _where: "message_id = '\(valueListGroupImages[i].messageId)'")
+                        } catch {
+                            rollback.pointee = true
+                            print("Access database error: \(error.localizedDescription)")
+                        }
                     })
                     message.mStatus = CoreMessage_TMessageUtil.getTID()
                     message.mBodies[CoreMessage_TMessageKey.L_PIN] = f_pin
@@ -2819,9 +2894,14 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                 }
             } else {
                 Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                        "status" : "4"
-                    ], _where: "message_id = '\(message_id)'")
+                    do {
+                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                            "status" : "4"
+                        ], _where: "message_id = '\(message_id)'")
+                    } catch {
+                        rollback.pointee = true
+                        print("Access database error: \(error.localizedDescription)")
+                    }
                 })
                 message.mStatus = CoreMessage_TMessageUtil.getTID()
                 message.mBodies[CoreMessage_TMessageKey.L_PIN] = f_pin
@@ -2951,9 +3031,14 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
     private func updateCounter(counter: Int) {
         DispatchQueue.global().async {
             Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", cvalues: [
-                    "counter" : "\(counter)"
-                ], _where: "l_pin = '\(self.dataPerson["f_pin"]!!)'")
+                do {
+                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", cvalues: [
+                        "counter" : "\(counter)"
+                    ], _where: "l_pin = '\(self.dataPerson["f_pin"]!!)'")
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
+                }
             })
             NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reloadTabChats"), object: nil, userInfo: nil)
         }
@@ -3260,13 +3345,18 @@ extension EditorPersonal: UITextViewDelegate {
                 }
                 var dataURL = ""
                 Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                    if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select data_link from LINK_PREVIEW where link='\(text)'") {
-                        while cursor.next() {
-                            if let data = cursor.string(forColumnIndex: 0) {
-                                dataURL = data
+                    do {
+                        if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select data_link from LINK_PREVIEW where link='\(text)'") {
+                            while cursor.next() {
+                                if let data = cursor.string(forColumnIndex: 0) {
+                                    dataURL = data
+                                }
                             }
+                            cursor.close()
                         }
-                        cursor.close()
+                    } catch {
+                        rollback.pointee = true
+                        print("Access database error: \(error.localizedDescription)")
                     }
                 })
                 if !dataURL.isEmpty {
@@ -3312,7 +3402,7 @@ extension EditorPersonal: UITextViewDelegate {
                                 ], replace: true)
                             } catch {
                                 rollback.pointee = true
-                                //print(error)
+                                print("Access database error: \(error.localizedDescription)")
                             }
                         })
                         if self.showingLink != text {
@@ -3486,9 +3576,14 @@ extension EditorPersonal: UIContextMenuInteractionDelegate {
                 }
                 DispatchQueue.global().async {
                     Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                            "is_stared" : 1
-                        ], _where: "message_id = '\(dataMessages[indexPath!.row]["message_id"] as! String)'")
+                        do {
+                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                                "is_stared" : 1
+                            ], _where: "message_id = '\(dataMessages[indexPath!.row]["message_id"] as! String)'")
+                        } catch {
+                            rollback.pointee = true
+                            print("Access database error: \(error.localizedDescription)")
+                        }
                     })
                 }
                 let idx = self.dataMessages.firstIndex(where: { $0["message_id"] as? String == dataMessages[indexPath!.row]["message_id"] as? String})
@@ -3504,9 +3599,14 @@ extension EditorPersonal: UIContextMenuInteractionDelegate {
                 }
                 DispatchQueue.global().async {
                     Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                            "is_stared" : 0
-                        ], _where: "message_id = '\(dataMessages[indexPath!.row]["message_id"] as! String)'")
+                        do {
+                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                                "is_stared" : 0
+                            ], _where: "message_id = '\(dataMessages[indexPath!.row]["message_id"] as! String)'")
+                        } catch {
+                            rollback.pointee = true
+                            print("Access database error: \(error.localizedDescription)")
+                        }
                     })
                 }
                 let idx = self.dataMessages.firstIndex(where: { $0["message_id"] as? String == dataMessages[indexPath!.row]["message_id"] as? String})
@@ -3681,12 +3781,17 @@ extension EditorPersonal: UIContextMenuInteractionDelegate {
                 }
             }
             Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                    "status" : "1"
-                ], _where: "message_id = '\(messageId)'")
-                _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
-                    "status" : "1"
-                ], _where: "message_id = '\(messageId)'")
+                do {
+                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                        "status" : "1"
+                    ], _where: "message_id = '\(messageId)'")
+                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
+                        "status" : "1"
+                    ], _where: "message_id = '\(messageId)'")
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
+                }
             })
             let message = CoreMessage_TMessageBank.sendMessage(message_id: messageId,
                                                                l_pin: dataMessages[indexPath!.row][TypeDataMessage.l_pin] as! String,
@@ -5656,11 +5761,16 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource {
                 }
                 var dataURL = ""
                 Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                    if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select data_link from LINK_PREVIEW where link='\(text)'"), cursor.next() {
-                        if let data = cursor.string(forColumnIndex: 0) {
-                            dataURL = data
+                    do {
+                        if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select data_link from LINK_PREVIEW where link='\(text)'"), cursor.next() {
+                            if let data = cursor.string(forColumnIndex: 0) {
+                                dataURL = data
+                            }
+                            cursor.close()
                         }
-                        cursor.close()
+                    } catch {
+                        rollback.pointee = true
+                        print("Access database error: \(error.localizedDescription)")
                     }
                 })
                 if dataURL.isEmpty {
@@ -5699,7 +5809,7 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource {
                                 }
                             } catch {
                                 rollback.pointee = true
-                                //print(error)
+                                print("Access database error: \(error.localizedDescription)")
                             }
                         })
                     }, onError: { error in
@@ -5999,9 +6109,14 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource {
             let result = Nexilis.write(message: CoreMessage_TMessageBank.getAckLocationMessage(f_pin: dataMessages[indexPath.row]["f_pin"] as! String, message_id: dataMessages[indexPath.row]["message_id"] as! String, l_pin: dataMessages[indexPath.row]["l_pin"] as! String, server_date: "\(Date().currentTimeMillis())", message_scope_id: dataMessages[indexPath.row]["message_scope_id"] as! String, longitude: "", latitude: "", description: ""))
             if result != nil {
                 Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                        "status" : "8"
-                    ], _where: "message_id = '\(dataMessages[indexPath.row]["message_id"] as! String)'")
+                    do {
+                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                            "status" : "8"
+                        ], _where: "message_id = '\(dataMessages[indexPath.row]["message_id"] as! String)'")
+                    } catch {
+                        rollback.pointee = true
+                        print("Access database error: \(error.localizedDescription)")
+                    }
                 })
                 DispatchQueue.main.async {
                     if let index = self.dataMessages.firstIndex(where: {$0["message_id"] as? String == dataMessages[indexPath.row]["message_id"] as? String}) {

+ 77 - 57
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Chat/EditorStarMessages.swift

@@ -47,9 +47,14 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
             UIAction(title: "Unfavorite all messages".localized(), handler: {(_) in
                 DispatchQueue.global().async {
                     Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                        _ = Database.shared.updateAllRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                            "is_stared" : 0
-                        ])
+                        do {
+                            _ = Database.shared.updateAllRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                                "is_stared" : 0
+                            ])
+                        } catch {
+                            rollback.pointee = true
+                            print("Access database error: \(error.localizedDescription)")
+                        }
                     })
                 }
                 self.dataMessages.removeAll()
@@ -765,11 +770,16 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
                 }
                 var dataURL = ""
                 Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                    if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select data_link from LINK_PREVIEW where link='\(text)'"), cursor.next() {
-                        if let data = cursor.string(forColumnIndex: 0) {
-                            dataURL = data
+                    do {
+                        if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select data_link from LINK_PREVIEW where link='\(text)'"), cursor.next() {
+                            if let data = cursor.string(forColumnIndex: 0) {
+                                dataURL = data
+                            }
+                            cursor.close()
                         }
-                        cursor.close()
+                    } catch {
+                        rollback.pointee = true
+                        print("Access database error: \(error.localizedDescription)")
                     }
                 })
                 if dataURL.isEmpty {
@@ -808,7 +818,7 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
                                 }
                             } catch {
                                 rollback.pointee = true
-                                //print(error)
+                                print("Access database error: \(error.localizedDescription)")
                             }
                         })
                     }, onError: { error in
@@ -943,58 +953,63 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
     
     func getData() {
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT message_id, f_pin, l_pin, message_scope_id, server_date, status, message_text, audio_id, video_id, image_id, thumb_id, read_receipts, chat_id, file_id, attachment_flag, reff_id, lock, is_stared, blog_id FROM MESSAGE where is_stared=1 order by server_date asc") {
-                while cursorData.next() {
-                    var row: [String: Any?] = [:]
-                    row["message_id"] = cursorData.string(forColumnIndex: 0)
-                    row["f_pin"] = cursorData.string(forColumnIndex: 1)
-                    row["l_pin"] = cursorData.string(forColumnIndex: 2)
-                    row["message_scope_id"] = cursorData.string(forColumnIndex: 3)
-                    row["server_date"] = cursorData.string(forColumnIndex: 4)
-                    row["status"] = cursorData.string(forColumnIndex: 5)
-                    row["message_text"] = cursorData.string(forColumnIndex: 6)
-                    row["audio_id"] = cursorData.string(forColumnIndex: 7)
-                    row["video_id"] = cursorData.string(forColumnIndex: 8)
-                    row["image_id"] = cursorData.string(forColumnIndex: 9)
-                    row["thumb_id"] = cursorData.string(forColumnIndex: 10)
-                    row["read_receipts"] = cursorData.int(forColumnIndex: 11)
-                    row["chat_id"] = cursorData.string(forColumnIndex: 12)
-                    row["file_id"] = cursorData.string(forColumnIndex: 13)
-                    row["attachment_flag"] = cursorData.string(forColumnIndex: 14)
-                    row["reff_id"] = cursorData.string(forColumnIndex: 15)
-                    row["lock"] = cursorData.string(forColumnIndex: 16)
-                    row["is_stared"] = cursorData.string(forColumnIndex: 17)
-                    row["blog_id"] = cursorData.string(forColumnIndex: 18)
-                    if let cursorStatus = Database.shared.getRecords(fmdb: fmdb, query: "SELECT status FROM MESSAGE_STATUS WHERE message_id='\(row["message_id"] as! String)'") {
-                        while cursorStatus.next() {
-                            row["status"] = cursorStatus.string(forColumnIndex: 0)
-                        }
-                        cursorStatus.close()
-                    }
-                    let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
-                    let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
-                    let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
-                    if let dirPath = paths.first {
-                        let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["video_id"] as! String)
-                        let fileURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["file_id"] as! String)
-                        if ((row["video_id"] as! String) != "") {
-                            if FileManager.default.fileExists(atPath: videoURL.path){
-                                row["progress"] = 100.0
-                            } else {
-                                row["progress"] = 0.0
+            do {
+                if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT message_id, f_pin, l_pin, message_scope_id, server_date, status, message_text, audio_id, video_id, image_id, thumb_id, read_receipts, chat_id, file_id, attachment_flag, reff_id, lock, is_stared, blog_id FROM MESSAGE where is_stared=1 order by server_date asc") {
+                    while cursorData.next() {
+                        var row: [String: Any?] = [:]
+                        row["message_id"] = cursorData.string(forColumnIndex: 0)
+                        row["f_pin"] = cursorData.string(forColumnIndex: 1)
+                        row["l_pin"] = cursorData.string(forColumnIndex: 2)
+                        row["message_scope_id"] = cursorData.string(forColumnIndex: 3)
+                        row["server_date"] = cursorData.string(forColumnIndex: 4)
+                        row["status"] = cursorData.string(forColumnIndex: 5)
+                        row["message_text"] = cursorData.string(forColumnIndex: 6)
+                        row["audio_id"] = cursorData.string(forColumnIndex: 7)
+                        row["video_id"] = cursorData.string(forColumnIndex: 8)
+                        row["image_id"] = cursorData.string(forColumnIndex: 9)
+                        row["thumb_id"] = cursorData.string(forColumnIndex: 10)
+                        row["read_receipts"] = cursorData.int(forColumnIndex: 11)
+                        row["chat_id"] = cursorData.string(forColumnIndex: 12)
+                        row["file_id"] = cursorData.string(forColumnIndex: 13)
+                        row["attachment_flag"] = cursorData.string(forColumnIndex: 14)
+                        row["reff_id"] = cursorData.string(forColumnIndex: 15)
+                        row["lock"] = cursorData.string(forColumnIndex: 16)
+                        row["is_stared"] = cursorData.string(forColumnIndex: 17)
+                        row["blog_id"] = cursorData.string(forColumnIndex: 18)
+                        if let cursorStatus = Database.shared.getRecords(fmdb: fmdb, query: "SELECT status FROM MESSAGE_STATUS WHERE message_id='\(row["message_id"] as! String)'") {
+                            while cursorStatus.next() {
+                                row["status"] = cursorStatus.string(forColumnIndex: 0)
                             }
-                        } else {
-                            if FileManager.default.fileExists(atPath: fileURL.path){
-                                row["progress"] = 100.0
+                            cursorStatus.close()
+                        }
+                        let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
+                        let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
+                        let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
+                        if let dirPath = paths.first {
+                            let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["video_id"] as! String)
+                            let fileURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["file_id"] as! String)
+                            if ((row["video_id"] as! String) != "") {
+                                if FileManager.default.fileExists(atPath: videoURL.path){
+                                    row["progress"] = 100.0
+                                } else {
+                                    row["progress"] = 0.0
+                                }
                             } else {
-                                row["progress"] = 0.0
+                                if FileManager.default.fileExists(atPath: fileURL.path){
+                                    row["progress"] = 100.0
+                                } else {
+                                    row["progress"] = 0.0
+                                }
                             }
                         }
+                        row["chat_date"] = chatDate(stringDate: row["server_date"] as! String, messageId: row["message_id"] as! String)
+                        dataMessages.append(row)
                     }
-                    row["chat_date"] = chatDate(stringDate: row["server_date"] as! String, messageId: row["message_id"] as! String)
-                    dataMessages.append(row)
+                    cursorData.close()
                 }
-                cursorData.close()
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
     }
@@ -1314,9 +1329,14 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
         let star = UIAction(title: "Unstar".localized(), image: UIImage(systemName: "star.slash.fill"), handler: {(_) in
             DispatchQueue.global().async {
                 Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                        "is_stared" : 0
-                    ], _where: "message_id = '\(dataMessages[indexPath!.row]["message_id"] as! String)'")
+                    do {
+                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                            "is_stared" : 0
+                        ], _where: "message_id = '\(dataMessages[indexPath!.row]["message_id"] as! String)'")
+                    } catch {
+                        rollback.pointee = true
+                        print("Access database error: \(error.localizedDescription)")
+                    }
                 })
             }
             let idx = self.dataMessages.firstIndex(where: { $0["message_id"] as! String == dataMessages[indexPath!.row]["message_id"] as! String})

+ 16 - 6
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Chat/ListGroupImages.swift

@@ -268,18 +268,28 @@ class ListGroupImages: UIViewController, UITableViewDataSource, UITableViewDeleg
                 if listGroupingImages[indexSelected].dataMessage["is_stared"] as! String == "0" {
                     DispatchQueue.global().async { [self] in
                         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                                "is_stared" : 1
-                            ], _where: "message_id = '\(listGroupingImages[indexSelected].messageId)'")
+                            do {
+                                _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                                    "is_stared" : 1
+                                ], _where: "message_id = '\(listGroupingImages[indexSelected].messageId)'")
+                            } catch {
+                                rollback.pointee = true
+                                print("Access database error: \(error.localizedDescription)")
+                            }
                         })
                     }
                     listGroupingImages[indexSelected].dataMessage["is_stared"] = "1"
                 } else {
                     DispatchQueue.global().async { [self] in
                         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
-                                "is_stared" : 0
-                            ], _where: "message_id = '\(listGroupingImages[indexSelected].messageId)'")
+                            do {
+                                _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
+                                    "is_stared" : 0
+                                ], _where: "message_id = '\(listGroupingImages[indexSelected].messageId)'")
+                            } catch {
+                                rollback.pointee = true
+                                print("Access database error: \(error.localizedDescription)")
+                            }
                         })
                     }
                     listGroupingImages[indexSelected].dataMessage["is_stared"] = "0"

+ 18 - 13
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Chat/MessageInfo.swift

@@ -51,20 +51,25 @@ class MessageInfo: UIViewController, UITableViewDelegate, UITableViewDataSource
     
     private func getData() {
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_pin, status, time_delivered, time_read, time_ack FROM MESSAGE_STATUS where message_id='\(data["message_id"]!!)'") {
-                var listStatus: [Int] = []
-                while cursorData.next() {
-                    var row: [String: Any?] = [:]
-                    row["f_pin"] = cursorData.string(forColumnIndex: 0) ?? ""
-                    row["status"] = cursorData.string(forColumnIndex: 1) ?? ""
-                    row["time_delivered"] = cursorData.string(forColumnIndex: 2) ?? ""
-                    row["time_read"] = cursorData.string(forColumnIndex: 3) ?? ""
-                    row["time_ack"] = cursorData.string(forColumnIndex: 4) ?? ""
-                    dataStatus.append(row)
-                    listStatus.append(Int(row["status"] as! String)!)
+            do {
+                if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_pin, status, time_delivered, time_read, time_ack FROM MESSAGE_STATUS where message_id='\(data["message_id"]!!)'") {
+                    var listStatus: [Int] = []
+                    while cursorData.next() {
+                        var row: [String: Any?] = [:]
+                        row["f_pin"] = cursorData.string(forColumnIndex: 0) ?? ""
+                        row["status"] = cursorData.string(forColumnIndex: 1) ?? ""
+                        row["time_delivered"] = cursorData.string(forColumnIndex: 2) ?? ""
+                        row["time_read"] = cursorData.string(forColumnIndex: 3) ?? ""
+                        row["time_ack"] = cursorData.string(forColumnIndex: 4) ?? ""
+                        dataStatus.append(row)
+                        listStatus.append(Int(row["status"] as! String)!)
+                    }
+                    data["status"] = "\(listStatus.min() ?? 2)"
+                    cursorData.close()
                 }
-                data["status"] = "\(listStatus.min() ?? 2)"
-                cursorData.close()
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
     }

+ 34 - 29
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Contact/ContactCallViewController.swift

@@ -149,37 +149,42 @@ class ContactCallViewController: UIViewController {
         dataPerson.removeAll()
         let idMe = User.getMyPin() as String?
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_pin, first_name, last_name, official_account, image_id, device_id, offline_mode, user_type, ex_block, ex_offmp FROM BUDDY where official_account<>'1' and f_pin <> '\(idMe!)' order by 4 desc, 2 collate nocase asc") {
-                while cursorData.next() {
-                    var row: [String: String?] = [:]
-                    row["f_pin"] = cursorData.string(forColumnIndex: 0)
-                    if(connectedCall.count > 0 && connectedCall.contains(where: { $0["f_pin"] == row["f_pin"] })) {
-                        continue
+            do {
+                if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_pin, first_name, last_name, official_account, image_id, device_id, offline_mode, user_type, ex_block, ex_offmp FROM BUDDY where official_account<>'1' and f_pin <> '\(idMe!)' order by 4 desc, 2 collate nocase asc") {
+                    while cursorData.next() {
+                        var row: [String: String?] = [:]
+                        row["f_pin"] = cursorData.string(forColumnIndex: 0)
+                        if(connectedCall.count > 0 && connectedCall.contains(where: { $0["f_pin"] == row["f_pin"] })) {
+                            continue
+                        }
+                        var name = ""
+                        if let firstname = cursorData.string(forColumnIndex: 1) {
+                             name = firstname
+                        }
+                        if let lastname = cursorData.string(forColumnIndex: 2) {
+                            name = name + " " + lastname
+                        }
+                        if name.trimmingCharacters(in: .whitespaces) == "USR\(row["f_pin"]!!)" {
+                            continue
+                        }
+                        row["block"] = cursorData.string(forColumnIndex: 8)
+                        if row["block"] == "1" || row["block"] == "-1" {
+                            continue
+                        }
+                        row["name"] = name
+                        row["picture"] = cursorData.string(forColumnIndex: 4)
+                        row["isOfficial"] = cursorData.string(forColumnIndex: 3)
+                        row["deviceId"] = cursorData.string(forColumnIndex: 5)
+                        row["isOffline"] = cursorData.string(forColumnIndex: 6)
+                        row["user_type"] = cursorData.string(forColumnIndex: 7)
+                        row["ex_offmp"] = cursorData.string(forColumnIndex: 7)
+                        dataPerson.append(row)
                     }
-                    var name = ""
-                    if let firstname = cursorData.string(forColumnIndex: 1) {
-                         name = firstname
-                    }
-                    if let lastname = cursorData.string(forColumnIndex: 2) {
-                        name = name + " " + lastname
-                    }
-                    if name.trimmingCharacters(in: .whitespaces) == "USR\(row["f_pin"]!!)" {
-                        continue
-                    }
-                    row["block"] = cursorData.string(forColumnIndex: 8)
-                    if row["block"] == "1" || row["block"] == "-1" {
-                        continue
-                    }
-                    row["name"] = name
-                    row["picture"] = cursorData.string(forColumnIndex: 4)
-                    row["isOfficial"] = cursorData.string(forColumnIndex: 3)
-                    row["deviceId"] = cursorData.string(forColumnIndex: 5)
-                    row["isOffline"] = cursorData.string(forColumnIndex: 6)
-                    row["user_type"] = cursorData.string(forColumnIndex: 7)
-                    row["ex_offmp"] = cursorData.string(forColumnIndex: 7)
-                    dataPerson.append(row)
+                    cursorData.close()
                 }
-                cursorData.close()
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
     }

+ 254 - 249
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/BackupRestoreView.swift

@@ -478,7 +478,7 @@ public class BackupRestoreView: UIViewController, UITableViewDataSource, UITable
                 recordSizeRestore += 1
             } catch {
                 rollback.pointee = true
-                //print(error)
+                print("Access database error: \(error.localizedDescription)")
             }
         })
     }
@@ -494,7 +494,7 @@ public class BackupRestoreView: UIViewController, UITableViewDataSource, UITable
                 recordSizeRestore += 1
             } catch {
                 rollback.pointee = true
-                //print(error)
+                print("Access database error: \(error.localizedDescription)")
             }
         })
     }
@@ -519,7 +519,7 @@ public class BackupRestoreView: UIViewController, UITableViewDataSource, UITable
                 recordSizeRestore += 1
             } catch {
                 rollback.pointee = true
-                //print(error)
+                print("Access database error: \(error.localizedDescription)")
             }
         })
     }
@@ -544,7 +544,7 @@ public class BackupRestoreView: UIViewController, UITableViewDataSource, UITable
                 recordSizeRestore += 1
             } catch {
                 rollback.pointee = true
-                //print(error)
+                print("Access database error: \(error.localizedDescription)")
             }
         })
     }
@@ -569,7 +569,7 @@ public class BackupRestoreView: UIViewController, UITableViewDataSource, UITable
                 recordSizeRestore += 1
             } catch {
                 rollback.pointee = true
-                //print(error)
+                print("Access database error: \(error.localizedDescription)")
             }
         })
     }
@@ -664,286 +664,291 @@ public class BackupRestoreView: UIViewController, UITableViewDataSource, UITable
     
     private func backupData(indexPath: IndexPath) {
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            let documentDirectoryUrl = try! FileManager.default.url(
-                for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true
-            )
-            var recordSize: Int64 = 0
-            
-            //Make File MESSAGE
-            let file_message = documentDirectoryUrl.appendingPathComponent("MESSAGE").appendingPathExtension("")
-            if let tableInfo = Database.shared.getRecords(fmdb: fmdb,query: "PRAGMA table_info(MESSAGE)") {
-                var text_message = ""
-                while tableInfo.next() {
-                    if text_message.isEmpty {
-                        text_message.append(tableInfo.string(forColumn: "name")!)
-                    } else {
-                        text_message.append(separator)
-                        text_message.append(tableInfo.string(forColumn: "name")!)
-                    }
-                }
-                text_message.append("\n")
-                tableInfo.close()
+            do {
+                let documentDirectoryUrl = try! FileManager.default.url(
+                    for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true
+                )
+                var recordSize: Int64 = 0
                 
-                if let cursorData = Database.shared.getRecords(fmdb: fmdb,query: "SELECT * FROM MESSAGE") {
-                    let columnCount = cursorData.columnCount
-                    var value_m = ""
-                    while cursorData.next() {
-                        for i in 0..<columnCount {
-                            value_m.append(cursorData.string(forColumnIndex: i) == nil ? "null" : cursorData.string(forColumnIndex: i)!.isEmpty ? "<empty>" : cursorData.string(forColumnIndex: i)!)
-                            value_m.append(separator)
+                //Make File MESSAGE
+                let file_message = documentDirectoryUrl.appendingPathComponent("MESSAGE").appendingPathExtension("")
+                if let tableInfo = Database.shared.getRecords(fmdb: fmdb,query: "PRAGMA table_info(MESSAGE)") {
+                    var text_message = ""
+                    while tableInfo.next() {
+                        if text_message.isEmpty {
+                            text_message.append(tableInfo.string(forColumn: "name")!)
+                        } else {
+                            text_message.append(separator)
+                            text_message.append(tableInfo.string(forColumn: "name")!)
                         }
-                        value_m.append("\n")
-                        recordSize += 1
                     }
-                    text_message.append(value_m)
-                    cursorData.close()
-                }
-                do {
-                    try text_message.write(to: file_message, atomically: true, encoding: .utf8)
-                }
-                catch {
-                    //print(error)
-                }
-            }
-            
-            //Make File UC_LIST
-            let file_uc_list = documentDirectoryUrl.appendingPathComponent("UC_LIST").appendingPathExtension("")
-            if let tableInfo = Database.shared.getRecords(fmdb: fmdb,query: "PRAGMA table_info(MESSAGE_SUMMARY)") {
-                var text_uc_list = ""
-                while tableInfo.next() {
-                    if tableInfo.string(forColumn: "name")! == "counter" {
-                        continue
+                    text_message.append("\n")
+                    tableInfo.close()
+                    
+                    if let cursorData = Database.shared.getRecords(fmdb: fmdb,query: "SELECT * FROM MESSAGE") {
+                        let columnCount = cursorData.columnCount
+                        var value_m = ""
+                        while cursorData.next() {
+                            for i in 0..<columnCount {
+                                value_m.append(cursorData.string(forColumnIndex: i) == nil ? "null" : cursorData.string(forColumnIndex: i)!.isEmpty ? "<empty>" : cursorData.string(forColumnIndex: i)!)
+                                value_m.append(separator)
+                            }
+                            value_m.append("\n")
+                            recordSize += 1
+                        }
+                        text_message.append(value_m)
+                        cursorData.close()
                     }
-                    if text_uc_list.isEmpty {
-                        text_uc_list.append(tableInfo.string(forColumn: "name")! == "l_pin" ? "opposite" : tableInfo.string(forColumn: "name")!)
-                    } else {
-                        text_uc_list.append(separator)
-                        text_uc_list.append(tableInfo.string(forColumn: "name")! == "l_pin" ? "opposite" : tableInfo.string(forColumn: "name")!)
+                    do {
+                        try text_message.write(to: file_message, atomically: true, encoding: .utf8)
+                    }
+                    catch {
+                        //print(error)
                     }
                 }
-                text_uc_list.append("\n")
-                tableInfo.close()
                 
-                if let cursorData = Database.shared.getRecords(fmdb: fmdb,query: "SELECT * FROM MESSAGE_SUMMARY") {
-                    let columnCount = cursorData.columnCount
-                    var value_m = ""
-                    while cursorData.next() {
-                        for i in 0..<columnCount - 1 {
-                            value_m.append(cursorData.string(forColumnIndex: i) == nil ? "null" : cursorData.string(forColumnIndex: i)!.isEmpty ? "<empty>" : cursorData.string(forColumnIndex: i)!)
-                            value_m.append(separator)
+                //Make File UC_LIST
+                let file_uc_list = documentDirectoryUrl.appendingPathComponent("UC_LIST").appendingPathExtension("")
+                if let tableInfo = Database.shared.getRecords(fmdb: fmdb,query: "PRAGMA table_info(MESSAGE_SUMMARY)") {
+                    var text_uc_list = ""
+                    while tableInfo.next() {
+                        if tableInfo.string(forColumn: "name")! == "counter" {
+                            continue
+                        }
+                        if text_uc_list.isEmpty {
+                            text_uc_list.append(tableInfo.string(forColumn: "name")! == "l_pin" ? "opposite" : tableInfo.string(forColumn: "name")!)
+                        } else {
+                            text_uc_list.append(separator)
+                            text_uc_list.append(tableInfo.string(forColumn: "name")! == "l_pin" ? "opposite" : tableInfo.string(forColumn: "name")!)
                         }
-                        value_m.append("\n")
-                        recordSize += 1
                     }
-                    text_uc_list.append(value_m)
-                    cursorData.close()
-                }
-                do {
-                    try text_uc_list.write(to: file_uc_list, atomically: true, encoding: .utf8)
-                }
-                catch {//print(error)
+                    text_uc_list.append("\n")
+                    tableInfo.close()
                     
-                }
-            }
-            
-            //Make File FORM_DATA
-            let file_form_data = documentDirectoryUrl.appendingPathComponent("FORM_DATA").appendingPathExtension("")
-            if let tableInfo = Database.shared.getRecords(fmdb: fmdb,query: "PRAGMA table_info(FORM_DATA)") {
-                var text_form_data = ""
-                while tableInfo.next() {
-                    if text_form_data.isEmpty {
-                        text_form_data.append(tableInfo.string(forColumn: "name")!)
-                    } else {
-                        text_form_data.append(separator)
-                        text_form_data.append(tableInfo.string(forColumn: "name")!)
+                    if let cursorData = Database.shared.getRecords(fmdb: fmdb,query: "SELECT * FROM MESSAGE_SUMMARY") {
+                        let columnCount = cursorData.columnCount
+                        var value_m = ""
+                        while cursorData.next() {
+                            for i in 0..<columnCount - 1 {
+                                value_m.append(cursorData.string(forColumnIndex: i) == nil ? "null" : cursorData.string(forColumnIndex: i)!.isEmpty ? "<empty>" : cursorData.string(forColumnIndex: i)!)
+                                value_m.append(separator)
+                            }
+                            value_m.append("\n")
+                            recordSize += 1
+                        }
+                        text_uc_list.append(value_m)
+                        cursorData.close()
+                    }
+                    do {
+                        try text_uc_list.write(to: file_uc_list, atomically: true, encoding: .utf8)
+                    }
+                    catch {//print(error)
+                        
                     }
                 }
-                text_form_data.append("\n")
-                tableInfo.close()
                 
-                if let cursorData = Database.shared.getRecords(fmdb: fmdb,query: "SELECT * FROM FORM_DATA") {
-                    let columnCount = cursorData.columnCount
-                    var value_m = ""
-                    while cursorData.next() {
-                        for i in 0..<columnCount - 1 {
-                            value_m.append(cursorData.string(forColumnIndex: i) == nil ? "null" : cursorData.string(forColumnIndex: i)!.isEmpty ? "<empty>" : cursorData.string(forColumnIndex: i)!)
-                            value_m.append(separator)
+                //Make File FORM_DATA
+                let file_form_data = documentDirectoryUrl.appendingPathComponent("FORM_DATA").appendingPathExtension("")
+                if let tableInfo = Database.shared.getRecords(fmdb: fmdb,query: "PRAGMA table_info(FORM_DATA)") {
+                    var text_form_data = ""
+                    while tableInfo.next() {
+                        if text_form_data.isEmpty {
+                            text_form_data.append(tableInfo.string(forColumn: "name")!)
+                        } else {
+                            text_form_data.append(separator)
+                            text_form_data.append(tableInfo.string(forColumn: "name")!)
                         }
-                        value_m.append("\n")
-                        recordSize += 1
                     }
-                    text_form_data.append(value_m)
-                    cursorData.close()
-                }
-                do {
-                    try text_form_data.write(to: file_form_data, atomically: true, encoding: .utf8)
-                }
-                catch {//print(error)
+                    text_form_data.append("\n")
+                    tableInfo.close()
                     
-                }
-            }
-            
-            //Make File TASK_PIC
-            let file_task_pic = documentDirectoryUrl.appendingPathComponent("TASK_PIC").appendingPathExtension("")
-            if let tableInfo = Database.shared.getRecords(fmdb: fmdb,query: "PRAGMA table_info(TASK_PIC)") {
-                var text_task_pic = ""
-                while tableInfo.next() {
-                    if text_task_pic.isEmpty {
-                        text_task_pic.append(tableInfo.string(forColumn: "name")!)
-                    } else {
-                        text_task_pic.append(separator)
-                        text_task_pic.append(tableInfo.string(forColumn: "name")!)
+                    if let cursorData = Database.shared.getRecords(fmdb: fmdb,query: "SELECT * FROM FORM_DATA") {
+                        let columnCount = cursorData.columnCount
+                        var value_m = ""
+                        while cursorData.next() {
+                            for i in 0..<columnCount - 1 {
+                                value_m.append(cursorData.string(forColumnIndex: i) == nil ? "null" : cursorData.string(forColumnIndex: i)!.isEmpty ? "<empty>" : cursorData.string(forColumnIndex: i)!)
+                                value_m.append(separator)
+                            }
+                            value_m.append("\n")
+                            recordSize += 1
+                        }
+                        text_form_data.append(value_m)
+                        cursorData.close()
+                    }
+                    do {
+                        try text_form_data.write(to: file_form_data, atomically: true, encoding: .utf8)
+                    }
+                    catch {//print(error)
+                        
                     }
                 }
-                text_task_pic.append("\n")
-                tableInfo.close()
                 
-                if let cursorData = Database.shared.getRecords(fmdb: fmdb,query: "SELECT * FROM TASK_PIC") {
-                    let columnCount = cursorData.columnCount
-                    var value_m = ""
-                    while cursorData.next() {
-                        for i in 0..<columnCount - 1 {
-                            value_m.append(cursorData.string(forColumnIndex: i) == nil ? "null" : cursorData.string(forColumnIndex: i)!.isEmpty ? "<empty>" : cursorData.string(forColumnIndex: i)!)
-                            value_m.append(separator)
+                //Make File TASK_PIC
+                let file_task_pic = documentDirectoryUrl.appendingPathComponent("TASK_PIC").appendingPathExtension("")
+                if let tableInfo = Database.shared.getRecords(fmdb: fmdb,query: "PRAGMA table_info(TASK_PIC)") {
+                    var text_task_pic = ""
+                    while tableInfo.next() {
+                        if text_task_pic.isEmpty {
+                            text_task_pic.append(tableInfo.string(forColumn: "name")!)
+                        } else {
+                            text_task_pic.append(separator)
+                            text_task_pic.append(tableInfo.string(forColumn: "name")!)
                         }
-                        value_m.append("\n")
-                        recordSize += 1
                     }
-                    text_task_pic.append(value_m)
-                    cursorData.close()
-                }
-                do {
-                    try text_task_pic.write(to: file_task_pic, atomically: true, encoding: .utf8)
-                }
-                catch {//print(error)
+                    text_task_pic.append("\n")
+                    tableInfo.close()
                     
-                }
-            }
-            
-            //Make File TASK_DETAIL
-            let file_task_detail = documentDirectoryUrl.appendingPathComponent("TASK_DETAIL").appendingPathExtension("")
-            if let tableInfo = Database.shared.getRecords(fmdb: fmdb,query: "PRAGMA table_info(TASK_DETAIL)") {
-                var text_task_detail = ""
-                while tableInfo.next() {
-                    if text_task_detail.isEmpty {
-                        text_task_detail.append(tableInfo.string(forColumn: "name")!)
-                    } else {
-                        text_task_detail.append(separator)
-                        text_task_detail.append(tableInfo.string(forColumn: "name")!)
+                    if let cursorData = Database.shared.getRecords(fmdb: fmdb,query: "SELECT * FROM TASK_PIC") {
+                        let columnCount = cursorData.columnCount
+                        var value_m = ""
+                        while cursorData.next() {
+                            for i in 0..<columnCount - 1 {
+                                value_m.append(cursorData.string(forColumnIndex: i) == nil ? "null" : cursorData.string(forColumnIndex: i)!.isEmpty ? "<empty>" : cursorData.string(forColumnIndex: i)!)
+                                value_m.append(separator)
+                            }
+                            value_m.append("\n")
+                            recordSize += 1
+                        }
+                        text_task_pic.append(value_m)
+                        cursorData.close()
+                    }
+                    do {
+                        try text_task_pic.write(to: file_task_pic, atomically: true, encoding: .utf8)
+                    }
+                    catch {//print(error)
+                        
                     }
                 }
-                text_task_detail.append("\n")
-                tableInfo.close()
                 
-                if let cursorData = Database.shared.getRecords(fmdb: fmdb,query: "SELECT * FROM TASK_DETAIL") {
-                    let columnCount = cursorData.columnCount
-                    var value_m = ""
-                    while cursorData.next() {
-                        for i in 0..<columnCount - 1 {
-                            value_m.append(cursorData.string(forColumnIndex: i) == nil ? "null" : cursorData.string(forColumnIndex: i)!.isEmpty ? "<empty>" : cursorData.string(forColumnIndex: i)!)
-                            value_m.append(separator)
+                //Make File TASK_DETAIL
+                let file_task_detail = documentDirectoryUrl.appendingPathComponent("TASK_DETAIL").appendingPathExtension("")
+                if let tableInfo = Database.shared.getRecords(fmdb: fmdb,query: "PRAGMA table_info(TASK_DETAIL)") {
+                    var text_task_detail = ""
+                    while tableInfo.next() {
+                        if text_task_detail.isEmpty {
+                            text_task_detail.append(tableInfo.string(forColumn: "name")!)
+                        } else {
+                            text_task_detail.append(separator)
+                            text_task_detail.append(tableInfo.string(forColumn: "name")!)
                         }
-                        value_m.append("\n")
-                        recordSize += 1
                     }
-                    text_task_detail.append(value_m)
-                    cursorData.close()
-                }
-                do {
-                    try text_task_detail.write(to: file_task_detail, atomically: true, encoding: .utf8)
-                }
-                catch {//print(error)
+                    text_task_detail.append("\n")
+                    tableInfo.close()
                     
+                    if let cursorData = Database.shared.getRecords(fmdb: fmdb,query: "SELECT * FROM TASK_DETAIL") {
+                        let columnCount = cursorData.columnCount
+                        var value_m = ""
+                        while cursorData.next() {
+                            for i in 0..<columnCount - 1 {
+                                value_m.append(cursorData.string(forColumnIndex: i) == nil ? "null" : cursorData.string(forColumnIndex: i)!.isEmpty ? "<empty>" : cursorData.string(forColumnIndex: i)!)
+                                value_m.append(separator)
+                            }
+                            value_m.append("\n")
+                            recordSize += 1
+                        }
+                        text_task_detail.append(value_m)
+                        cursorData.close()
+                    }
+                    do {
+                        try text_task_detail.write(to: file_task_detail, atomically: true, encoding: .utf8)
+                    }
+                    catch {//print(error)
+                        
+                    }
                 }
-            }
-            
-            //ZIP ALL FILES
-            let fileManager = FileManager()
-            var destinationURL = documentDirectoryUrl
-            destinationURL.appendPathComponent("zipItem\(Date().currentTimeMillis())")
-//            let listFiles: [URL] = [file_message, file_uc_list, file_form_data, file_task_pic, file_task_detail]
-            do {
-                try fileManager.createDirectory(at: destinationURL, withIntermediateDirectories: true, attributes: nil)
-                let zipFiles = destinationURL.appendingPathComponent(getFileName(option: choosenOption, fileId: fileIdBackup, withoutZIP: true)).appendingPathExtension("zip")
-//                try Zip.zipFiles(paths: listFiles, zipFilePath: zipFiles, password: nil, progress: {progress in
-//                    self.labelPreparing.text = "Preparing...".localized() + " \(progress * 100)%"
-//                })
-                let unzipProgress = Progress()
-                let observation = unzipProgress.observe(\.fractionCompleted) { progress, _ in
-                    self.labelPreparing.text = "Preparing...".localized() + " \(progress.fractionCompleted * 100)%"
-                }
-                try fileManager.zipItem(at: file_message, to: zipFiles, progress: unzipProgress)
-                guard let archive = Archive(url: zipFiles, accessMode: .update) else  {
-                    return
-                }
+                
+                //ZIP ALL FILES
+                let fileManager = FileManager()
+                var destinationURL = documentDirectoryUrl
+                destinationURL.appendPathComponent("zipItem\(Date().currentTimeMillis())")
+    //            let listFiles: [URL] = [file_message, file_uc_list, file_form_data, file_task_pic, file_task_detail]
                 do {
-                    try archive.addEntry(with: file_uc_list.lastPathComponent, relativeTo: file_uc_list.deletingLastPathComponent())
-                    try archive.addEntry(with: file_form_data.lastPathComponent, relativeTo: file_form_data.deletingLastPathComponent())
-                    try archive.addEntry(with: file_task_pic.lastPathComponent, relativeTo: file_task_pic.deletingLastPathComponent())
-                    try archive.addEntry(with: file_task_detail.lastPathComponent, relativeTo: file_task_detail.deletingLastPathComponent())
-                } catch {
-                    //print("Adding entry to ZIP archive failed with error:\(error)")
-                }
-                self.labelPreparing.text = "Uploading...".localized()
-                Network().uploadHTTP(fileUrl: zipFiles, completion: { result,progress,response in
-                    if result {
-                        DispatchQueue.main.async { [self] in
-                            labelPreparing.text = "Uploading...".localized() + " \(progress)%"
-                            if progress == 100 {
-                                do {
-                                    let path = zipFiles.path
-                                    let attrib = try FileManager.default.attributesOfItem(atPath: path)
-                                    let fileSize = attrib[.size] as! Int64
-                                    DispatchQueue.global().async { [self] in
-                                        _ = Nexilis.write(message: CoreMessage_TMessageBank.getBackupUploaded(option: choosenOption, fileid: fileIdBackup, filesize: String(fileSize), recordSize: String(recordSize)))
-                                    }
-                                    let date = Date()
-                                    let calendar = Calendar.current
-                                    
-                                    if (calendar.isDateInToday(date)) {
-                                        dayLastBackup = "Today".localized()
-                                    } else {
-                                        let startOfNow = calendar.startOfDay(for: Date())
-                                        let startOfTimeStamp = calendar.startOfDay(for: date)
-                                        let components = calendar.dateComponents([.day], from: startOfNow, to: startOfTimeStamp)
-                                        let day = -(components.day!)
-                                        if day == 1{
-                                            dayLastBackup = "Yesterday".localized()
+                    try fileManager.createDirectory(at: destinationURL, withIntermediateDirectories: true, attributes: nil)
+                    let zipFiles = destinationURL.appendingPathComponent(getFileName(option: choosenOption, fileId: fileIdBackup, withoutZIP: true)).appendingPathExtension("zip")
+    //                try Zip.zipFiles(paths: listFiles, zipFilePath: zipFiles, password: nil, progress: {progress in
+    //                    self.labelPreparing.text = "Preparing...".localized() + " \(progress * 100)%"
+    //                })
+                    let unzipProgress = Progress()
+                    let observation = unzipProgress.observe(\.fractionCompleted) { progress, _ in
+                        self.labelPreparing.text = "Preparing...".localized() + " \(progress.fractionCompleted * 100)%"
+                    }
+                    try fileManager.zipItem(at: file_message, to: zipFiles, progress: unzipProgress)
+                    guard let archive = Archive(url: zipFiles, accessMode: .update) else  {
+                        return
+                    }
+                    do {
+                        try archive.addEntry(with: file_uc_list.lastPathComponent, relativeTo: file_uc_list.deletingLastPathComponent())
+                        try archive.addEntry(with: file_form_data.lastPathComponent, relativeTo: file_form_data.deletingLastPathComponent())
+                        try archive.addEntry(with: file_task_pic.lastPathComponent, relativeTo: file_task_pic.deletingLastPathComponent())
+                        try archive.addEntry(with: file_task_detail.lastPathComponent, relativeTo: file_task_detail.deletingLastPathComponent())
+                    } catch {
+                        //print("Adding entry to ZIP archive failed with error:\(error)")
+                    }
+                    self.labelPreparing.text = "Uploading...".localized()
+                    Network().uploadHTTP(fileUrl: zipFiles, completion: { result,progress,response in
+                        if result {
+                            DispatchQueue.main.async { [self] in
+                                labelPreparing.text = "Uploading...".localized() + " \(progress)%"
+                                if progress == 100 {
+                                    do {
+                                        let path = zipFiles.path
+                                        let attrib = try FileManager.default.attributesOfItem(atPath: path)
+                                        let fileSize = attrib[.size] as! Int64
+                                        DispatchQueue.global().async { [self] in
+                                            _ = Nexilis.write(message: CoreMessage_TMessageBank.getBackupUploaded(option: choosenOption, fileid: fileIdBackup, filesize: String(fileSize), recordSize: String(recordSize)))
+                                        }
+                                        let date = Date()
+                                        let calendar = Calendar.current
+                                        
+                                        if (calendar.isDateInToday(date)) {
+                                            dayLastBackup = "Today".localized()
                                         } else {
-                                            let formatter = DateFormatter()
-                                            formatter.dateFormat = "dd MMMM yyyy"
-                                            let lang: String = SecureUserDefaults.shared.value(forKey: "i18n_language") ?? "en"
-                                            if lang == "id" {
-                                                formatter.locale = NSLocale(localeIdentifier: "id") as Locale?
+                                            let startOfNow = calendar.startOfDay(for: Date())
+                                            let startOfTimeStamp = calendar.startOfDay(for: date)
+                                            let components = calendar.dateComponents([.day], from: startOfNow, to: startOfTimeStamp)
+                                            let day = -(components.day!)
+                                            if day == 1{
+                                                dayLastBackup = "Yesterday".localized()
+                                            } else {
+                                                let formatter = DateFormatter()
+                                                formatter.dateFormat = "dd MMMM yyyy"
+                                                let lang: String = SecureUserDefaults.shared.value(forKey: "i18n_language") ?? "en"
+                                                if lang == "id" {
+                                                    formatter.locale = NSLocale(localeIdentifier: "id") as Locale?
+                                                }
+                                                let stringFormat = formatter.string(from: date as Date)
+                                                dayLastBackup = stringFormat
                                             }
-                                            let stringFormat = formatter.string(from: date as Date)
-                                            dayLastBackup = stringFormat
                                         }
-                                    }
-                                    
-                                    let formatter = DateFormatter()
-                                    formatter.dateFormat = "HH:mm"
-                                    formatter.locale = NSLocale(localeIdentifier: "id") as Locale?
-                                    timeLastBackup = formatter.string(from: date as Date)
-                                    
-                                    valueLastBackup = dayLastBackup.localized() + ", " + timeLastBackup
-                                    valuesizeBackup = Units(bytes: fileSize).getReadableUnit()
-                                    
-                                    labelPreparing.text = "Successfully Backup Data".localized()
-                                    DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: { [self] in
-                                        isBackupStart = false
-                                        tableView.beginUpdates()
-                                        tableView.reloadRows(at: [indexPath, IndexPath(row: 0, section: 0)], with: .none)
-                                        tableView.reloadSections(IndexSet(integer: 2), with: .none)
-                                        tableView.endUpdates()
-                                    })
-                                } catch {}
+                                        
+                                        let formatter = DateFormatter()
+                                        formatter.dateFormat = "HH:mm"
+                                        formatter.locale = NSLocale(localeIdentifier: "id") as Locale?
+                                        timeLastBackup = formatter.string(from: date as Date)
+                                        
+                                        valueLastBackup = dayLastBackup.localized() + ", " + timeLastBackup
+                                        valuesizeBackup = Units(bytes: fileSize).getReadableUnit()
+                                        
+                                        labelPreparing.text = "Successfully Backup Data".localized()
+                                        DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: { [self] in
+                                            isBackupStart = false
+                                            tableView.beginUpdates()
+                                            tableView.reloadRows(at: [indexPath, IndexPath(row: 0, section: 0)], with: .none)
+                                            tableView.reloadSections(IndexSet(integer: 2), with: .none)
+                                            tableView.endUpdates()
+                                        })
+                                    } catch {}
+                                }
                             }
                         }
-                    }
-                })
+                    })
+                } catch {
+                    //print(error)
+                }
             } catch {
-                //print(error)
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
     }

+ 7 - 2
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/BroadcastMembersTableViewController.swift

@@ -164,7 +164,7 @@ class BroadcastMembersTableViewController: UITableViewController, UISearchContro
                     }
                 } catch {
                     rollback.pointee = true
-                    //print(error)
+                    print("Access database error: \(error.localizedDescription)")
                 }
                 completion()
             })
@@ -244,7 +244,12 @@ class BroadcastMembersTableViewController: UITableViewController, UISearchContro
     private func getGroups(id: String = "", parent: String = "", completion: @escaping ([Group]) -> ()) {
         DispatchQueue.global().async {
             Database.shared.database?.inTransaction({ fmdb, rollback in
-                completion(self.getGroupRecursive(fmdb: fmdb, id: id, parent: parent))
+                do {
+                    completion(self.getGroupRecursive(fmdb: fmdb, id: id, parent: parent))
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
+                }
             })
         }
     }

+ 15 - 10
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/BroadcastViewController.swift

@@ -153,17 +153,22 @@ class BroadcastViewController: UITableViewController, UITextFieldDelegate, UITex
         
         let query = "select f.id, f.form_id, f.name, f.created_date, f.created_by, f.sq_no from FORM f"
         Database.shared.database?.inTransaction({ fmdb, rollback in
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: query) {
-                while cursor.next() {
-                    var form = Form()
-                    form.id = cursor.long(forColumnIndex: 0)
-                    form.formId = cursor.string(forColumnIndex: 1)!
-                    form.title = cursor.string(forColumnIndex: 2)!
-                    form.createdDate = Int(cursor.string(forColumnIndex: 3)!)!
-                    form.createdBy = cursor.string(forColumnIndex: 4)!
-                    form.sqNo = Int(cursor.int(forColumnIndex: 5))
-                    forms.append(form)
+            do {
+                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: query) {
+                    while cursor.next() {
+                        var form = Form()
+                        form.id = cursor.long(forColumnIndex: 0)
+                        form.formId = cursor.string(forColumnIndex: 1)!
+                        form.title = cursor.string(forColumnIndex: 2)!
+                        form.createdDate = Int(cursor.string(forColumnIndex: 3)!)!
+                        form.createdBy = cursor.string(forColumnIndex: 4)!
+                        form.sqNo = Int(cursor.int(forColumnIndex: 5))
+                        forms.append(form)
+                    }
                 }
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         // Do any additional setup after loading the view.

+ 3 - 0
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/ChangeDeviceViewController.swift

@@ -225,6 +225,9 @@ public class ChangeDeviceViewController: UIViewController {
             banner.show()
             return
         }
+        if Database.shared.openDatabase() == 0 {
+            return
+        }
         Nexilis.showLoader()
         DispatchQueue.global().async {
             let md5Hex = password

+ 6 - 1
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/ChangeNamePassswordViewController.swift

@@ -156,7 +156,12 @@ public class ChangeNamePassswordViewController: UIViewController {
                     if let resp2 = Nexilis.writeAndWait(message: tMessage){
                         if resp2.isOk() {
                             Database.shared.database?.inTransaction({ fmdb, rollback in
-                                _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: ["first_name": first , "last_name": last], _where: "f_pin = '\(idMe)'")
+                                do {
+                                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: ["first_name": first , "last_name": last], _where: "f_pin = '\(idMe)'")
+                                } catch {
+                                    rollback.pointee = true
+                                    print("Access database error: \(error.localizedDescription)")
+                                }
                             })
                             Utils.setProfile(value: true)
                             SecureUserDefaults.shared.sync()

+ 14 - 4
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/ChangeNameTableViewController.swift

@@ -26,9 +26,14 @@ class ChangeNameTableViewController: UITableViewController {
         navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Save".localized(), style: .plain, target: self, action: #selector(save(sender:)))
         
         Database.shared.database?.inTransaction({ fmdb, rollback in
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select FIRST_NAME || ' ' || ifnull(LAST_NAME, '') from BUDDY where F_PIN = '\(data)'"), cursor.next() {
-                name.text = cursor.string(forColumnIndex: 0)?.trimmingCharacters(in: .whitespaces)
-                cursor.close()
+            do {
+                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select FIRST_NAME || ' ' || ifnull(LAST_NAME, '') from BUDDY where F_PIN = '\(data)'"), cursor.next() {
+                    name.text = cursor.string(forColumnIndex: 0)?.trimmingCharacters(in: .whitespaces)
+                    cursor.close()
+                }
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         name.placeholder = "Name".localized()
@@ -45,7 +50,12 @@ class ChangeNameTableViewController: UITableViewController {
             if let resp = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getChangePersonInfoName(firstname: first, lastname: last)) {
                 if resp.isOk() {
                     Database.shared.database?.inTransaction({ fmdb, rollback in
-                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: ["first_name": first , "last_name": last], _where: "f_pin = '\(self.data)'")
+                        do {
+                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: ["first_name": first , "last_name": last], _where: "f_pin = '\(self.data)'")
+                        } catch {
+                            rollback.pointee = true
+                            print("Access database error: \(error.localizedDescription)")
+                        }
                     })
                     NotificationCenter.default.post(name: NSNotification.Name(rawValue: "updateFifthTab"), object: nil, userInfo: nil)
                     DispatchQueue.main.async {

+ 65 - 40
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/ContactChatViewController.swift

@@ -85,9 +85,14 @@ class ContactChatViewController: UITableViewController {
         super.viewDidLoad()
         let me = User.getMyPin()!
         Database.shared.database?.inTransaction({ fmdb, rollback in
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select FIRST_NAME, LAST_NAME, IMAGE_ID, USER_TYPE from BUDDY where F_PIN = '\(me)'"), cursor.next() {
-                isAdmin = cursor.string(forColumnIndex: 3) == "23" || cursor.string(forColumnIndex: 3) == "24"
-                cursor.close()
+            do {
+                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select FIRST_NAME, LAST_NAME, IMAGE_ID, USER_TYPE from BUDDY where F_PIN = '\(me)'"), cursor.next() {
+                    isAdmin = cursor.string(forColumnIndex: 3) == "23" || cursor.string(forColumnIndex: 3) == "24"
+                    cursor.close()
+                }
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         
@@ -408,24 +413,29 @@ class ContactChatViewController: UITableViewController {
         contacts.append(gptUser)
         DispatchQueue.global().async {
             Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_pin, first_name, last_name, image_id, official_account, user_type FROM BUDDY where f_pin <> '\(User.getMyPin()!)' order by 5 desc, 2 collate nocase asc") {
-                    while cursorData.next() {
-                        let user = User(pin: cursorData.string(forColumnIndex: 0) ?? "",
-                                        firstName: cursorData.string(forColumnIndex: 1) ?? "",
-                                        lastName: cursorData.string(forColumnIndex: 2) ?? "",
-                                        thumb: cursorData.string(forColumnIndex: 3) ?? "",
-                                        userType: cursorData.string(forColumnIndex: 5) ?? "")
-                        if (user.firstName + " " + user.lastName).trimmingCharacters(in: .whitespaces) == "USR\(user.pin)" {
-                            continue
-                        }
-                        user.official = cursorData.string(forColumnIndex: 4) ?? ""
-                        if !self.contacts.contains(where: {$0.pin == user.pin}) {
-                            self.contacts.append(user)
+                do {
+                    if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_pin, first_name, last_name, image_id, official_account, user_type FROM BUDDY where f_pin <> '\(User.getMyPin()!)' order by 5 desc, 2 collate nocase asc") {
+                        while cursorData.next() {
+                            let user = User(pin: cursorData.string(forColumnIndex: 0) ?? "",
+                                            firstName: cursorData.string(forColumnIndex: 1) ?? "",
+                                            lastName: cursorData.string(forColumnIndex: 2) ?? "",
+                                            thumb: cursorData.string(forColumnIndex: 3) ?? "",
+                                            userType: cursorData.string(forColumnIndex: 5) ?? "")
+                            if (user.firstName + " " + user.lastName).trimmingCharacters(in: .whitespaces) == "USR\(user.pin)" {
+                                continue
+                            }
+                            user.official = cursorData.string(forColumnIndex: 4) ?? ""
+                            if !self.contacts.contains(where: {$0.pin == user.pin}) {
+                                self.contacts.append(user)
+                            }
                         }
+                        cursorData.close()
                     }
-                    cursorData.close()
+                    completion()
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
                 }
-                completion()
             })
         }
     }
@@ -544,7 +554,12 @@ class ContactChatViewController: UITableViewController {
     private func getGroups(id: String = "", parent: String = "", completion: @escaping ([Group]) -> ()) {
         DispatchQueue.global().async {
             Database.shared.database?.inTransaction({ fmdb, rollback in
-                completion(self.getGroupRecursive(fmdb: fmdb, id: id, parent: parent))
+                do {
+                    completion(self.getGroupRecursive(fmdb: fmdb, id: id, parent: parent))
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
+                }
             })
         }
     }
@@ -765,22 +780,27 @@ extension ContactChatViewController {
         }
         if group.childs.count == 0 {
             Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                let idMe = User.getMyPin() as String?
-                if let cursorMember = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin from GROUPZ_MEMBER where group_id = '\(group.id)' and f_pin = '\(idMe!)'"), cursorMember.next() {
-                    let groupId = group.chatId.isEmpty ? group.id : group.chatId
-                    if let chooser = isChooser {
-                        chooser("4", groupId)
-                        dismiss(animated: true, completion: nil)
-                        return
+                do {
+                    let idMe = User.getMyPin() as String?
+                    if let cursorMember = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin from GROUPZ_MEMBER where group_id = '\(group.id)' and f_pin = '\(idMe!)'"), cursorMember.next() {
+                        let groupId = group.chatId.isEmpty ? group.id : group.chatId
+                        if let chooser = isChooser {
+                            chooser("4", groupId)
+                            dismiss(animated: true, completion: nil)
+                            return
+                        }
+                        self.groupMap.removeAll()
+                        let editorGroupVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorGroupVC") as! EditorGroup
+                        editorGroupVC.hidesBottomBarWhenPushed = true
+                        editorGroupVC.unique_l_pin = groupId
+                        navigationController?.show(editorGroupVC, sender: nil)
+                        cursorMember.close()
+                    } else {
+                        self.view.makeToast("You are not a member of this group".localized(), duration: 0.5)
                     }
-                    self.groupMap.removeAll()
-                    let editorGroupVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorGroupVC") as! EditorGroup
-                    editorGroupVC.hidesBottomBarWhenPushed = true
-                    editorGroupVC.unique_l_pin = groupId
-                    navigationController?.show(editorGroupVC, sender: nil)
-                    cursorMember.close()
-                } else {
-                    self.view.makeToast("You are not a member of this group".localized(), duration: 0.5)
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
                 }
             })
         } else {
@@ -1403,13 +1423,18 @@ extension ContactChatViewController {
     private func getRealStatus(messageId: String) -> String {
         var status = "1"
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            if let cursorStatus = Database.shared.getRecords(fmdb: fmdb, query: "SELECT status, f_pin FROM MESSAGE_STATUS WHERE message_id='\(messageId)'") {
-                var listStatus: [Int] = []
-                while cursorStatus.next() {
-                    listStatus.append(Int(cursorStatus.string(forColumnIndex: 0)!)!)
+            do {
+                if let cursorStatus = Database.shared.getRecords(fmdb: fmdb, query: "SELECT status, f_pin FROM MESSAGE_STATUS WHERE message_id='\(messageId)'") {
+                    var listStatus: [Int] = []
+                    while cursorStatus.next() {
+                        listStatus.append(Int(cursorStatus.string(forColumnIndex: 0)!)!)
+                    }
+                    cursorStatus.close()
+                    status = "\(listStatus.min() ?? 2)"
                 }
-                cursorStatus.close()
-                status = "\(listStatus.min() ?? 2)"
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         return status

+ 6 - 1
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/GroupDescViewController.swift

@@ -45,7 +45,12 @@ class GroupDescViewController: UITableViewController {
                 if let resp = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getChangeGroupInfo(p_group_id: self.data, p_quote: text)) {
                     if resp.isOk() {
                         Database.shared.database?.inTransaction({ fmdb, rollback in
-                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "GROUPZ", cvalues: ["quote": text], _where: "group_id = '\(self.data)'")
+                            do {
+                                _ = Database.shared.updateRecord(fmdb: fmdb, table: "GROUPZ", cvalues: ["quote": text], _where: "group_id = '\(self.data)'")
+                            } catch {
+                                rollback.pointee = true
+                                print("Access database error: \(error.localizedDescription)")
+                            }
                         })
                         DispatchQueue.main.async {
                             self.navigationController?.dismiss(animated: true, completion: {

+ 90 - 60
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/GroupDetailViewController.swift

@@ -122,9 +122,14 @@ class GroupDetailViewController: UITableViewController {
                 
                 if group.official == "1" && !group.parent.isEmpty {
                     Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                        if let cursorImage = Database.shared.getRecords(fmdb: fmdb, query: "SELECT image_id FROM GROUPZ where group_type = 1 AND official = 1"), cursorImage.next() {
-                            self.group?.profile = cursorImage.string(forColumnIndex: 0)!
-                            cursorImage.close()
+                        do {
+                            if let cursorImage = Database.shared.getRecords(fmdb: fmdb, query: "SELECT image_id FROM GROUPZ where group_type = 1 AND official = 1"), cursorImage.next() {
+                                self.group?.profile = cursorImage.string(forColumnIndex: 0)!
+                                cursorImage.close()
+                            }
+                        } catch {
+                            rollback.pointee = true
+                            print("Access database error: \(error.localizedDescription)")
                         }
                     })
                 }
@@ -224,50 +229,55 @@ class GroupDetailViewController: UITableViewController {
         DispatchQueue.global().async {
             let query = "select g.group_id, g.f_name, g.image_id, g.quote, g.created_by, g.created_date, g.parent, g.group_type, g.is_open, g.official, g.level from GROUPZ g where g.group_id = '\(self.data)'"
             Database.shared.database?.inTransaction({ fmdb, rollback in
-                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: query), cursor.next() {
-                    let group = Group(id: cursor.string(forColumnIndex: 0) ?? "",
-                                       name: cursor.string(forColumnIndex: 1) ?? "",
-                                       profile: cursor.string(forColumnIndex: 2) ?? "",
-                                       quote: cursor.string(forColumnIndex: 3) ?? "",
-                                       by: cursor.string(forColumnIndex: 4) ?? "",
-                                       date: cursor.string(forColumnIndex: 5) ?? "",
-                                       parent: cursor.string(forColumnIndex: 6) ?? "",
-                                       groupType: cursor.string(forColumnIndex: 7) ?? "",
-                                       isOpen: cursor.string(forColumnIndex: 8) ?? "",
-                                       official: cursor.string(forColumnIndex: 9) ?? "",
-                                    level: cursor.string(forColumnIndex: 10) ?? "")
-                    cursor.close()
-                    
-                    group.topics.append(Topic(chatId: "", title: "Lounge".localized(), thumb: ""))
-                    
-                    if let cursorTopic = Database.shared.getRecords(fmdb: fmdb, query: "select chat_id, title, thumb from DISCUSSION_FORUM where group_id = '\(self.data)'") {
-                        while cursorTopic.next() {
-                            let topic = Topic(chatId: cursorTopic.string(forColumnIndex: 0) ?? "",
-                                              title: cursorTopic.string(forColumnIndex: 1) ?? "",
-                                              thumb: cursorTopic.string(forColumnIndex: 2) ?? "")
-                            group.topics.append(topic)
+                do {
+                    if let cursor = Database.shared.getRecords(fmdb: fmdb, query: query), cursor.next() {
+                        let group = Group(id: cursor.string(forColumnIndex: 0) ?? "",
+                                           name: cursor.string(forColumnIndex: 1) ?? "",
+                                           profile: cursor.string(forColumnIndex: 2) ?? "",
+                                           quote: cursor.string(forColumnIndex: 3) ?? "",
+                                           by: cursor.string(forColumnIndex: 4) ?? "",
+                                           date: cursor.string(forColumnIndex: 5) ?? "",
+                                           parent: cursor.string(forColumnIndex: 6) ?? "",
+                                           groupType: cursor.string(forColumnIndex: 7) ?? "",
+                                           isOpen: cursor.string(forColumnIndex: 8) ?? "",
+                                           official: cursor.string(forColumnIndex: 9) ?? "",
+                                        level: cursor.string(forColumnIndex: 10) ?? "")
+                        cursor.close()
+                        
+                        group.topics.append(Topic(chatId: "", title: "Lounge".localized(), thumb: ""))
+                        
+                        if let cursorTopic = Database.shared.getRecords(fmdb: fmdb, query: "select chat_id, title, thumb from DISCUSSION_FORUM where group_id = '\(self.data)'") {
+                            while cursorTopic.next() {
+                                let topic = Topic(chatId: cursorTopic.string(forColumnIndex: 0) ?? "",
+                                                  title: cursorTopic.string(forColumnIndex: 1) ?? "",
+                                                  thumb: cursorTopic.string(forColumnIndex: 2) ?? "")
+                                group.topics.append(topic)
+                            }
+                            cursorTopic.close()
                         }
-                        cursorTopic.close()
-                    }
-                    
-                    if let cursorMember = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin, first_name, last_name, thumb_id, position from GROUPZ_MEMBER where group_id = '\(self.data)' order by 2 asc") {
-                        while cursorMember.next() {
-                            let member = Member(pin: cursorMember.string(forColumnIndex: 0) ?? "",
-                                            firstName: cursorMember.string(forColumnIndex: 1) ?? "",
-                                            lastName: cursorMember.string(forColumnIndex: 2) ?? "",
-                                            thumb: cursorMember.string(forColumnIndex: 3) ?? "",
-                                            position: cursorMember.string(forColumnIndex: 4) ?? "")
-                            if let cursorUser = Database.shared.getRecords(fmdb: fmdb, query: "SELECT user_type, official_account FROM BUDDY where f_pin='\(member.pin)'"), cursorUser.next() {
-                                member.userType = cursorUser.string(forColumnIndex: 0)
-                                member.official = cursorUser.string(forColumnIndex: 1)
-                                cursorUser.close()
+                        
+                        if let cursorMember = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin, first_name, last_name, thumb_id, position from GROUPZ_MEMBER where group_id = '\(self.data)' order by 2 asc") {
+                            while cursorMember.next() {
+                                let member = Member(pin: cursorMember.string(forColumnIndex: 0) ?? "",
+                                                firstName: cursorMember.string(forColumnIndex: 1) ?? "",
+                                                lastName: cursorMember.string(forColumnIndex: 2) ?? "",
+                                                thumb: cursorMember.string(forColumnIndex: 3) ?? "",
+                                                position: cursorMember.string(forColumnIndex: 4) ?? "")
+                                if let cursorUser = Database.shared.getRecords(fmdb: fmdb, query: "SELECT user_type, official_account FROM BUDDY where f_pin='\(member.pin)'"), cursorUser.next() {
+                                    member.userType = cursorUser.string(forColumnIndex: 0)
+                                    member.official = cursorUser.string(forColumnIndex: 1)
+                                    cursorUser.close()
+                                }
+                                group.members.append(member)
                             }
-                            group.members.append(member)
+                            cursorMember.close()
                         }
-                        cursorMember.close()
+                        
+                        completion(group)
                     }
-                    
-                    completion(group)
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
                 }
             })
         }
@@ -440,9 +450,14 @@ class GroupDetailViewController: UITableViewController {
                         self.removeTopic(chatId: topic.chatId) { result in
                             if result, let index = g.topics.firstIndex(of: topic) {
                                 Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "DISCUSSION_FORUM", _where: "chat_id = '\(topic.chatId)'")
-                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE", _where: "chat_id='\(topic.chatId)'")
-                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "l_pin='\(topic.chatId)'")
+                                    do {
+                                        _ = Database.shared.deleteRecord(fmdb: fmdb, table: "DISCUSSION_FORUM", _where: "chat_id = '\(topic.chatId)'")
+                                        _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE", _where: "chat_id='\(topic.chatId)'")
+                                        _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "l_pin='\(topic.chatId)'")
+                                    } catch {
+                                        rollback.pointee = true
+                                        print("Access database error: \(error.localizedDescription)")
+                                    }
                                 })
                                 var data: [AnyHashable : Any] = [:]
                                 data["code"] = CoreMessage_TMessageCode.DELETE_CHAT
@@ -706,10 +721,15 @@ class GroupDetailViewController: UITableViewController {
     private func checkIsFriend(pin: String) -> Bool {
         var isFriend = true
         Database.shared.database?.inTransaction({ fmdb, rollback in
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin from BUDDY where f_pin = '\(pin)'"), cursor.next() {
-                cursor.close()
-            } else {
-                isFriend = false
+            do {
+                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin from BUDDY where f_pin = '\(pin)'"), cursor.next() {
+                    cursor.close()
+                } else {
+                    isFriend = false
+                }
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         return isFriend
@@ -850,11 +870,16 @@ class GroupDetailViewController: UITableViewController {
                 default:
                     content.text = "Created by".localized()
                     Database.shared.database?.inTransaction({ fmdb, rollback in
-                        if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select first_name || ' ' || ifnull(last_name, '') from BUDDY where f_pin = '\(g.by)'") {
-                            if cursor.next() {
-                                content.secondaryText = cursor.string(forColumnIndex: 0) ?? "Unknown".localized()
+                        do {
+                            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select first_name || ' ' || ifnull(last_name, '') from BUDDY where f_pin = '\(g.by)'") {
+                                if cursor.next() {
+                                    content.secondaryText = cursor.string(forColumnIndex: 0) ?? "Unknown".localized()
+                                }
+                                cursor.close()
                             }
-                            cursor.close()
+                        } catch {
+                            rollback.pointee = true
+                            print("Access database error: \(error.localizedDescription)")
                         }
                     })
                 }
@@ -987,12 +1012,17 @@ extension GroupDetailViewController: ImageVideoPickerDelegate {
                         }
                         if let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getChangeGroupInfo(p_group_id: g.id, p_thumb_id: fileDir.lastPathComponent)), response.isOk() {
                             Database.shared.database?.inTransaction({ fmdb, rollback in
-                                _ = Database.shared.updateRecord(fmdb: fmdb, table: "GROUPZ", cvalues: ["image_id": fileDir.lastPathComponent], _where: "group_id = '\(g.id)'")
-                                DispatchQueue.main.async {
-                                    Nexilis.hideLoader(completion: {
-                                        self.tempImage = image
-                                        cell.profile.image = self.tempImage
-                                    })
+                                do {
+                                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "GROUPZ", cvalues: ["image_id": fileDir.lastPathComponent], _where: "group_id = '\(g.id)'")
+                                    DispatchQueue.main.async {
+                                        Nexilis.hideLoader(completion: {
+                                            self.tempImage = image
+                                            cell.profile.image = self.tempImage
+                                        })
+                                    }
+                                } catch {
+                                    rollback.pointee = true
+                                    print("Access database error: \(error.localizedDescription)")
                                 }
                             })
                         } else {

+ 60 - 50
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/GroupMemberViewController.swift

@@ -68,44 +68,49 @@ class GroupMemberViewController: UITableViewController {
     @objc func add(sender: Any) {
         DispatchQueue.global().async {
             Database.shared.database?.inTransaction({ fmdb, rollback in
-                var result: Int = 0
-                for u in self.userSelected {
-                    if let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getAddGroupMember(p_group_id: self.group.id, p_member_pin: u.pin, p_position: "0")), response.isOk() {
-                        let arrayChatId = self.group.topics.filter({ t in
-                            return t.title != "Lounge".localized()
-                        }).map { t in
-                            return t.chatId
-                        }.joined(separator: ",")
-                        if let responseTopic = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getAddChatMember(groupId: self.group.id, chatId: arrayChatId, pin: u.pin)), responseTopic.isOk() {
-                            let insert = try! Database.shared.insertRecord(fmdb: fmdb, table: "GROUPZ_MEMBER", cvalues: [
-                                "group_id": self.group.id,
-                                "f_pin": u.pin,
-                                "position": "0", // 0: member, 1: Admin
-                                "user_id": u.pin,
-                                "first_name": u.firstName,
-                                "last_name": u.lastName,
-                                "msisdn": "",
-                                "thumb_id": u.thumb,
-                                "created_date": Date().currentTimeMillis()
-                            ], replace: true)
-                            if insert > 0 {
-                                if self.group.isInternal {
-                                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: ["user_type": "23"], _where: "f_pin = '\(u.pin)'")
+                do {
+                    var result: Int = 0
+                    for u in self.userSelected {
+                        if let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getAddGroupMember(p_group_id: self.group.id, p_member_pin: u.pin, p_position: "0")), response.isOk() {
+                            let arrayChatId = self.group.topics.filter({ t in
+                                return t.title != "Lounge".localized()
+                            }).map { t in
+                                return t.chatId
+                            }.joined(separator: ",")
+                            if let responseTopic = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getAddChatMember(groupId: self.group.id, chatId: arrayChatId, pin: u.pin)), responseTopic.isOk() {
+                                let insert = try! Database.shared.insertRecord(fmdb: fmdb, table: "GROUPZ_MEMBER", cvalues: [
+                                    "group_id": self.group.id,
+                                    "f_pin": u.pin,
+                                    "position": "0", // 0: member, 1: Admin
+                                    "user_id": u.pin,
+                                    "first_name": u.firstName,
+                                    "last_name": u.lastName,
+                                    "msisdn": "",
+                                    "thumb_id": u.thumb,
+                                    "created_date": Date().currentTimeMillis()
+                                ], replace: true)
+                                if insert > 0 {
+                                    if self.group.isInternal {
+                                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: ["user_type": "23"], _where: "f_pin = '\(u.pin)'")
+                                    }
                                 }
+                                result += 1
                             }
-                            result += 1
                         }
                     }
-                }
-                
-                DispatchQueue.main.async {
-                    if self.userSelected.count == result {
-                        self.navigationController?.dismiss(animated: true, completion: {
-                            self.isDismiss?()
-                        })
-                    } else {
-                        self.showToast(message: "Server busy".localized(), seconds: 3)
+                    
+                    DispatchQueue.main.async {
+                        if self.userSelected.count == result {
+                            self.navigationController?.dismiss(animated: true, completion: {
+                                self.isDismiss?()
+                            })
+                        } else {
+                            self.showToast(message: "Server busy".localized(), seconds: 3)
+                        }
                     }
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
                 }
             })
         }
@@ -116,26 +121,31 @@ class GroupMemberViewController: UITableViewController {
     func getData(completion: @escaping ([User]) -> ()) {
         DispatchQueue.global().async {
             Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                var r: [User] = []
-                var query =  "SELECT f_pin, first_name, last_name, image_id, user_type FROM BUDDY where f_pin not in (select m.f_pin from GROUPZ_MEMBER m where m.group_id = '\(self.group.id)') and official_account = '0' order by 2 collate nocase asc"
-                if self.isContactCenterInvite {
-                    query =  "SELECT f_pin, first_name, last_name, image_id, user_type FROM BUDDY where f_pin not in (select m.f_pin from GROUPZ_MEMBER m where m.group_id = '\(self.group.id)') and user_type = '23' and official_account = '0' order by 2 collate nocase asc"
-                }
-                if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: query) {
-                    while cursorData.next() {
-                        let user = User(pin: cursorData.string(forColumnIndex: 0) ?? "",
-                                            firstName: cursorData.string(forColumnIndex: 1) ?? "",
-                                            lastName: cursorData.string(forColumnIndex: 2) ?? "",
-                                            thumb: cursorData.string(forColumnIndex: 3) ?? "")
-                        user.userType = cursorData.string(forColumnIndex: 4)
-                        if (user.firstName + " " + user.lastName).trimmingCharacters(in: .whitespaces) == "USR\(user.pin)" {
-                            continue
+                do {
+                    var r: [User] = []
+                    var query =  "SELECT f_pin, first_name, last_name, image_id, user_type FROM BUDDY where f_pin not in (select m.f_pin from GROUPZ_MEMBER m where m.group_id = '\(self.group.id)') and official_account = '0' order by 2 collate nocase asc"
+                    if self.isContactCenterInvite {
+                        query =  "SELECT f_pin, first_name, last_name, image_id, user_type FROM BUDDY where f_pin not in (select m.f_pin from GROUPZ_MEMBER m where m.group_id = '\(self.group.id)') and user_type = '23' and official_account = '0' order by 2 collate nocase asc"
+                    }
+                    if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: query) {
+                        while cursorData.next() {
+                            let user = User(pin: cursorData.string(forColumnIndex: 0) ?? "",
+                                                firstName: cursorData.string(forColumnIndex: 1) ?? "",
+                                                lastName: cursorData.string(forColumnIndex: 2) ?? "",
+                                                thumb: cursorData.string(forColumnIndex: 3) ?? "")
+                            user.userType = cursorData.string(forColumnIndex: 4)
+                            if (user.firstName + " " + user.lastName).trimmingCharacters(in: .whitespaces) == "USR\(user.pin)" {
+                                continue
+                            }
+                            r.append(user)
                         }
-                        r.append(user)
+                        cursorData.close()
                     }
-                    cursorData.close()
+                    completion(r)
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
                 }
-                completion(r)
             })
         }
     }

+ 6 - 1
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/GroupNameViewController.swift

@@ -46,7 +46,12 @@ class GroupNameViewController: UITableViewController {
                 if let resp = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getChangeGroupInfo(p_group_id: self.data, p_name: text)) {
                     if resp.isOk() {
                         Database.shared.database?.inTransaction({ fmdb, rollback in
-                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "GROUPZ", cvalues: ["f_name": text], _where: "group_id = '\(self.data)'")
+                            do {
+                                _ = Database.shared.updateRecord(fmdb: fmdb, table: "GROUPZ", cvalues: ["f_name": text], _where: "group_id = '\(self.data)'")
+                            } catch {
+                                rollback.pointee = true
+                                print("Access database error: \(error.localizedDescription)")
+                            }
                         })
                         DispatchQueue.main.async {
                             self.navigationController?.dismiss(animated: true, completion: {

+ 6 - 1
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/GroupTopicViewController.swift

@@ -43,7 +43,12 @@ class GroupTopicViewController: UITableViewController {
                 if let resp = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getCreateChat(chat_id: id, title: text, group_id: self.data)) {
                     if resp.isOk() {
                         Database.shared.database?.inTransaction({ fmdb, rollback in
-                            _ = try! Database.shared.insertRecord(fmdb: fmdb, table: "DISCUSSION_FORUM", cvalues: ["chat_id": id, "title": text, "group_id": self.data, "scope_id": "4"], replace: true)
+                            do {
+                                _ = try! Database.shared.insertRecord(fmdb: fmdb, table: "DISCUSSION_FORUM", cvalues: ["chat_id": id, "title": text, "group_id": self.data, "scope_id": "4"], replace: true)
+                            } catch {
+                                rollback.pointee = true
+                                print("Access database error: \(error.localizedDescription)")
+                            }
                         })
                         DispatchQueue.main.async {
                             self.navigationController?.dismiss(animated: true, completion: {

+ 8 - 3
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/HistoryBroadcastViewController.swift

@@ -40,9 +40,14 @@ class HistoryBroadcastViewController: UIViewController, UITableViewDelegate, UIT
         
         let me = User.getMyPin()!
         Database.shared.database?.inTransaction({ fmdb, rollback in
-            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select FIRST_NAME, LAST_NAME, IMAGE_ID, USER_TYPE from BUDDY where F_PIN = '\(me)'"), cursor.next() {
-                isAdmin = cursor.string(forColumnIndex: 3) == "23" || cursor.string(forColumnIndex: 3) == "24"
-                cursor.close()
+            do {
+                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select FIRST_NAME, LAST_NAME, IMAGE_ID, USER_TYPE from BUDDY where F_PIN = '\(me)'"), cursor.next() {
+                    isAdmin = cursor.string(forColumnIndex: 3) == "23" || cursor.string(forColumnIndex: 3) == "24"
+                    cursor.close()
+                }
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         if isAdmin {

+ 37 - 27
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/HistoryCCViewController.swift

@@ -133,21 +133,26 @@ public class HistoryCCViewController: UITableViewController, QLPreviewController
     
     func getData() {
         Database.shared.database?.inTransaction({ fmdb, rollback in
-            var data: [[String: Any?]] = []
-            if let cursorHistory = Database.shared.getRecords(fmdb: fmdb, query: "SELECT type, f_pin, complaint_id, time, time_end, requester FROM CALL_CENTER_HISTORY order by time desc") {
-                while cursorHistory.next() {
-                    var row: [String: Any?] = [:]
-                    row["type"] = cursorHistory.string(forColumnIndex: 0)
-                    row["officer"] = cursorHistory.string(forColumnIndex: 1)
-                    row["complaint_id"] = cursorHistory.string(forColumnIndex: 2)
-                    row["date_start"] = cursorHistory.string(forColumnIndex: 3)
-                    row["date_end"] = cursorHistory.string(forColumnIndex: 4)
-                    row["requester"] = cursorHistory.string(forColumnIndex: 5)
-                    data.append(row)
+            do {
+                var data: [[String: Any?]] = []
+                if let cursorHistory = Database.shared.getRecords(fmdb: fmdb, query: "SELECT type, f_pin, complaint_id, time, time_end, requester FROM CALL_CENTER_HISTORY order by time desc") {
+                    while cursorHistory.next() {
+                        var row: [String: Any?] = [:]
+                        row["type"] = cursorHistory.string(forColumnIndex: 0)
+                        row["officer"] = cursorHistory.string(forColumnIndex: 1)
+                        row["complaint_id"] = cursorHistory.string(forColumnIndex: 2)
+                        row["date_start"] = cursorHistory.string(forColumnIndex: 3)
+                        row["date_end"] = cursorHistory.string(forColumnIndex: 4)
+                        row["requester"] = cursorHistory.string(forColumnIndex: 5)
+                        data.append(row)
+                    }
+                    cursorHistory.close()
                 }
-                cursorHistory.close()
+                self.data = data
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
-            self.data = data
         })
     }
     
@@ -173,21 +178,26 @@ public class HistoryCCViewController: UITableViewController, QLPreviewController
     @objc func buttonPDFClicked(sender: UIButton) {
         var dataMessages: [[String: Any?]] = []
         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-            let query = "SELECT f_pin, l_pin, message_text, audio_id, video_id, image_id, thumb_id, file_id FROM MESSAGE where call_center_id='\(data[sender.tag]["complaint_id"] as! String)' order by server_date asc"
-            if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: query) {
-                while cursorData.next() {
-                    var row: [String: Any?] = [:]
-                    row["f_pin"] = cursorData.string(forColumnIndex: 0)
-                    row["l_pin"] = cursorData.string(forColumnIndex: 1)
-                    row["message_text"] = cursorData.string(forColumnIndex: 2)
-                    row["audio_id"] = cursorData.string(forColumnIndex: 3)
-                    row["video_id"] = cursorData.string(forColumnIndex: 4)
-                    row["image_id"] = cursorData.string(forColumnIndex: 5)
-                    row["thumb_id"] = cursorData.string(forColumnIndex: 6)
-                    row["file_id"] = cursorData.string(forColumnIndex: 7)
-                    dataMessages.append(row)
+            do {
+                let query = "SELECT f_pin, l_pin, message_text, audio_id, video_id, image_id, thumb_id, file_id FROM MESSAGE where call_center_id='\(data[sender.tag]["complaint_id"] as! String)' order by server_date asc"
+                if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: query) {
+                    while cursorData.next() {
+                        var row: [String: Any?] = [:]
+                        row["f_pin"] = cursorData.string(forColumnIndex: 0)
+                        row["l_pin"] = cursorData.string(forColumnIndex: 1)
+                        row["message_text"] = cursorData.string(forColumnIndex: 2)
+                        row["audio_id"] = cursorData.string(forColumnIndex: 3)
+                        row["video_id"] = cursorData.string(forColumnIndex: 4)
+                        row["image_id"] = cursorData.string(forColumnIndex: 5)
+                        row["thumb_id"] = cursorData.string(forColumnIndex: 6)
+                        row["file_id"] = cursorData.string(forColumnIndex: 7)
+                        dataMessages.append(row)
+                    }
+                    cursorData.close()
                 }
-                cursorData.close()
+            } catch {
+                rollback.pointee = true
+                print("Access database error: \(error.localizedDescription)")
             }
         })
         let dataOfficer = getDataProfile(f_pin: data[sender.tag]["officer"] as! String)

+ 79 - 44
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/ProfileViewController.swift

@@ -87,18 +87,23 @@ public class ProfileViewController: UITableViewController {
                     }
                     if let me = User.getMyPin(), me == self.data || self.flag == Flag.me {
                         Database.shared.database?.inTransaction({ fmdb, rollback in
-                            let idMe = User.getMyPin()!
-                            if let cursorCount = Database.shared.getRecords(fmdb: fmdb, query: "select COUNT(*) from BUDDY where f_pin <> '\(idMe)' and first_name NOT LIKE 'USR%' "), cursorCount.next() {
-                                let count = cursorCount.string(forColumnIndex: 0)!
-                                self.countFriend.text = count + " " + "Friends".localized()
-                                self.countFriend.font = .systemFont(ofSize: 12)
-                                self.viewFriend.layer.cornerRadius = 5.0
-                                self.viewFriend.clipsToBounds = true
-                                self.viewFriend.isHidden = false
-                                
-                                self.viewFriend.isUserInteractionEnabled = true
-                                self.viewFriend.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.friendsTapped)))
-                                cursorCount.close()
+                            do {
+                                let idMe = User.getMyPin()!
+                                if let cursorCount = Database.shared.getRecords(fmdb: fmdb, query: "select COUNT(*) from BUDDY where f_pin <> '\(idMe)' and first_name NOT LIKE 'USR%' "), cursorCount.next() {
+                                    let count = cursorCount.string(forColumnIndex: 0)!
+                                    self.countFriend.text = count + " " + "Friends".localized()
+                                    self.countFriend.font = .systemFont(ofSize: 12)
+                                    self.viewFriend.layer.cornerRadius = 5.0
+                                    self.viewFriend.clipsToBounds = true
+                                    self.viewFriend.isHidden = false
+                                    
+                                    self.viewFriend.isUserInteractionEnabled = true
+                                    self.viewFriend.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.friendsTapped)))
+                                    cursorCount.close()
+                                }
+                            } catch {
+                                rollback.pointee = true
+                                print("Access database error: \(error.localizedDescription)")
                             }
                         })
                     }
@@ -140,12 +145,17 @@ public class ProfileViewController: UITableViewController {
                 var r: User?
                 r = User.getData(pin: self.data)
                 Database.shared.database?.inTransaction({ fmdb, rollback in
-                    let idMe = User.getMyPin()!
-                    if let cursorCount = Database.shared.getRecords(fmdb: fmdb, query: "select COUNT(*) from BUDDY where f_pin <> '\(idMe)' and first_name NOT LIKE 'USR%' "), cursorCount.next() {
-                        DispatchQueue.main.async {
-                            self.countFriend.text = cursorCount.string(forColumnIndex: 0) ?? "" + " " + "Friends".localized()
+                    do {
+                        let idMe = User.getMyPin()!
+                        if let cursorCount = Database.shared.getRecords(fmdb: fmdb, query: "select COUNT(*) from BUDDY where f_pin <> '\(idMe)' and first_name NOT LIKE 'USR%' "), cursorCount.next() {
+                            DispatchQueue.main.async {
+                                self.countFriend.text = cursorCount.string(forColumnIndex: 0) ?? "" + " " + "Friends".localized()
+                            }
+                            cursorCount.close()
                         }
-                        cursorCount.close()
+                    } catch {
+                        rollback.pointee = true
+                        print("Access database error: \(error.localizedDescription)")
                     }
                 })
                 completion(r)
@@ -294,9 +304,14 @@ public class ProfileViewController: UITableViewController {
                 if let resp = Nexilis.writeAndWait(message: tMessage) {
                     if resp.isOk() {
                         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
-                                "offline_mode" : value ? "0" : "1"
-                            ], _where: "f_pin = '\(self.data)'")
+                            do {
+                                _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
+                                    "offline_mode" : value ? "0" : "1"
+                                ], _where: "f_pin = '\(self.data)'")
+                            } catch {
+                                rollback.pointee = true
+                                print("Access database error: \(error.localizedDescription)")
+                            }
                         })
                         DispatchQueue.main.async { [self] in
                             let imageView = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
@@ -339,9 +354,14 @@ public class ProfileViewController: UITableViewController {
                 if let resp = Nexilis.writeAndWait(message: tMessage) {
                     if resp.isOk() {
                         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
-                                "privacy_flag" : value ? "1" : "0"
-                            ], _where: "f_pin = '\(self.data)'")
+                            do {
+                                _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
+                                    "privacy_flag" : value ? "1" : "0"
+                                ], _where: "f_pin = '\(self.data)'")
+                            } catch {
+                                rollback.pointee = true
+                                print("Access database error: \(error.localizedDescription)")
+                            }
                         })
                         DispatchQueue.main.async { [self] in
                             let imageView = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
@@ -510,7 +530,12 @@ public class ProfileViewController: UITableViewController {
                             return
                         }
                         Database.shared.database?.inTransaction({ fmdb, rollback in
-                            _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: ["image_id": ""], _where: "f_pin = '\(me)'")
+                            do {
+                                _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: ["image_id": ""], _where: "f_pin = '\(me)'")
+                            } catch {
+                                rollback.pointee = true
+                                print("Access database error: \(error.localizedDescription)")
+                            }
                         })
                         NotificationCenter.default.post(name: NSNotification.Name(rawValue: "updateFifthTab"), object: nil, userInfo: nil)
                         
@@ -597,26 +622,31 @@ public class ProfileViewController: UITableViewController {
                 DispatchQueue.main.async { [self] in
                     if result {
                         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                            if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select * from BUDDY where f_pin = '\(self.data)'"), cursor.next() {
-                                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "BUDDY", _where: "f_pin = '\(self.data)'")
-                                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "l_pin='\(self.data)'")
-                                _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE", _where: "(f_pin='\(self.data)' or l_pin='\(self.data)') and message_scope_id='3'")
-                                cursor.close()
-                            }
-                            Nexilis.hideLoader(completion: {
-                                if self.previousViewController is GroupDetailViewController || self.isBNI {
-                                    self.isDismiss?()
-                                    self.navigationController?.popViewController(animated: true)
-                                } else {
-                                    if let editor = self.previousViewController as? EditorPersonal {
-                                        editor.afterUnfriend()
-                                    } else if let editor = self.previousViewController as? EditorGroup {
-                                        editor.afterUnfriend()
-                                    }
-                                    self.navigationController?.popToRootViewController(animated: true)
+                            do {
+                                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select * from BUDDY where f_pin = '\(self.data)'"), cursor.next() {
+                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "BUDDY", _where: "f_pin = '\(self.data)'")
+                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "l_pin='\(self.data)'")
+                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE", _where: "(f_pin='\(self.data)' or l_pin='\(self.data)') and message_scope_id='3'")
+                                    cursor.close()
                                 }
-                                Nexilis.shared.stateUnfriend = ""
-                            })
+                                Nexilis.hideLoader(completion: {
+                                    if self.previousViewController is GroupDetailViewController || self.isBNI {
+                                        self.isDismiss?()
+                                        self.navigationController?.popViewController(animated: true)
+                                    } else {
+                                        if let editor = self.previousViewController as? EditorPersonal {
+                                            editor.afterUnfriend()
+                                        } else if let editor = self.previousViewController as? EditorGroup {
+                                            editor.afterUnfriend()
+                                        }
+                                        self.navigationController?.popToRootViewController(animated: true)
+                                    }
+                                    Nexilis.shared.stateUnfriend = ""
+                                })
+                            } catch {
+                                rollback.pointee = true
+                                print("Access database error: \(error.localizedDescription)")
+                            }
                         })
                     } else {
                         if self.call != nil {
@@ -738,7 +768,12 @@ extension ProfileViewController: ImageVideoPickerDelegate {
                             }
                             if let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getChangePersonImage(thumb_id: fileDir.lastPathComponent)), response.isOk() {
                                 Database.shared.database?.inTransaction({ fmdb, rollback in
-                                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: ["image_id": fileDir.lastPathComponent], _where: "f_pin = '\(me)'")
+                                    do {
+                                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: ["image_id": fileDir.lastPathComponent], _where: "f_pin = '\(me)'")
+                                    } catch {
+                                        rollback.pointee = true
+                                        print("Access database error: \(error.localizedDescription)")
+                                    }
                                 })
                                 NotificationCenter.default.post(name: NSNotification.Name(rawValue: "updateFifthTab"), object: nil, userInfo: nil)
                                 

+ 75 - 60
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/SetInternalCSAccount.swift

@@ -82,25 +82,30 @@ public class SetInternalCSAccount: UITableViewController {
     func getData(completion: @escaping ([User]) -> ()) {
         DispatchQueue.global().async {
             Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                var r: [User] = []
-                var query =  "SELECT u.f_pin, u.first_name, u.last_name, u.image_id, u.user_type FROM BUDDY u where u.f_pin <> '\(User.getMyPin()!)' and u.official_account <> '1' and u.official_account <> '2' and u.official_account <> '3' order by 2 collate nocase asc"
-                if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: query) {
-                    while cursorData.next() {
-                        let user = User(pin: cursorData.string(forColumnIndex: 0) ?? "",
-                                            firstName: cursorData.string(forColumnIndex: 1) ?? "",
-                                            lastName: cursorData.string(forColumnIndex: 2) ?? "",
-                                            thumb: cursorData.string(forColumnIndex: 3) ?? "",
-                                            userType: cursorData.string(forColumnIndex: 4) ?? "")
-                        if (user.firstName + " " + user.lastName).trimmingCharacters(in: .whitespaces) == "USR\(user.pin)" {
-                            continue
-                        }
-                        if r.first(where: {$0.pin == user.pin}) == nil {
-                            r.append(user)
+                do {
+                    var r: [User] = []
+                    let query =  "SELECT u.f_pin, u.first_name, u.last_name, u.image_id, u.user_type FROM BUDDY u where u.f_pin <> '\(User.getMyPin()!)' and u.official_account <> '1' and u.official_account <> '2' and u.official_account <> '3' order by 2 collate nocase asc"
+                    if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: query) {
+                        while cursorData.next() {
+                            let user = User(pin: cursorData.string(forColumnIndex: 0) ?? "",
+                                                firstName: cursorData.string(forColumnIndex: 1) ?? "",
+                                                lastName: cursorData.string(forColumnIndex: 2) ?? "",
+                                                thumb: cursorData.string(forColumnIndex: 3) ?? "",
+                                                userType: cursorData.string(forColumnIndex: 4) ?? "")
+                            if (user.firstName + " " + user.lastName).trimmingCharacters(in: .whitespaces) == "USR\(user.pin)" {
+                                continue
+                            }
+                            if r.first(where: {$0.pin == user.pin}) == nil {
+                                r.append(user)
+                            }
                         }
+                        cursorData.close()
                     }
-                    cursorData.close()
+                    completion(r)
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
                 }
-                completion(r)
             })
         }
     }
@@ -111,38 +116,43 @@ public class SetInternalCSAccount: UITableViewController {
         alert.addAction(UIAlertAction(title: "Yes".localized(), style: .default, handler: {(_) in
             Nexilis.showLoader()
             Database.shared.database?.inTransaction({ fmdb, rollback in
-                if let result = Nexilis.writeSync(message: CoreMessage_TMessageBank.getManagementContactCenter(user_type: (self.isSetCS ? "1" : "3"), l_pin: user.pin), timeout: 5000) {
-                    if result.isOk() {
-                        DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
-                            let imageView = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
-                            imageView.tintColor = .white
-                            let banner = FloatingNotificationBanner(title: "Successfully changed".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .success, colors: nil, iconPosition: .center)
-                            banner.show()
-                            self.getData { users in
-                                self.availableUser.removeAll()
-                                self.availableUser.append(contentsOf: users)
-                                DispatchQueue.main.async {
-                                    self.tableView.reloadData()
+                do {
+                    if let result = Nexilis.writeSync(message: CoreMessage_TMessageBank.getManagementContactCenter(user_type: (self.isSetCS ? "1" : "3"), l_pin: user.pin), timeout: 5000) {
+                        if result.isOk() {
+                            DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
+                                let imageView = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
+                                imageView.tintColor = .white
+                                let banner = FloatingNotificationBanner(title: "Successfully changed".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .success, colors: nil, iconPosition: .center)
+                                banner.show()
+                                self.getData { users in
+                                    self.availableUser.removeAll()
+                                    self.availableUser.append(contentsOf: users)
+                                    DispatchQueue.main.async {
+                                        self.tableView.reloadData()
+                                    }
                                 }
+                                Nexilis.hideLoader {}
+                            })
+                        } else {
+                            DispatchQueue.main.async {
+                                let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                                imageView.tintColor = .white
+                                let banner = FloatingNotificationBanner(title: "Unable to access servers".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .top)
+                                banner.show()
+                                Nexilis.hideLoader {}
                             }
-                            Nexilis.hideLoader {}
-                        })
+                        }
                     } else {
                         DispatchQueue.main.async {
                             let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
                             imageView.tintColor = .white
                             let banner = FloatingNotificationBanner(title: "Unable to access servers".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .top)
                             banner.show()
-                            Nexilis.hideLoader {}
                         }
                     }
-                } else {
-                    DispatchQueue.main.async {
-                        let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
-                        imageView.tintColor = .white
-                        let banner = FloatingNotificationBanner(title: "Unable to access servers".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .top)
-                        banner.show()
-                    }
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
                 }
             })
         }))
@@ -155,38 +165,43 @@ public class SetInternalCSAccount: UITableViewController {
         alert.addAction(UIAlertAction(title: "Yes".localized(), style: .destructive, handler: {(_) in
             Nexilis.showLoader()
             Database.shared.database?.inTransaction({ fmdb, rollback in
-                if let result = Nexilis.writeSync(message: CoreMessage_TMessageBank.getManagementContactCenter(user_type: (self.isSetCS ? "0" : "2"), l_pin: user.pin), timeout: 5000) {
-                    if result.isOk() {
-                        DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
-                            let imageView = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
-                            imageView.tintColor = .white
-                            let banner = FloatingNotificationBanner(title: "Successfully changed".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .success, colors: nil, iconPosition: .center)
-                            banner.show()
-                            self.getData { users in
-                                self.availableUser.removeAll()
-                                self.availableUser.append(contentsOf: users)
-                                DispatchQueue.main.async {
-                                    self.tableView.reloadData()
+                do {
+                    if let result = Nexilis.writeSync(message: CoreMessage_TMessageBank.getManagementContactCenter(user_type: (self.isSetCS ? "0" : "2"), l_pin: user.pin), timeout: 5000) {
+                        if result.isOk() {
+                            DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
+                                let imageView = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
+                                imageView.tintColor = .white
+                                let banner = FloatingNotificationBanner(title: "Successfully changed".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .success, colors: nil, iconPosition: .center)
+                                banner.show()
+                                self.getData { users in
+                                    self.availableUser.removeAll()
+                                    self.availableUser.append(contentsOf: users)
+                                    DispatchQueue.main.async {
+                                        self.tableView.reloadData()
+                                    }
                                 }
+                                Nexilis.hideLoader {}
+                            })
+                        } else {
+                            DispatchQueue.main.async {
+                                let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                                imageView.tintColor = .white
+                                let banner = FloatingNotificationBanner(title: "Unable to access servers".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .top)
+                                banner.show()
+                                Nexilis.hideLoader {}
                             }
-                            Nexilis.hideLoader {}
-                        })
+                        }
                     } else {
                         DispatchQueue.main.async {
                             let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
                             imageView.tintColor = .white
                             let banner = FloatingNotificationBanner(title: "Unable to access servers".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .top)
                             banner.show()
-                            Nexilis.hideLoader {}
                         }
                     }
-                } else {
-                    DispatchQueue.main.async {
-                        let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
-                        imageView.tintColor = .white
-                        let banner = FloatingNotificationBanner(title: "Unable to access servers".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .top)
-                        banner.show()
-                    }
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
                 }
             })
         }))

+ 118 - 97
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/SettingTableViewController.swift

@@ -99,116 +99,132 @@ public class SettingTableViewController: UITableViewController, UIGestureRecogni
     
     func makeMenu(imageSignIn: String = ""){
         let isChangeProfile = Utils.getSetProfile()
-        Database.shared.database?.inTransaction({ fmdb, rollback in
-            let idMe = User.getMyPin() as String?
-            if let cursorUser = Database.shared.getRecords(fmdb: fmdb, query: "SELECT user_type, image_id, official_account FROM BUDDY where f_pin='\(idMe!)'"), cursorUser.next() {
-                if (User.isInternal(userType: cursorUser.string(forColumnIndex: 0) ?? "") && User.isAdmin(fmdb: fmdb)) || User.isOfficial(official_account: cursorUser.string(forColumnIndex: 2) ?? "") || User.isOfficial(official_account: cursorUser.string(forColumnIndex: 2) ?? "") {
-                    Item.menus["Personal"] = [
-                        Item(icon: UIImage(systemName: "person"), title: "Personal Information".localized()),
-                        Item(icon: UIImage(systemName: "textformat.abc"), title: "Change Language".localized()),
-                        Item(icon: UIImage(systemName: "person.crop.rectangle"), title: "Change Admin / Internal Password".localized()),
-                        Item(icon: UIImage(systemName: "laptopcomputer.and.iphone"), title: "Sign-In to Web".localized()),
-                        Item(icon: UIImage(named: "ic_internal", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, title: "Set Internal Account".localized()),
-                        Item(icon: UIImage(named: "pb_call_center", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, title: "Set CS Account".localized()),
-                    ]
-                } else if User.isInternal(userType: cursorUser.string(forColumnIndex: 0) ?? "") || User.isCallCenter(userType: cursorUser.string(forColumnIndex: 0) ?? "") || User.isVerified(official_account: cursorUser.string(forColumnIndex: 2) ?? "") {
-                    Item.menus["Personal"] = [
-                        Item(icon: UIImage(systemName: "person"), title: "Personal Information".localized()),
-                        Item(icon: UIImage(systemName: "textformat.abc"), title: "Change Language".localized()),
-                        Item(icon: UIImage(systemName: "laptopcomputer.and.iphone"), title: "Sign-In to Web".localized()),
-                    ]
-                } else {
-                    Item.menus["Personal"] = [
-                        Item(icon: UIImage(systemName: "person"), title: "Personal Information".localized()),
-                            Item(icon: UIImage(systemName: "textformat.abc"), title: "Change Language".localized()),
-                        Item(icon: UIImage(systemName: "person.badge.key"), title: "Access Admin / Internal Features".localized()),
-                    ]
-                }
-                if !isChangeProfile {
-                    Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "arrow.up.and.person.rectangle.portrait"), title: "Sign-Up/Sign-In".localized()))
-                } else if isChangeProfile {
-                    if Nexilis.checkingAccess(key: "backup_restore") {
-                        Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "arrow.clockwise.icloud"), title: "Backup & Restore".localized()))
-                    }
-                    if Utils.getLimitValidTrans() == "1" {
-                        Item.menus["Personal"]?.insert(Item(icon: UIImage(systemName: "lessthan.circle"), title: "Validation Transaction Limit".localized()), at: 1)
-                    }
-                }
-                let image = cursorUser.string(forColumnIndex: 1)
-                if image != nil {
-                    if !image!.isEmpty {
-                        do {
-                            let documentDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
-                            let file = documentDir.appendingPathComponent(image!)
-                            if FileManager().fileExists(atPath: file.path) {
-                                let image = UIImage(contentsOfFile: file.path)
-                                Item.menus["Personal"]?[0].icon = image?.circleMasked
-                                if !imageSignIn.isEmpty {
-                                    var dataImage: [AnyHashable : Any] = [:]
-                                    dataImage["name"] = imageSignIn
-                                    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "imageFBUpdate"), object: nil, userInfo: dataImage)
-                                }
-                            } else {
-                                Download().start(forKey: image!) { (name, progress) in
-                                    guard progress == 100 else {
-                                        return
-                                    }
-
-                                    DispatchQueue.main.async {
+        if Database.shared.database == nil {
+            Item.menus["Personal"] = [
+                Item(icon: UIImage(systemName: "person"), title: "Personal Information".localized()),
+                Item(icon: UIImage(systemName: "textformat.abc"), title: "Change Language".localized()),
+                Item(icon: UIImage(systemName: "arrow.up.and.person.rectangle.portrait"), title: "Sign-Up/Sign-In".localized()),
+            ]
+            if Nexilis.showButtonFB {
+                Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "gearshape.circle"), title: "Configure Floating Button".localized()))
+            }
+        } else {
+            Database.shared.database?.inTransaction({ fmdb, rollback in
+                do {
+                    let idMe = User.getMyPin() as String?
+                    if let cursorUser = Database.shared.getRecords(fmdb: fmdb, query: "SELECT user_type, image_id, official_account FROM BUDDY where f_pin='\(idMe!)'"), cursorUser.next() {
+                        if (User.isInternal(userType: cursorUser.string(forColumnIndex: 0) ?? "") && User.isAdmin(fmdb: fmdb)) || User.isOfficial(official_account: cursorUser.string(forColumnIndex: 2) ?? "") || User.isOfficial(official_account: cursorUser.string(forColumnIndex: 2) ?? "") {
+                            Item.menus["Personal"] = [
+                                Item(icon: UIImage(systemName: "person"), title: "Personal Information".localized()),
+                                Item(icon: UIImage(systemName: "textformat.abc"), title: "Change Language".localized()),
+                                Item(icon: UIImage(systemName: "person.crop.rectangle"), title: "Change Admin / Internal Password".localized()),
+                                Item(icon: UIImage(systemName: "laptopcomputer.and.iphone"), title: "Sign-In to Web".localized()),
+                                Item(icon: UIImage(named: "ic_internal", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, title: "Set Internal Account".localized()),
+                                Item(icon: UIImage(named: "pb_call_center", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, title: "Set CS Account".localized()),
+                            ]
+                        } else if User.isInternal(userType: cursorUser.string(forColumnIndex: 0) ?? "") || User.isCallCenter(userType: cursorUser.string(forColumnIndex: 0) ?? "") || User.isVerified(official_account: cursorUser.string(forColumnIndex: 2) ?? "") {
+                            Item.menus["Personal"] = [
+                                Item(icon: UIImage(systemName: "person"), title: "Personal Information".localized()),
+                                Item(icon: UIImage(systemName: "textformat.abc"), title: "Change Language".localized()),
+                                Item(icon: UIImage(systemName: "laptopcomputer.and.iphone"), title: "Sign-In to Web".localized()),
+                            ]
+                        } else {
+                            Item.menus["Personal"] = [
+                                Item(icon: UIImage(systemName: "person"), title: "Personal Information".localized()),
+                                    Item(icon: UIImage(systemName: "textformat.abc"), title: "Change Language".localized()),
+                                Item(icon: UIImage(systemName: "person.badge.key"), title: "Access Admin / Internal Features".localized()),
+                            ]
+                        }
+                        if !isChangeProfile {
+                            Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "arrow.up.and.person.rectangle.portrait"), title: "Sign-Up/Sign-In".localized()))
+                        } else if isChangeProfile {
+                            if Nexilis.checkingAccess(key: "backup_restore") {
+                                Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "arrow.clockwise.icloud"), title: "Backup & Restore".localized()))
+                            }
+                            if Utils.getLimitValidTrans() == "1" {
+                                Item.menus["Personal"]?.insert(Item(icon: UIImage(systemName: "lessthan.circle"), title: "Validation Transaction Limit".localized()), at: 1)
+                            }
+                        }
+                        let image = cursorUser.string(forColumnIndex: 1)
+                        if image != nil {
+                            if !image!.isEmpty {
+                                do {
+                                    let documentDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
+                                    let file = documentDir.appendingPathComponent(image!)
+                                    if FileManager().fileExists(atPath: file.path) {
                                         let image = UIImage(contentsOfFile: file.path)
                                         Item.menus["Personal"]?[0].icon = image?.circleMasked
-                                        self.tableView.reloadData()
                                         if !imageSignIn.isEmpty {
                                             var dataImage: [AnyHashable : Any] = [:]
                                             dataImage["name"] = imageSignIn
                                             NotificationCenter.default.post(name: NSNotification.Name(rawValue: "imageFBUpdate"), object: nil, userInfo: dataImage)
                                         }
+                                    } else {
+                                        Download().start(forKey: image!) { (name, progress) in
+                                            guard progress == 100 else {
+                                                return
+                                            }
+
+                                            DispatchQueue.main.async {
+                                                let image = UIImage(contentsOfFile: file.path)
+                                                Item.menus["Personal"]?[0].icon = image?.circleMasked
+                                                self.tableView.reloadData()
+                                                if !imageSignIn.isEmpty {
+                                                    var dataImage: [AnyHashable : Any] = [:]
+                                                    dataImage["name"] = imageSignIn
+                                                    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "imageFBUpdate"), object: nil, userInfo: dataImage)
+                                                }
+                                            }
+                                        }
                                     }
-                                }
+                                } catch {}
                             }
-                        } catch {}
-                    }
-                }
-                cursorUser.close()
-            } else {
-                Item.menus["Personal"] = [
-                    Item(icon: UIImage(systemName: "person"), title: "Personal Information".localized()),
-                        Item(icon: UIImage(systemName: "textformat.abc"), title: "Change Language".localized()),
-                    Item(icon: UIImage(systemName: "person.badge.key"), title: "Access Admin / Internal Features".localized()),
-                ]
-                if Nexilis.showButtonFB {
-                    Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "gearshape.circle"), title: "Configure Floating Button".localized()))
-                }
-                Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "arrow.up.and.person.rectangle.portrait"), title: "Sign-Up/Sign-In".localized()))
-                if !imageSignIn.isEmpty {
-                    do {
-                        let documentDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
-                        let file = documentDir.appendingPathComponent(imageSignIn)
-                        if FileManager().fileExists(atPath: file.path) {
-                            let image = UIImage(contentsOfFile: file.path)
-                            Item.menus["Personal"]?[0].icon = image?.circleMasked
-                            var dataImage: [AnyHashable : Any] = [:]
-                            dataImage["name"] = imageSignIn
-                            NotificationCenter.default.post(name: NSNotification.Name(rawValue: "imageFBUpdate"), object: nil, userInfo: dataImage)
-                        } else {
-                            Download().start(forKey: imageSignIn) { (name, progress) in
-                                guard progress == 100 else {
-                                    return
-                                }
-                                DispatchQueue.main.async {
+                        }
+                        cursorUser.close()
+                    } else {
+                        Item.menus["Personal"] = [
+                            Item(icon: UIImage(systemName: "person"), title: "Personal Information".localized()),
+                                Item(icon: UIImage(systemName: "textformat.abc"), title: "Change Language".localized()),
+                            Item(icon: UIImage(systemName: "person.badge.key"), title: "Access Admin / Internal Features".localized()),
+                        ]
+                        if Nexilis.showButtonFB {
+                            Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "gearshape.circle"), title: "Configure Floating Button".localized()))
+                        }
+                        Item.menus["Personal"]?.append(Item(icon: UIImage(systemName: "arrow.up.and.person.rectangle.portrait"), title: "Sign-Up/Sign-In".localized()))
+                        if !imageSignIn.isEmpty {
+                            do {
+                                let documentDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
+                                let file = documentDir.appendingPathComponent(imageSignIn)
+                                if FileManager().fileExists(atPath: file.path) {
                                     let image = UIImage(contentsOfFile: file.path)
                                     Item.menus["Personal"]?[0].icon = image?.circleMasked
-                                    self.tableView.reloadData()
                                     var dataImage: [AnyHashable : Any] = [:]
                                     dataImage["name"] = imageSignIn
                                     NotificationCenter.default.post(name: NSNotification.Name(rawValue: "imageFBUpdate"), object: nil, userInfo: dataImage)
+                                } else {
+                                    Download().start(forKey: imageSignIn) { (name, progress) in
+                                        guard progress == 100 else {
+                                            return
+                                        }
+                                        DispatchQueue.main.async {
+                                            let image = UIImage(contentsOfFile: file.path)
+                                            Item.menus["Personal"]?[0].icon = image?.circleMasked
+                                            self.tableView.reloadData()
+                                            var dataImage: [AnyHashable : Any] = [:]
+                                            dataImage["name"] = imageSignIn
+                                            NotificationCenter.default.post(name: NSNotification.Name(rawValue: "imageFBUpdate"), object: nil, userInfo: dataImage)
+                                        }
+                                    }
                                 }
-                            }
+                            } catch {}
                         }
-                    } catch {}
+                    }
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
                 }
-            }
-        })
+            })
+        }
         
         Item.menus["Config"] = [
             Item(icon: UIImage(systemName: "iphone"), title: "Create Your Own App".localized()),
@@ -678,10 +694,15 @@ public class SettingTableViewController: UITableViewController, UIGestureRecogni
                                 Utils.resetValueSuperApp()
                                 Utils.setValueInitialApp(data: Utils.getPrefTheme())
                                 Database.shared.database?.inTransaction({ fmdb, rollback in
-                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ", _where: "")
-                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ_MEMBER", _where: "")
-                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "DISCUSSION_FORUM", _where: "")
-                                    _ = Nexilis.write(message: CoreMessage_TMessageBank.getPostRegistration(p_pin: User.getMyPin() ?? ""))
+                                    do {
+                                        _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ", _where: "")
+                                        _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ_MEMBER", _where: "")
+                                        _ = Database.shared.deleteRecord(fmdb: fmdb, table: "DISCUSSION_FORUM", _where: "")
+                                        _ = Nexilis.write(message: CoreMessage_TMessageBank.getPostRegistration(p_pin: User.getMyPin() ?? ""))
+                                    } catch {
+                                        rollback.pointee = true
+                                        print("Access database error: \(error.localizedDescription)")
+                                    }
                                 })
                                 Nexilis.hideLoader {
                                     let alert = LibAlertController(title: "Successfully changed".localized(), message: "Please open the app again to see the changes".localized(), preferredStyle: .alert)

+ 14 - 6
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Control/SignUpSignIn.swift

@@ -268,6 +268,9 @@ public class SignUpSignIn: UIViewController {
             banner.show()
             return
         }
+        if Database.shared.openDatabase() == 0 {
+            return
+        }
         Nexilis.showLoader()
         DispatchQueue.global().async {
             let md5Hex = password
@@ -395,13 +398,18 @@ public class SignUpSignIn: UIViewController {
                         }
                     } else {
                         Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                            if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT * FROM BUDDY where f_pin = '\(idMe)' ") {
-                                if !cursorData.next() {
-                                    _ = Nexilis.write(message: CoreMessage_TMessageBank.getPostRegistration(p_pin: idMe))
-                                } else {
-                                    _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: ["first_name": first , "last_name": last], _where: "f_pin = '\(idMe)'")
+                            do {
+                                if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT * FROM BUDDY where f_pin = '\(idMe)' ") {
+                                    if !cursorData.next() {
+                                        _ = Nexilis.write(message: CoreMessage_TMessageBank.getPostRegistration(p_pin: idMe))
+                                    } else {
+                                        _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: ["first_name": first , "last_name": last], _where: "f_pin = '\(idMe)'")
+                                    }
+                                    cursorData.close()
                                 }
-                                cursorData.close()
+                            } catch {
+                                rollback.pointee = true
+                                print("Access database error: \(error.localizedDescription)")
                             }
                         })
                         Utils.setProfile(value: true)

+ 30 - 25
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Streaming/QmeraGroupChooserViewController.swift

@@ -87,36 +87,41 @@ class QmeraGroupStreamingViewController: UITableViewController {
     private func getData(completion: @escaping ([Group]) -> ()) {
         DispatchQueue.global().async {
             Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                var r: [Group] = []
-                if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select g.group_id, g.f_name, g.image_id, g.quote, g.created_by, g.created_date, g.parent, g.group_type, g.is_open, g.official, g.is_education from GROUPZ g where g.group_id not in (\(self.ignored.map{ "'\($0.id)'" }.joined(separator: ","))) order by 9 desc, 2 collate nocase asc") {
-                    while cursor.next() {
-                        let group = Group(
-                            id: cursor.string(forColumnIndex: 0) ?? "",
-                            name: cursor.string(forColumnIndex: 1) ?? "",
-                            profile: cursor.string(forColumnIndex: 2) ?? "",
-                            quote: cursor.string(forColumnIndex: 3) ?? "",
-                            by: cursor.string(forColumnIndex: 4) ?? "",
-                            date: cursor.string(forColumnIndex: 5) ?? "",
-                            parent: cursor.string(forColumnIndex: 6) ?? "",
-                            chatId: "",
-                            groupType: cursor.string(forColumnIndex: 7) ?? "",
-                            isOpen: cursor.string(forColumnIndex: 8) ?? "",
-                            official: cursor.string(forColumnIndex: 9) ?? "",
-                            isEducation: cursor.string(forColumnIndex: 10) ?? "")
-                        let idMe = User.getMyPin() as String?
-                        if let cursorUser = Database.shared.getRecords(fmdb: fmdb, query: "SELECT user_type FROM BUDDY where f_pin='\(idMe!)'"), cursorUser.next() {
-                            if cursorUser.string(forColumnIndex: 0) != "23" && cursorUser.string(forColumnIndex: 0) != "24" {
-                                if !group.parent.isEmpty && group.official == "1" {
-                                    continue
+                do {
+                    var r: [Group] = []
+                    if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select g.group_id, g.f_name, g.image_id, g.quote, g.created_by, g.created_date, g.parent, g.group_type, g.is_open, g.official, g.is_education from GROUPZ g where g.group_id not in (\(self.ignored.map{ "'\($0.id)'" }.joined(separator: ","))) order by 9 desc, 2 collate nocase asc") {
+                        while cursor.next() {
+                            let group = Group(
+                                id: cursor.string(forColumnIndex: 0) ?? "",
+                                name: cursor.string(forColumnIndex: 1) ?? "",
+                                profile: cursor.string(forColumnIndex: 2) ?? "",
+                                quote: cursor.string(forColumnIndex: 3) ?? "",
+                                by: cursor.string(forColumnIndex: 4) ?? "",
+                                date: cursor.string(forColumnIndex: 5) ?? "",
+                                parent: cursor.string(forColumnIndex: 6) ?? "",
+                                chatId: "",
+                                groupType: cursor.string(forColumnIndex: 7) ?? "",
+                                isOpen: cursor.string(forColumnIndex: 8) ?? "",
+                                official: cursor.string(forColumnIndex: 9) ?? "",
+                                isEducation: cursor.string(forColumnIndex: 10) ?? "")
+                            let idMe = User.getMyPin() as String?
+                            if let cursorUser = Database.shared.getRecords(fmdb: fmdb, query: "SELECT user_type FROM BUDDY where f_pin='\(idMe!)'"), cursorUser.next() {
+                                if cursorUser.string(forColumnIndex: 0) != "23" && cursorUser.string(forColumnIndex: 0) != "24" {
+                                    if !group.parent.isEmpty && group.official == "1" {
+                                        continue
+                                    }
                                 }
+                                cursorUser.close()
                             }
-                            cursorUser.close()
+                            r.append(group)
                         }
-                        r.append(group)
+                        cursor.close()
                     }
-                    cursor.close()
+                    completion(r)
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
                 }
-                completion(r)
             })
         }
     }

+ 17 - 12
appbuilder-ios/NexilisLite/NexilisLite/Source/View/Streaming/QmeraUserChooserViewController.swift

@@ -102,21 +102,26 @@ class QmeraUserChooserViewController: UITableViewController {
     private func getData(completion: @escaping ([User]) -> ()) {
         DispatchQueue.global().async {
             Database.shared.database?.inTransaction({ (fmdb, rollback) in
-                var r: [User] = []
-                if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_pin, first_name, last_name, image_id FROM BUDDY where f_pin not in (\(self.ignored.map{ "'\($0.pin)'" }.joined(separator: ","))) and f_pin <> '\(User.getMyPin()!)' and official_account <> 1 order by 2 collate nocase asc") {
-                    while cursorData.next() {
-                        let user = User(pin: cursorData.string(forColumnIndex: 0) ?? "",
-                                            firstName: cursorData.string(forColumnIndex: 1) ?? "",
-                                            lastName: cursorData.string(forColumnIndex: 2) ?? "",
-                                            thumb: cursorData.string(forColumnIndex: 3) ?? "")
-                        if (user.firstName + " " + user.lastName).trimmingCharacters(in: .whitespaces) == "USR\(user.pin)" {
-                            continue
+                do {
+                    var r: [User] = []
+                    if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_pin, first_name, last_name, image_id FROM BUDDY where f_pin not in (\(self.ignored.map{ "'\($0.pin)'" }.joined(separator: ","))) and f_pin <> '\(User.getMyPin()!)' and official_account <> 1 order by 2 collate nocase asc") {
+                        while cursorData.next() {
+                            let user = User(pin: cursorData.string(forColumnIndex: 0) ?? "",
+                                                firstName: cursorData.string(forColumnIndex: 1) ?? "",
+                                                lastName: cursorData.string(forColumnIndex: 2) ?? "",
+                                                thumb: cursorData.string(forColumnIndex: 3) ?? "")
+                            if (user.firstName + " " + user.lastName).trimmingCharacters(in: .whitespaces) == "USR\(user.pin)" {
+                                continue
+                            }
+                            r.append(user)
                         }
-                        r.append(user)
+                        cursorData.close()
                     }
-                    cursorData.close()
+                    completion(r)
+                } catch {
+                    rollback.pointee = true
+                    print("Access database error: \(error.localizedDescription)")
                 }
-                completion(r)
             })
         }
     }