Selaa lähdekoodia

update fix bugs

alqindiirsyam 4 kuukautta sitten
vanhempi
commit
085a42339e
31 muutettua tiedostoa jossa 795 lisäystä ja 502 poistoa
  1. 43 14
      AppBuilder/AppBuilder/SecondTabViewController.swift
  2. BIN
      NexilisLite/.DS_Store
  3. 0 12
      NexilisLite/NexilisLite.xcodeproj/project.pbxproj
  4. 41 10
      NexilisLite/NexilisLite/Source/APIS.swift
  5. 8 14
      NexilisLite/NexilisLite/Source/Download.swift
  6. 10 2
      NexilisLite/NexilisLite/Source/Extension.swift
  7. 100 146
      NexilisLite/NexilisLite/Source/FileEncryption.swift
  8. 8 10
      NexilisLite/NexilisLite/Source/IncomingThread.swift
  9. 0 29
      NexilisLite/NexilisLite/Source/MasterKeyUtil.swift
  10. 5 4
      NexilisLite/NexilisLite/Source/Network.swift
  11. 57 37
      NexilisLite/NexilisLite/Source/Nexilis.swift
  12. 11 10
      NexilisLite/NexilisLite/Source/OutgoingThread.swift
  13. 11 0
      NexilisLite/NexilisLite/Source/Utils.swift
  14. 17 2
      NexilisLite/NexilisLite/Source/View/Call/AudioViewController.swift
  15. 26 2
      NexilisLite/NexilisLite/Source/View/Call/QmeraAudioViewController.swift
  16. 55 14
      NexilisLite/NexilisLite/Source/View/Call/QmeraVideoViewController.swift
  17. 10 2
      NexilisLite/NexilisLite/Source/View/Chat/ChatGPTBotView.swift
  18. 15 4
      NexilisLite/NexilisLite/Source/View/Chat/ChatWALikeVC.swift
  19. 106 53
      NexilisLite/NexilisLite/Source/View/Chat/EditorGroup.swift
  20. 127 67
      NexilisLite/NexilisLite/Source/View/Chat/EditorPersonal.swift
  21. 50 35
      NexilisLite/NexilisLite/Source/View/Chat/EditorStarMessages.swift
  22. 16 12
      NexilisLite/NexilisLite/Source/View/Chat/ListGroupImages.swift
  23. 5 1
      NexilisLite/NexilisLite/Source/View/Chat/MessageInfo.swift
  24. 23 11
      NexilisLite/NexilisLite/Source/View/Chat/SecureFolderView.swift
  25. 5 0
      NexilisLite/NexilisLite/Source/View/Control/BroadcastViewController.swift
  26. 5 0
      NexilisLite/NexilisLite/Source/View/Control/GroupDetailViewController.swift
  27. 5 1
      NexilisLite/NexilisLite/Source/View/Control/NotificationSound.swift
  28. 18 8
      NexilisLite/NexilisLite/Source/View/Control/ProfileViewController.swift
  29. 1 1
      NexilisLite/NexilisLite/Source/View/Control/SettingTableViewController.swift
  30. 5 1
      NexilisLite/NexilisLite/Source/View/Streaming/QmeraCreateStreamingViewController.swift
  31. 12 0
      NexilisLite/NexilisLite/Source/View/Streaming/QmeraStreamingViewController.swift

+ 43 - 14
AppBuilder/AppBuilder/SecondTabViewController.swift

@@ -1592,7 +1592,11 @@ extension SecondTabViewController: UITableViewDelegate, UITableViewDataSource {
                             }
                         }
                         else if FileEncryption.shared.isSecureExists(filename: data.file) {
-                            if let dataFile = try? FileEncryption.shared.readSecure(filename: data.file) {
+                            if var dataFile = try? FileEncryption.shared.readSecure(filename: data.file) {
+                                let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: dataFile)
+                                if dataDecrypt != nil {
+                                    dataFile = dataDecrypt!
+                                }
                                 var sizeOfFile = Int(dataFile.count / 1000000)
                                 if (sizeOfFile < 1) {
                                     sizeOfFile = Int(dataFile.count / 1000)
@@ -2120,8 +2124,11 @@ extension SecondTabViewController: UITableViewDelegate, UITableViewDataSource {
                     self.present(previewController, animated: true)
                 } else if FileEncryption.shared.isSecureExists(filename: sender.file_id) {
                     do {
-                        if let docData = try FileEncryption.shared.readSecure(filename: sender.file_id) {
-                            
+                        if var docData = try FileEncryption.shared.readSecure(filename: sender.file_id) {
+                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: docData)
+                            if dataDecrypt != nil {
+                                docData = dataDecrypt!
+                            }
                             let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                             let tempPath = cachesDirectory.appendingPathComponent(sender.file_id)
                             try docData.write(to: tempPath)
@@ -2174,7 +2181,11 @@ extension SecondTabViewController: UITableViewDelegate, UITableViewDataSource {
                     }
                 } else if FileEncryption.shared.isSecureExists(filename: sender.audio_id) {
                     do {
-                        if let audioData = try FileEncryption.shared.readSecure(filename: sender.audio_id) {
+                        if var audioData = try FileEncryption.shared.readSecure(filename: sender.audio_id) {
+                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: audioData)
+                            if dataDecrypt != nil {
+                                audioData = dataDecrypt!
+                            }
                             let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                             let tempPath = cachesDirectory.appendingPathComponent(sender.audio_id)
                             try audioData.write(to: tempPath)
@@ -2268,11 +2279,16 @@ extension SecondTabViewController: UITableViewDelegate, UITableViewDataSource {
 //                        imageGif.animationRepeatCount = 4
                     } else if FileEncryption.shared.isSecureExists(filename: gifData){
                         do {
-                            let data = try FileEncryption.shared.readSecure(filename: gifData)
-                            if let imageData = SDAnimatedImage(data: data!) {
-                                imageGif.image = imageData
-//                                imageGif.shouldCustomLoopCount = true
-//                                imageGif.animationRepeatCount = 4
+                            if var data = try FileEncryption.shared.readSecure(filename: gifData) {
+                                let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: data)
+                                if dataDecrypt != nil {
+                                    data = dataDecrypt!
+                                }
+                                if let imageData = SDAnimatedImage(data: data) {
+                                    imageGif.image = imageData
+    //                                imageGif.shouldCustomLoopCount = true
+    //                                imageGif.animationRepeatCount = 4
+                                }
                             }
                         }
                         catch {
@@ -2347,9 +2363,14 @@ extension SecondTabViewController: UITableViewDelegate, UITableViewDataSource {
                     APIS.openImageNexilis(image: image)
                 } else if FileEncryption.shared.isSecureExists(filename: imgData) {
                     do {
-                        let data = try FileEncryption.shared.readSecure(filename: imgData)
-                        let image = UIImage(data: data!) ?? UIImage()
-                        APIS.openImageNexilis(image: image)
+                        if var data = try FileEncryption.shared.readSecure(filename: imgData) {
+                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: data)
+                            if dataDecrypt != nil {
+                                data = dataDecrypt!
+                            }
+                            let image = UIImage(data: data) ?? UIImage()
+                            APIS.openImageNexilis(image: image)
+                        }
                     }
                     catch {
                     }
@@ -2369,7 +2390,11 @@ extension SecondTabViewController: UITableViewDelegate, UITableViewDataSource {
                     APIS.openVideoNexilis(videoURL: videoURL)
                 } else if FileEncryption.shared.isSecureExists(filename: vidData) {
                     do {
-                        if let secureData = try FileEncryption.shared.readSecure(filename: vidData) {
+                        if var secureData = try FileEncryption.shared.readSecure(filename: vidData) {
+                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: secureData)
+                            if dataDecrypt != nil {
+                                secureData = dataDecrypt!
+                            }
                             let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                             let tempPath = cachesDirectory.appendingPathComponent(vidData)
                             try secureData.write(to: tempPath)
@@ -2399,7 +2424,11 @@ extension SecondTabViewController: UITableViewDelegate, UITableViewDataSource {
                     }
                 } else if FileEncryption.shared.isSecureExists(filename: gifData) {
                     do {
-                        if let secureData = try FileEncryption.shared.readSecure(filename: gifData) {
+                        if var secureData = try FileEncryption.shared.readSecure(filename: gifData) {
+                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: secureData)
+                            if dataDecrypt != nil {
+                                secureData = dataDecrypt!
+                            }
                             APIS.openImageNexilis(image: UIImage(), data: secureData, isGIF: true)
                         }
                     } catch {

BIN
NexilisLite/.DS_Store


+ 0 - 12
NexilisLite/NexilisLite.xcodeproj/project.pbxproj

@@ -1266,14 +1266,10 @@
 			inputFileListPaths = (
 				"${PODS_ROOT}/Target Support Files/Pods-NexilisLite/Pods-NexilisLite-resources-${CONFIGURATION}-input-files.xcfilelist",
 			);
-			inputPaths = (
-			);
 			name = "[CP] Copy Pods Resources";
 			outputFileListPaths = (
 				"${PODS_ROOT}/Target Support Files/Pods-NexilisLite/Pods-NexilisLite-resources-${CONFIGURATION}-output-files.xcfilelist",
 			);
-			outputPaths = (
-			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
 			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NexilisLite/Pods-NexilisLite-resources.sh\"\n";
@@ -1287,14 +1283,10 @@
 			inputFileListPaths = (
 				"${PODS_ROOT}/Target Support Files/Pods-NexilisLite-NexilisLiteTests/Pods-NexilisLite-NexilisLiteTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
 			);
-			inputPaths = (
-			);
 			name = "[CP] Embed Pods Frameworks";
 			outputFileListPaths = (
 				"${PODS_ROOT}/Target Support Files/Pods-NexilisLite-NexilisLiteTests/Pods-NexilisLite-NexilisLiteTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
 			);
-			outputPaths = (
-			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
 			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NexilisLite-NexilisLiteTests/Pods-NexilisLite-NexilisLiteTests-frameworks.sh\"\n";
@@ -1308,14 +1300,10 @@
 			inputFileListPaths = (
 				"${PODS_ROOT}/Target Support Files/Pods-NexilisLite-NexilisLiteTests/Pods-NexilisLite-NexilisLiteTests-resources-${CONFIGURATION}-input-files.xcfilelist",
 			);
-			inputPaths = (
-			);
 			name = "[CP] Copy Pods Resources";
 			outputFileListPaths = (
 				"${PODS_ROOT}/Target Support Files/Pods-NexilisLite-NexilisLiteTests/Pods-NexilisLite-NexilisLiteTests-resources-${CONFIGURATION}-output-files.xcfilelist",
 			);
-			outputPaths = (
-			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
 			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NexilisLite-NexilisLiteTests/Pods-NexilisLite-NexilisLiteTests-resources.sh\"\n";

+ 41 - 10
NexilisLite/NexilisLite/Source/APIS.swift

@@ -983,14 +983,34 @@ public class APIS: NSObject {
                                 }
                                 Nexilis.playRingtoneCall()
                             } else if code == "CL02" {
+                                print("data \(data)")
+                                let callFromName = data["call-cancel-name"] as? String ?? ""
                                 let callFrom = data["call-cancel"] as? String ?? ""
+                                let callType = data["call-type"] as? String ?? ""
 //                                if let uuidCall = uuidCall {
-                                    print("STOP RINGTONE CALL")
-                                    Nexilis.stopRingtoneCall()
-                                    print("removeDeliveredNotifications \(callFrom)")
-                                    Nexilis.callAPNActivated = false
-                                    let center = UNUserNotificationCenter.current()
-                                    center.removeDeliveredNotifications(withIdentifiers: [callFrom])
+                                Nexilis.stopRingtoneCall()
+                                Nexilis.callAPNActivated = false
+                                let center = UNUserNotificationCenter.current()
+                                center.removeDeliveredNotifications(withIdentifiers: [callFrom])
+                                var textCall = ""
+                                if callType == "1" {
+                                    textCall = "audio"
+                                } else {
+                                    textCall = "video"
+                                }
+                                let content = UNMutableNotificationContent()
+                                content.title = callFromName
+                                content.body = "☎️ Missed \(textCall) call".localized()
+                                content.userInfo = ["id" : callFrom, "type" : code, "callType": callType]
+                                content.sound = nil
+                                let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
+                                let request = UNNotificationRequest(identifier: callFrom, content: content, trigger: trigger)
+                                center.add(request) { error in
+                                    if let error = error {
+                                        print("Error scheduling notification: \(error.localizedDescription)")
+                                    }
+                                }
+                                Nexilis.saveMessageCall(idCall: (User.getMyPin() ?? "") + CoreMessage_TMessageUtil.getTID(), textMessage: "Missed \(textCall) call".localized() + " at 0", fPin: callFrom, lPin: (User.getMyPin() ?? ""), timeCall: String(Date().currentTimeMillis()), attachment_type: MessageScope.MISSED_CALL)
     //                                    CallManager.shared.endCall(with: uuidCall)
 //                                }
                             }
@@ -1149,7 +1169,11 @@ public class APIS: NSObject {
                     sourceURL = audioURL
                 } else if FileEncryption.shared.isSecureExists(filename: nameSound) {
                     do {
-                        if let audioData = try FileEncryption.shared.readSecure(filename: nameSound) {
+                        if var audioData = try FileEncryption.shared.readSecure(filename: nameSound) {
+                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: audioData)
+                            if dataDecrypt != nil {
+                                audioData = dataDecrypt!
+                            }
                             let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                             let tempPath = cachesDirectory.appendingPathComponent(nameSound)
                             try audioData.write(to: tempPath)
@@ -1390,11 +1414,14 @@ public class APIS: NSObject {
     }
     
     public static func enterBackground() {
-        if !API.bAVisOngoing() {
-            API.deinitConnection()
-        }
+//        if !API.bAVisOngoing() {
+//            API.deinitConnection()
+//        }
+        notifTimer.invalidate()
     }
     
+    public static var notifTimer = Timer()
+    public static var stopNotif = false
     public static func enterForeground() {
         APIS.checkNotificationPermission(completion: { isAllowed in
             if !isAllowed {
@@ -1404,6 +1431,10 @@ public class APIS: NSObject {
             }
         })
         DispatchQueue.main.async {
+            stopNotif = true
+            self.notifTimer = Timer.scheduledTimer(withTimeInterval: 30, repeats: false) { _ in
+                stopNotif = false
+            }
             do {
                 if !Nexilis.afterConnect && API.nGetCLXConnState() == 0 {
                     let id = Utils.getConnectionID()

+ 8 - 14
NexilisLite/NexilisLite/Source/Download.swift

@@ -93,26 +93,20 @@ public class Download {
                             let url = documentDir.appendingPathComponent(filename)
 //                            print("write file \(url.path)")
 //                            try successResponse.write(to: url)
-                            let dResponse = try FileEncryption.shared.decryptToMemory(successResponse, MasterKeyUtil.shared.getServerKey())
-                            if isImage {
-                                let imageDec = UIImage(data: dResponse)
-                                if imageDec != nil {
-                                    try dResponse.write(to: url)
-                                } else {
-                                    try successResponse.write(to: url)
-                                }
+                            let dResponse = FileEncryption.shared.decryptFileFromServer(data: successResponse)
+                            if dResponse != nil {
+                                try FileEncryption.shared.writeSecure(filename: filename, data: dResponse!)
+                            } else {
+                                try FileEncryption.shared.writeSecure(filename: filename, data: successResponse)
                             }
-                            else {
-                                try successResponse.write(to: url)
-                            }
-                            Nexilis.removeDownload(forKey: filename)
+                            _ = Nexilis.removeDownload(forKey: filename)
                             completion(filename,100)
                         }
                         catch {}
                     }
                     else {
-                        let statusCode = result.response?.statusCode
-                        print("Response fail: \(result.debugDescription)")
+//                        let statusCode = result.response?.statusCode
+//                        print("Response fail: \(result.debugDescription)")
                         completion(filename,-100)
                     }
                 }

+ 10 - 2
NexilisLite/NexilisLite/Source/Extension.swift

@@ -413,8 +413,12 @@ extension NSObject {
                 let image = UIImage(contentsOfFile: file.path)?.sd_resizedImage(with: CGSize(width: 400, height: 400), scaleMode: .aspectFill)
                 completion(true, false, isCircle ? image?.circleMasked : image)
             } else if var tempData = try FileEncryption.shared.readSecure(filename: url) {
+                let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: tempData)
+                if dataDecrypt != nil {
+                    tempData = dataDecrypt!
+                }
                 let image = UIImage(data: tempData)?.sd_resizedImage(with: CGSize(width: 400, height: 400), scaleMode: .aspectFill)
-                FileEncryption.shared.wipeData(&tempData)
+//                FileEncryption.shared.wipeData(&tempData)
                 completion(true, true, isCircle ? image?.circleMasked : image)
             } else {
                 completion(false, false, placeholderImage)
@@ -439,7 +443,11 @@ extension NSObject {
                                 completion(true, true, isCircle ? image?.circleMasked : image)
                             } else if FileEncryption.shared.isSecureExists(filename: url) {
                                 do {
-                                    if let imageData = try FileEncryption.shared.readSecure(filename: url) {
+                                    if var imageData = try FileEncryption.shared.readSecure(filename: url) {
+                                        let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: imageData)
+                                        if dataDecrypt != nil {
+                                            imageData = dataDecrypt!
+                                        }
                                         let image = UIImage(data: imageData)?.sd_resizedImage(with: CGSize(width: 400, height: 400), scaleMode: .aspectFill)
                                         completion(true, true, isCircle ? image?.circleMasked : image)
                                     }

+ 100 - 146
NexilisLite/NexilisLite/Source/FileEncryption.swift

@@ -11,193 +11,128 @@ import CommonCrypto
 
 public class FileEncryption {
     
+    public var aesKey: SymmetricKey?
+    public var aesIV: Data?
+    
     public static let shared = FileEncryption()
 
     private init() {}
     
-    func generateIV() -> Data {
-        var iv = Data(count: kCCBlockSizeAES128)
-        let result = iv.withUnsafeMutableBytes {
-            SecRandomCopyBytes(kSecRandomDefault, kCCBlockSizeAES128, $0.baseAddress!)
-        }
-        precondition(result == errSecSuccess, "Failed to generate IV")
-        return iv
-    }
-    
-    func readDataFromFile(fileURL: URL) -> Data? {
-        do {
-            return try Data(contentsOf: fileURL)
-        } catch {
-            print("Failed to read file: \(error)")
-            return nil
-        }
-    }
-    
     public func readSecure(filename: String) throws -> Data? {
         let fileManager = FileManager.default
         let documentDir = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
-        let secureDir = documentDir.appendingPathComponent("secure")
-        let fileURL = secureDir.appendingPathComponent(filename)
-        return try decryptToMemory(fileURL)
+        let fileURL = documentDir.appendingPathComponent("Secure").appendingPathComponent(filename)
+
+        let encryptedData = try Data(contentsOf: fileURL)
+        let sealedBox = try AES.GCM.SealedBox(combined: encryptedData)
+        let decryptedData = try AES.GCM.open(sealedBox, using: MasterKeyUtil.shared.getMasterKey())
+
+        return decryptedData
     }
     
-    public func writeSecure(filename: String? = nil, fileURL : URL? = nil, data: Data? = nil) throws -> [Any]? {
+    public func writeSecure(filename: String? = nil, data: Data? = nil) throws {
         let fileManager = FileManager.default
+
+        // Get the app's Documents directory
         let documentDir = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
-        let secureDir = documentDir.appendingPathComponent("secure")
-        guard let inputFilename = filename ?? fileURL?.lastPathComponent else { return nil }
-        let inputURL = fileURL ?? documentDir.appendingPathComponent(inputFilename)
-        let outputURL = secureDir.appendingPathComponent(inputFilename)
-        guard let finalData = data ?? readDataFromFile(fileURL: inputURL) else { return nil }
-        let encryptedData = encryptFile(finalData)
-        do {
-            try encryptedData?.write(to: outputURL)
-            try fileManager.removeItem(at: inputURL)
-//            print("File deleted successfully")
-        } catch {
-            print("Error deleting file: \(error)")
+
+        // Optional: Create a "Secure" subdirectory
+        let secureDir = documentDir.appendingPathComponent("Secure", isDirectory: true)
+        if !fileManager.fileExists(atPath: secureDir.path) {
+            try fileManager.createDirectory(at: secureDir, withIntermediateDirectories: true)
         }
-        return [outputURL.lastPathComponent, outputURL]
+
+        // Create the file URL
+        let fileURL = secureDir.appendingPathComponent(filename ?? "")
+
+        // Encrypt the data
+        let sealedBox = try AES.GCM.seal(data ?? Data(), using: MasterKeyUtil.shared.getMasterKey())
+        let encryptedData = sealedBox.combined!
+
+        // Write encrypted data to file
+        try encryptedData.write(to: fileURL)
     }
     
     public func isSecureExists(filename: String) -> Bool {
-        let fileManager = FileManager.default
         do {
+            let fileManager = FileManager.default
             let documentDir = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
-            let secureDir = documentDir.appendingPathComponent("secure")
-            let outputURL = secureDir.appendingPathComponent(filename)
-            return fileManager.fileExists(atPath: outputURL.path)
+            let fileURL = documentDir.appendingPathComponent("Secure").appendingPathComponent(filename)
+            return fileManager.fileExists(atPath: fileURL.path)
         } catch {
             return false
         }
-        
-        
-    }
-    
-    func listSecure() throws -> [URL] {
-        let fileManager = FileManager.default
-        do {
-            let documentDir = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
-            let secureDir = documentDir.appendingPathComponent("secure")
-            let files = try fileManager.contentsOfDirectory(at: secureDir, includingPropertiesForKeys: nil, options: [])
-            return files
-        }
-    }
-    
-    func wipeData(_ data: inout Data) {
-        data.resetBytes(in: 0..<data.count)
-        data.count = 0
-    }
-    
-    func encryptFile(_ fileURL: URL) -> Data? {
-        guard let fileData = readDataFromFile(fileURL: fileURL) else { return nil }
-        return encryptFile(fileData)
     }
     
-    func encryptFile(_ data: Data) -> Data? {
+    public func decryptFileFromServer(data: Data) -> Data? {
         do {
-            let sealedBox = try AES.GCM.seal(data, using: MasterKeyUtil.shared.getMasterKey())
-            return sealedBox.combined
+            if aesKey == nil {
+                aesKey = try getAESKey()
+            }
+            if aesIV == nil {
+                aesIV = try getAESIV()
+            }
         } catch {
-            print("Encryption failed: \(error)")
+            print("Error retrieving AES key or IV: \(error)")
             return nil
         }
-    }
-    
-    func encryptFile(_ inputURL: URL, _ outputURL: URL, _ key: SymmetricKey) throws {
-        let keyData = key.withUnsafeBytes { Data($0) }
         
-        let iv = MasterKeyUtil.shared.getServerKeyIV()
-        let data = try Data(contentsOf: inputURL)
-        let encryptedData = Data(count: data.count + kCCBlockSizeAES128)
-        var finalData = encryptedData
-        
-        var numBytesEncrypted: size_t = 0
-
-        let status = finalData.withUnsafeMutableBytes { encryptedBytes in
-            data.withUnsafeBytes { dataBytes in
-                key.withUnsafeBytes { keyBytes in
-                    iv.withUnsafeBytes { ivBytes in
-                        CCCrypt(
-                            CCOperation(kCCEncrypt),
-                            CCAlgorithm(kCCAlgorithmAES),
-                            CCOptions(kCCOptionPKCS7Padding),
-                            keyBytes.baseAddress, keyData.count,
-                            ivBytes.baseAddress,
-                            dataBytes.baseAddress, data.count,
-                            encryptedBytes.baseAddress, encryptedData.count,
-                            &numBytesEncrypted
-                        )
-                    }
-                }
-            }
+        guard let key = aesKey, let iv = aesIV else {
+            return nil
         }
+        
+        do {
+            let nonce = try AES.GCM.Nonce(data: iv)
+            let sealedBox = try AES.GCM.SealedBox(nonce: nonce, ciphertext: data.dropLast(16), tag: data.suffix(16))
+            let decryptedData = try AES.GCM.open(sealedBox, using: key)
 
-        guard status == kCCSuccess else {
-            throw NSError(domain: "EncryptionError", code: Int(status), userInfo: nil)
+            return decryptedData
+        } catch {
+//            print("Decryption error: \(error.localizedDescription)")
+            return nil
         }
-
-        finalData.count = numBytesEncrypted
-
-        // Write IV and encrypted data to the output file
-        var outputData = Data()
-        outputData.append(iv)
-        outputData.append(finalData)
-        try outputData.write(to: outputURL)
     }
     
-    func decryptToMemory(_ encryptedData: Data) -> Data? {
+    func encryptFileToServer(data: Data) -> Data? {
         do {
-            let sealedBox = try AES.GCM.SealedBox(combined: encryptedData)
-            return try AES.GCM.open(sealedBox, using: MasterKeyUtil.shared.getMasterKey())
+            if aesKey == nil {
+                aesKey = try getAESKey()
+            }
+            if aesIV == nil {
+                aesIV = try getAESIV()
+            }
         } catch {
-            print("Decryption failed: \(error)")
-            return encryptedData
+            print("Error retrieving AES key or IV: \(error)")
+            return nil
         }
-    }
-
-    func decryptToMemory(_ encryptedData: URL) throws -> Data? {
-        let encryptedData = try Data(contentsOf: encryptedData)
-        return decryptToMemory(encryptedData)
-    }
-    
-    func decryptToMemory(_ encryptedData: Data, _ key: SymmetricKey) throws -> Data {
-        let keyData = key.withUnsafeBytes { Data($0) }
         
-        let iv = encryptedData.prefix(kCCBlockSizeAES128)
-        let cipherText = encryptedData.suffix(from: kCCBlockSizeAES128)
-        let decryptedData = Data(count: cipherText.count + kCCBlockSizeAES128)
-        var finalData = decryptedData
-        var numBytesDecrypted: size_t = 0
-
-        let status = finalData.withUnsafeMutableBytes { decryptedBytes in
-            cipherText.withUnsafeBytes { cipherBytes in
-                key.withUnsafeBytes { keyBytes in
-                    iv.withUnsafeBytes { ivBytes in
-                        CCCrypt(
-                            CCOperation(kCCDecrypt),
-                            CCAlgorithm(kCCAlgorithmAES),
-                            CCOptions(kCCOptionPKCS7Padding),
-                            keyBytes.baseAddress, keyData.count,
-                            ivBytes.baseAddress,
-                            cipherBytes.baseAddress, cipherText.count,
-                            decryptedBytes.baseAddress, decryptedData.count,
-                            &numBytesDecrypted
-                        )
-                    }
-                }
-            }
+        guard let key = aesKey, let iv = aesIV else {
+            return nil
         }
+        
+        do {
+            let nonce = try AES.GCM.Nonce(data: iv)
+            let sealedBox = try AES.GCM.seal(data, using: key, nonce: nonce)
+            var encryptedData = sealedBox.ciphertext
+            encryptedData.append(sealedBox.tag)
 
-        guard status == kCCSuccess else {
             return encryptedData
+        } catch {
+//            print("Encryption failed: \(error)")
+            return nil
         }
-
-        finalData.count = numBytesDecrypted
-        return finalData
     }
     
-    func wipeFolder() {
+    private func getAESKey() throws -> SymmetricKey {
+        let keyData = Data(base64Encoded: Utils.getSecureFolderEncrypt(), options: .ignoreUnknownCharacters)!
+        return SymmetricKey(data: keyData)
+    }
+    
+    private func getAESIV() throws -> Data {
+        return Data(base64Encoded: Utils.getSecureFolderEncryptIv(), options: .ignoreUnknownCharacters)!
+    }
+    
+    func wipeFolderOldSecure() {
         let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
         let secureDir = documentsDirectory.appendingPathComponent("secure")
         if FileManager.default.fileExists(atPath: secureDir.path) {
@@ -205,10 +140,29 @@ public class FileEncryption {
                 let fileNames = try FileManager.default.contentsOfDirectory(atPath: secureDir.path)
                 for fileName in fileNames {
                     let filePath = secureDir.appendingPathComponent(fileName)
-                    try FileManager.default.removeItem(atPath: secureDir.path)
+                    try FileManager.default.removeItem(atPath: filePath.path)
                 }
                 try FileManager.default.removeItem(atPath: secureDir.path)
                 print("Secure folder deleted successfully")
+                wipeFolderDocument()
+            } catch {
+                print("Error deleting secure folder")
+            }
+        }
+    }
+    
+    func wipeFolderDocument() {
+        let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
+        if FileManager.default.fileExists(atPath: documentsDirectory.path) {
+            do {
+                let fileNames = try FileManager.default.contentsOfDirectory(atPath: documentsDirectory.path)
+                for fileName in fileNames {
+                    let filePath = documentsDirectory.appendingPathComponent(fileName)
+                    if fileName == "encrypted_db_es.db" {
+                        continue
+                    }
+                    try FileManager.default.removeItem(atPath: filePath.path)
+                }
             } catch {
                 print("Error deleting secure folder")
             }

+ 8 - 10
NexilisLite/NexilisLite/Source/IncomingThread.swift

@@ -245,7 +245,7 @@ class IncomingThread {
                     if Utils.getForceAnonymous() {
                         viewController?.deleteAllRecordDatabase()
                         SecureUserDefaults.shared.removeValue(forKey: "device_id")
-                        FileEncryption.shared.wipeFolder()
+//                        FileEncryption.shared.wipeFolder()
                         Nexilis.destroyAll()
                     }
                     DispatchQueue.main.async {
@@ -1296,17 +1296,15 @@ class IncomingThread {
             }
         }
         let media = message.getMedia()
-        //print("MEDIA \(media)");
         let thumb_id = message.getBody(key: CoreMessage_TMessageKey.THUMB_ID)
-        do {
-            let data = Data(media)
-            let documentDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
-            let url = documentDir.appendingPathComponent(thumb_id)
-            //print("write thumb \(url.path)")
-            try data.write(to: url, options: .atomic)
-        } catch {
+        if media.count != 0 {
+            do {
+                let data = Data(media)
+                try FileEncryption.shared.writeSecure(filename: thumb_id, data: data)
+            } catch {
+            }
         }
-        if (!thumb_id.isEmpty) {
+        if (!thumb_id.isEmpty && media.count == 0) {
             Download().startHTTP(forKey: thumb_id) { (file, progress) in
                 //print ("masuk download \(progress)")
                 if(progress == 100 || progress == -100) {

+ 0 - 29
NexilisLite/NexilisLite/Source/MasterKeyUtil.swift

@@ -56,10 +56,6 @@ public class MasterKeyUtil {
         try generateAndStoreKey(keyAlias)
     }
     
-    func generateAndStoreServerKey(_ key_s: String) throws {
-        try generateAndStoreKey(serverKeyAlias, key_s: key_s)
-    }
-    
     func isDeviceNotSecure() -> Bool {
         let context = LAContext()
         var error: NSError?
@@ -88,11 +84,6 @@ public class MasterKeyUtil {
         }
     }
     
-    func getServerKeyIV() -> Data {
-        let keyData = base64toData(Utils.getSecureFolderEncryptIv()) ?? Data()
-        return keyData
-    }
-    
     func getMasterKey() throws -> SymmetricKey {
         if (Nexilis.checkingAccess(key: "authentication") && isDeviceNotSecure()) {
             var result = false
@@ -157,26 +148,6 @@ public class MasterKeyUtil {
         return SymmetricKey(data: keyData)
     }
     
-    func getServerKey() throws -> SymmetricKey {
-        let query: [String: Any] = [
-            kSecClass as String: kSecClassKey,
-            kSecAttrApplicationTag as String: serverKeyAlias,
-            kSecReturnData as String: true
-        ]
-        
-        var item: CFTypeRef?
-        let status = SecItemCopyMatching(query as CFDictionary, &item)
-        guard status == errSecSuccess else {
-            throw NSError(domain: "KeychainError", code: Int(status), userInfo: nil)
-        }
-        
-        guard let keyData = item as? Data else {
-            throw NSError(domain: "KeyRetrievalError", code: -1, userInfo: nil)
-        }
-        
-        return SymmetricKey(data: keyData)
-    }
-    
     func encryptP(data: Data) throws -> Data {
         let key = try getPrefsKey()
         let sealedBox = try AES.GCM.seal(data, using: key)

+ 5 - 4
NexilisLite/NexilisLite/Source/Network.swift

@@ -217,9 +217,6 @@ public class Network {
                         let filenameServer = "\(name)"
                         let fileDirServer = tempDir.appendingPathComponent(filenameServer)
                         let fileURLServer = URL(fileURLWithPath: fileDirServer.path)
-                        try FileEncryption.shared.encryptFile(fileURL, fileURLServer, MasterKeyUtil.shared.getServerKey())
-//                        let dataSecure = try FileEncryption.shared.encryptFile(fileURL)
-//                        dataSecure?.write(to: fileURLSecure)
                         filesIn.append(fileURL)
                         filesTempServer.append(fileURLServer)
                     }
@@ -248,7 +245,11 @@ public class Network {
         
         let uploadRequest = SessionManager.shared.session.upload(multipartFormData: { (multipartFormData: MultipartFormData) in
             for (key, value) in parameters {
-                multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key as String)
+                var dataToUpload = "\(value)".data(using: String.Encoding.utf8)!
+                if Nexilis.checkingAccess(key: "secure_folder_encrypt"){
+                    dataToUpload = FileEncryption.shared.encryptFileToServer(data: dataToUpload) ?? Data()
+                }
+                multipartFormData.append(dataToUpload, withName: key as String)
                 //print(multipartFormData)
             }
             

+ 57 - 37
NexilisLite/NexilisLite/Source/Nexilis.swift

@@ -15,6 +15,7 @@ import FMDB
 import QuickLook
 import NotificationBannerSwift
 import SDWebImage
+import CryptoKit
 
 public class Nexilis: NSObject {
     public static var sAPIKey = ""
@@ -304,6 +305,7 @@ public class Nexilis: NSObject {
         }
         
         _ = LocationManager()
+        FileEncryption.shared.wipeFolderOldSecure()
     }
     
     private static var ringtoneID: SystemSoundID = 0
@@ -526,21 +528,16 @@ public class Nexilis: NSObject {
                                     Utils.setAuthenticationDuration(value: ad)
                                 }
                                 if jsonData["secure_folder_encrypt_key"]! != nil {
-                                    do {
-                                        if let documentsDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
-                                            let secureURL = documentsDirectoryURL.appendingPathComponent("secure")
-                                            if !FileManager.default.fileExists(atPath: secureURL.path){
-                                                 try FileManager.default.createDirectory(at: secureURL, withIntermediateDirectories: true, attributes: nil)
-                                            }
-                                        }
-                                        try MasterKeyUtil.shared.generateAndStoreServerKey(jsonData["secure_folder_encrypt_key"] as! String)
-                                    }
-                                    catch {
-                                        
+                                    if let dataKey = Data(base64Encoded: jsonData["secure_folder_encrypt_key"] as! String, options: .ignoreUnknownCharacters) {
+                                        FileEncryption.shared.aesKey = SymmetricKey(data: dataKey)
+                                        Utils.setSecureFolderEncrypt(value: jsonData["secure_folder_encrypt_key"] as! String)
                                     }
                                 }
                                 if jsonData["secure_folder_encrypt_key_iv"]! != nil {
-                                    Utils.setSecureFolderEncryptIv(value: jsonData["secure_folder_encrypt_key_iv"] as! String)
+                                    if let dataKey = Data(base64Encoded: jsonData["secure_folder_encrypt_key_iv"] as! String, options: .ignoreUnknownCharacters) {
+                                        FileEncryption.shared.aesIV = dataKey
+                                        Utils.setSecureFolderEncryptIv(value: jsonData["secure_folder_encrypt_key_iv"] as! String)
+                                    }
                                 }
                                 if jsonData["chatbot_greetings"]! != nil {
                                     if let greeting = jsonData["chatbot_greetings"] as? String {
@@ -1834,7 +1831,11 @@ public class Nexilis: NSObject {
         }
         else if FileEncryption.shared.isSecureExists(filename: url.lastPathComponent) {
             do {
-                if let imageData = try FileEncryption.shared.readSecure(filename: url.lastPathComponent) {
+                if var imageData = try FileEncryption.shared.readSecure(filename: url.lastPathComponent) {
+                    let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: imageData)
+                    if dataDecrypt != nil {
+                        imageData = dataDecrypt!
+                    }
                     image = UIImage(data: imageData)
                 }
             }
@@ -2792,17 +2793,22 @@ extension Nexilis: MessageDelegate {
                                     }
                                 } else if FileEncryption.shared.isSecureExists(filename: image) {
                                     do {
-                                        let data = try FileEncryption.shared.readSecure(filename: image)
-                                        let image = UIImage(data: data!)
-                                        let previewImageVC = PreviewAttachmentImageVideo(nibName: "PreviewAttachmentImageVideo", bundle: Bundle.resourceBundle(for: Nexilis.self))
-                                        previewImageVC.image = image
-                                        previewImageVC.isHiddenTextField = true
-                                        previewImageVC.modalPresentationStyle = .overFullScreen
-                                        previewImageVC.modalTransitionStyle  = .crossDissolve
-                                        if UIApplication.shared.visibleViewController?.navigationController != nil {
-                                            UIApplication.shared.visibleViewController?.navigationController?.present(previewImageVC, animated: true, completion: nil)
-                                        } else {
-                                            UIApplication.shared.visibleViewController?.present(previewImageVC, animated: true, completion: nil)
+                                        if var data = try FileEncryption.shared.readSecure(filename: image) {
+                                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: data)
+                                            if dataDecrypt != nil {
+                                                data = dataDecrypt!
+                                            }
+                                            let image = UIImage(data: data)
+                                            let previewImageVC = PreviewAttachmentImageVideo(nibName: "PreviewAttachmentImageVideo", bundle: Bundle.resourceBundle(for: Nexilis.self))
+                                            previewImageVC.image = image
+                                            previewImageVC.isHiddenTextField = true
+                                            previewImageVC.modalPresentationStyle = .overFullScreen
+                                            previewImageVC.modalTransitionStyle  = .crossDissolve
+                                            if UIApplication.shared.visibleViewController?.navigationController != nil {
+                                                UIApplication.shared.visibleViewController?.navigationController?.present(previewImageVC, animated: true, completion: nil)
+                                            } else {
+                                                UIApplication.shared.visibleViewController?.present(previewImageVC, animated: true, completion: nil)
+                                            }
                                         }
                                     } catch {
                                         
@@ -2812,12 +2818,6 @@ extension Nexilis: MessageDelegate {
                                         guard progress == 100 else {
                                             return
                                         }
-                                        
-                                        do {
-                                            try FileEncryption.shared.writeSecure(filename: image)
-                                        } catch {
-                                            
-                                        }
                 
                                         DispatchQueue.main.async {
                                             var image : UIImage?
@@ -2827,7 +2827,12 @@ extension Nexilis: MessageDelegate {
                                             else if FileEncryption.shared.isSecureExists(filename: imageURL.lastPathComponent) {
                                                 do {
                                                     if let imageData = try FileEncryption.shared.readSecure(filename: imageURL.lastPathComponent) {
-                                                        image = UIImage(data: imageData)
+                                                        let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: imageData)
+                                                        if dataDecrypt == nil {
+                                                            image = UIImage(data: imageData)
+                                                        } else {
+                                                            image = UIImage(data: dataDecrypt!)
+                                                        }
                                                     }
                                                 } catch {
                                                     
@@ -2877,7 +2882,11 @@ extension Nexilis: MessageDelegate {
                                     }
                                 } else if FileEncryption.shared.isSecureExists(filename: file) {
                                     do {
-                                        if let docData = try FileEncryption.shared.readSecure(filename: file) {
+                                        if var docData = try FileEncryption.shared.readSecure(filename: file) {
+                                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: docData)
+                                            if dataDecrypt != nil {
+                                                docData = dataDecrypt!
+                                            }
                                             let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                                             let tempPath = cachesDirectory.appendingPathComponent(file)
                                             try docData.write(to: tempPath)
@@ -2904,8 +2913,11 @@ extension Nexilis: MessageDelegate {
                                                 return
                                             }
                                             do {
-                                                let secureFilename = try FileEncryption.shared.writeSecure(filename: name)
-                                                if let docData = try FileEncryption.shared.readSecure(filename: secureFilename?[0] as! String) {
+                                                if var docData = try FileEncryption.shared.readSecure(filename: file) {
+                                                    let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: docData)
+                                                    if dataDecrypt != nil {
+                                                        docData = dataDecrypt!
+                                                    }
                                                     let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                                                     let tempPath = cachesDirectory.appendingPathComponent(file)
                                                     try docData.write(to: tempPath)
@@ -3714,7 +3726,7 @@ extension Nexilis: MessageDelegate {
                 }
                 return
             }
-            if !Nexilis.showLibraryNotification || APIS.checkAppStateisBackground() {
+            if !Nexilis.showLibraryNotification || APIS.checkAppStateisBackground() || APIS.stopNotif {
                 return
             }
             let sender = message.getBody(key: CoreMessage_TMessageKey.F_PIN)
@@ -4006,7 +4018,11 @@ extension Nexilis: MessageDelegate {
                                                                 }
                                                             } else if FileEncryption.shared.isSecureExists(filename: nameSound) {
                                                                 do {
-                                                                    if let audioData = try FileEncryption.shared.readSecure(filename: nameSound) {
+                                                                    if var audioData = try FileEncryption.shared.readSecure(filename: nameSound) {
+                                                                        let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: audioData)
+                                                                        if dataDecrypt != nil {
+                                                                            audioData = dataDecrypt!
+                                                                        }
                                                                         let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                                                                         let tempPath = cachesDirectory.appendingPathComponent(nameSound)
                                                                         try audioData.write(to: tempPath)
@@ -4125,7 +4141,11 @@ extension Nexilis: MessageDelegate {
                                             }
                                         } else if FileEncryption.shared.isSecureExists(filename: nameSound) {
                                             do {
-                                                if let audioData = try FileEncryption.shared.readSecure(filename: nameSound) {
+                                                if var audioData = try FileEncryption.shared.readSecure(filename: nameSound) {
+                                                    let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: audioData)
+                                                    if dataDecrypt != nil {
+                                                        audioData = dataDecrypt!
+                                                    }
                                                     let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                                                     let tempPath = cachesDirectory.appendingPathComponent(nameSound)
                                                     try audioData.write(to: tempPath)

+ 11 - 10
NexilisLite/NexilisLite/Source/OutgoingThread.swift

@@ -166,13 +166,17 @@ class OutgoingThread {
                 Network().uploadHTTP(name: message.getBody(key: CoreMessage_TMessageKey.THUMB_ID)) { (result, progress) in
                     if result, progress == 100 {
                         do {
-                            let fileManager = FileManager.default
-                            let documentDir = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
-                            let fileDir = documentDir.appendingPathComponent(message.getBody(key: CoreMessage_TMessageKey.THUMB_ID))
-                            let path = fileDir.path
-                            if FileManager.default.fileExists(atPath: path) {
-                                let data = try Data(contentsOf: URL(fileURLWithPath: path))
-                                message.setMedia(media: [UInt8] (data))
+                            do{
+                                try FileEncryption.shared.writeSecure(filename: fileName)
+                                if var data = try FileEncryption.shared.readSecure(filename: fileName) {
+                                    let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: data)
+                                    if dataDecrypt != nil {
+                                        data = dataDecrypt!
+                                    }
+                                    message.setMedia(media: [UInt8] (data))
+                                }
+                            } catch {
+                                
                             }
                         } catch {}
                         Network().uploadHTTP(name: fileName) { (result, progress) in
@@ -201,17 +205,14 @@ class OutgoingThread {
                                             
                                         }
                                     } else {
-                                        print("masuk 1")
                                         self.retryUpload(message: message, fileName: fileName)
                                     }
                                 }
                             } else {
-                                print("masuk 2")
                                 self.retryUpload(message: message, fileName: fileName)
                             }
                         }
                     } else {
-                        print("masuk 3")
                         if !result {
                             self.retryUpload(message: message, fileName: fileName)
                         }

+ 11 - 0
NexilisLite/NexilisLite/Source/Utils.swift

@@ -647,6 +647,17 @@ public final class Utils {
         return "easySoftIndonesia"
     }
     
+    public static func setSecureFolderEncrypt(value: String){
+        SecureUserDefaults.shared.set(value, forKey: "secure_folder_encrypt_key")
+    }
+    
+    public static func getSecureFolderEncrypt() -> String {
+        if let value: String = SecureUserDefaults.shared.value(forKey: "secure_folder_encrypt_key") {
+            return value
+        }
+        return "easySoftIndonesia"
+    }
+    
     public static func setSecureFolderEncryptIv(value: String){
         SecureUserDefaults.shared.set(value, forKey: "secure_folder_encrypt_key_iv")
     }

+ 17 - 2
NexilisLite/NexilisLite/Source/View/Call/AudioViewController.swift

@@ -199,6 +199,15 @@ extension UIImageView {
             if FileManager().fileExists(atPath: file.path) {
                 self.image = UIImage(contentsOfFile: file.path)
                 self.backgroundColor = .clear
+            } else if FileEncryption.shared.isSecureExists(filename: url) {
+                if var dataFile = try? FileEncryption.shared.readSecure(filename: url) {
+                    let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: dataFile)
+                    if dataDecrypt != nil {
+                        dataFile = dataDecrypt!
+                    }
+                    self.image = UIImage(data: dataFile)
+                    self.backgroundColor = .clear
+                }
             } else {
                 Download().startHTTP(forKey: url) { (name, progress) in
                     print ("masuk download \(progress)")
@@ -208,8 +217,14 @@ extension UIImageView {
                     
                     DispatchQueue.main.async {
                         if UIImageView.urlStore[tmpAddress] == url {
-                            self.image = UIImage(contentsOfFile: file.path)
-                            self.backgroundColor = .clear
+                            if var dataFile = try? FileEncryption.shared.readSecure(filename: url) {
+                                let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: dataFile)
+                                if dataDecrypt != nil {
+                                    dataFile = dataDecrypt!
+                                }
+                                self.image = UIImage(data: dataFile)
+                                self.backgroundColor = .clear
+                            }
                         }
                     }
                 }

+ 26 - 2
NexilisLite/NexilisLite/Source/View/Call/QmeraAudioViewController.swift

@@ -727,7 +727,28 @@ class QmeraAudioViewController: UIViewController {
                 self.users.append(user)
                 // Start Calling
 //                Nexilis.shared.callManager.startCall(handle: user.pin)
-                API.initiateCCall(sParty: user.pin)
+                if self.callFCM {
+                    DispatchQueue.global().async {
+                        if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getCalling(fPin: user.pin, type: "1"), timeout: 30 * 1000) {
+                            if response.isOk() {
+                            } else if response.getBody(key: CoreMessage_TMessageKey.ERRCOD, default_value: "99") == "01" {
+                                API.initiateCCall(sParty: user.pin)
+                                Nexilis.playRingbacktoneCall()
+                            } else {
+                                Nexilis.stopRingbacktoneCall()
+                            }
+                        } else {
+                            let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                            imageView.tintColor = .white
+                            let banner = FloatingNotificationBanner(title: "Unable to access servers. 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()
+                        }
+                    }
+                } else {
+                    API.initiateCCall(sParty: user.pin)
+                    Nexilis.playRingbacktoneCall()
+                }
+               
             }
         }
         controller.selectedUser.append(contentsOf: users)
@@ -871,7 +892,7 @@ class QmeraAudioViewController: UIViewController {
 //                for i in 0..<Nexilis.shared.callManager.calls.count {
 //                    Nexilis.shared.callManager.end(call: Nexilis.shared.callManager.calls[i])
 //                }
-                if callFCM {
+                if callFCM && self.timer == nil {
                     DispatchQueue.global().async {
                         if let _ = Nexilis.writeSync(message: CoreMessage_TMessageBank.getCancelCall(fPin: self.user!.pin, type: "1"), timeout: 30 * 1000) {
                         } else {
@@ -1061,6 +1082,7 @@ class QmeraAudioViewController: UIViewController {
                                 self.end.isEnabled = false
                             }
                             QmeraAudioViewController.isLoop = false
+                            QmeraAudioViewController.bSpeakerPhone = false
                             DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                                 self.didEnd(sender: true)
                             }
@@ -1089,6 +1111,7 @@ class QmeraAudioViewController: UIViewController {
                             self.end.isEnabled = false
                         }
                         QmeraAudioViewController.isLoop = false
+                        QmeraAudioViewController.bSpeakerPhone = false
                         DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                             self.didEnd(sender: true)
                         }
@@ -1118,6 +1141,7 @@ class QmeraAudioViewController: UIViewController {
                             }
                         }
                         QmeraAudioViewController.isLoop = false
+                        QmeraAudioViewController.bSpeakerPhone = false
                         DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                             self.didEnd(sender: true)
                         }

+ 55 - 14
NexilisLite/NexilisLite/Source/View/Call/QmeraVideoViewController.swift

@@ -647,6 +647,7 @@ class QmeraVideoViewController: UIViewController {
                 Nexilis.stopRingtoneCall()
                 Nexilis.stopRingbacktoneCall()
                 QmeraVideoViewController.isLoop = false
+                QmeraVideoViewController.bSpeakerPhone = false
                 self.endAllCall()
                 self.dismiss(animated: true, completion: nil)
             }))
@@ -655,6 +656,17 @@ class QmeraVideoViewController: UIViewController {
             let alert = LibAlertController(title: "End Video Call".localized(), message: "Are you sure you want to end video call?".localized(), preferredStyle: .alert)
             alert.addAction(UIAlertAction(title: "No".localized(), style: UIAlertAction.Style.default, handler: nil))
             alert.addAction(UIAlertAction(title: "Yes".localized(), style: UIAlertAction.Style.default, handler: {(_) in
+                if self.callFCM && !self.vcTimer.isValid {
+                    DispatchQueue.global().async {
+                        if let _ = Nexilis.writeSync(message: CoreMessage_TMessageBank.getCancelCall(fPin: self.dataPerson[0]["f_pin"]!!, type: "2"), timeout: 30 * 1000) {
+                        } else {
+                            let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                            imageView.tintColor = .white
+                            let banner = FloatingNotificationBanner(title: "Unable to access servers. 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()
+                        }
+                    }
+                }
                 self.makeStateCall()
                 Nexilis.stopRingtoneCall()
                 Nexilis.stopRingbacktoneCall()
@@ -692,6 +704,7 @@ class QmeraVideoViewController: UIViewController {
                 self.vcTimer.invalidate()
 //                self.labelTimerVC.text = "Video call is over".localized()
                 QmeraVideoViewController.isLoop = false
+                QmeraVideoViewController.bSpeakerPhone = false
                 self.endAllCall()
                 DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                     if self.isInisiator && !self.isPresent {
@@ -1093,9 +1106,30 @@ class QmeraVideoViewController: UIViewController {
                         self.isAddCall = data["f_pin"]!!
                     }
                 } else {
-                    DispatchQueue.main.async {
-                        self.dataPerson.append(data)
-                        API.initiateCCall(sParty: data["f_pin"]!, nCamIdx: 1, nResIdx: 2, nVQuality: 4, ivRemoteView: self.listRemoteViewFix, ivLocalView: self.cameraView, ivRemoteZ: self.zoomView)
+                    if self.callFCM {
+                        DispatchQueue.global().async {
+                            if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getCalling(fPin: data["f_pin"]!!, type: "2"), timeout: 30 * 1000) {
+                                if response.isOk() {
+                                } else if response.getBody(key: CoreMessage_TMessageKey.ERRCOD, default_value: "99") == "01" {
+                                    self.dataPerson.append(data)
+                                    API.initiateCCall(sParty: data["f_pin"]!, nCamIdx: 1, nResIdx: 2, nVQuality: 4, ivRemoteView: self.listRemoteViewFix, ivLocalView: self.cameraView, ivRemoteZ: self.zoomView)
+                                    Nexilis.playRingbacktoneCall()
+                                } else {
+                                    Nexilis.stopRingbacktoneCall()
+                                }
+                            } else {
+                                let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                                imageView.tintColor = .white
+                                let banner = FloatingNotificationBanner(title: "Unable to access servers. 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()
+                            }
+                        }
+                    } else {
+                        DispatchQueue.main.async {
+                            self.dataPerson.append(data)
+                            API.initiateCCall(sParty: data["f_pin"]!, nCamIdx: 1, nResIdx: 2, nVQuality: 4, ivRemoteView: self.listRemoteViewFix, ivLocalView: self.cameraView, ivRemoteZ: self.zoomView)
+                            Nexilis.playRingbacktoneCall()
+                        }
                     }
                 }
             }
@@ -1169,7 +1203,7 @@ class QmeraVideoViewController: UIViewController {
             }
         } else if (state == Nexilis.VIDEO_CALL_ZOOM) && self.dataPerson.count > 1 {
             DispatchQueue.main.async {
-                if arrayMessage[0] == arrayMessage[3] {
+                if arrayMessage[2] != "2" {
                     self.zoomView.transform   = CGAffineTransform.init(scaleX: -1.9, y: 2.2).rotated(by: (-CGFloat.pi)/2)
                     self.zoomView.contentMode = .scaleAspectFit
                 } else {
@@ -1190,14 +1224,19 @@ class QmeraVideoViewController: UIViewController {
         }
         else if state == Nexilis.STREAMING_SEMINAR_ENDED { // always call turnspeaker
             QmeraVideoViewController.isLoop = true
-            DispatchQueue.global(qos: .userInitiated).async {
-                repeat {
-                    Thread.sleep(forTimeInterval : 1)
-                    if (QmeraVideoViewController.isLoop && !API.bAudioEngineIsRunning()) {
-                        API.turnSpeakerPhone(bSPon: QmeraVideoViewController.bSpeakerPhone!)
-                    }
-                } while (QmeraVideoViewController.isLoop)
-            }
+            DispatchQueue.global().asyncAfter(deadline: .now() + 0.5, execute: {
+                API.adjustVolume(fValue: 10.0)
+                self.setSpeaker()
+                DispatchQueue.global(qos: .userInitiated).async {
+                    repeat {
+                        Thread.sleep(forTimeInterval : 1)
+                        print("Audio: \(API.bAudioEngineIsRunning())")
+                        if (QmeraVideoViewController.isLoop && !API.bAudioEngineIsRunning()) {
+                            API.turnSpeakerPhone(bSPon: QmeraVideoViewController.bSpeakerPhone!)
+                        }
+                    } while (QmeraVideoViewController.isLoop)
+                }
+            })
 //                DispatchQueue.global().asyncAfter(deadline: .now() + 3, execute: {
 //                    API.turnSpeakerPhone(bSPon: QmeraAudioViewController.bSpeakerPhone!)
 //                })
@@ -1403,6 +1442,7 @@ class QmeraVideoViewController: UIViewController {
                         _ = Nexilis.getWhiteboardDelegate()?.terminate()
                     }
                     QmeraVideoViewController.isLoop = false
+                    QmeraVideoViewController.bSpeakerPhone = false
                     DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
                         self.endAllCall()
                         self.dismiss(animated: true, completion: nil)
@@ -1456,6 +1496,7 @@ class QmeraVideoViewController: UIViewController {
                         controller!.dismiss(animated: true)
                     }
                     QmeraVideoViewController.isLoop = false
+                    QmeraVideoViewController.bSpeakerPhone = false
                     DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
                         self.endAllCall()
                         if self.isInisiator && !self.isPresent {
@@ -1674,7 +1715,7 @@ class QmeraVideoViewController: UIViewController {
                         for i in 0...1{
                             self.scrollRemoteView.addSubview(self.listRemoteViewFix[i])
                             self.listRemoteViewFix[i].frame = CGRect(x: 0, y: 170 * i, width: 120, height: 160)
-                            self.listRemoteViewFix[i].backgroundColor = .clear
+                            self.listRemoteViewFix[i].backgroundColor = .white
                             self.listRemoteViewFix[i].makeRoundedView(radius: 8.0)
                             self.scrollRemoteView.addSubview(self.containerLabelName[i])
                             self.containerLabelName[i].frame = CGRect(x: 0, y: 170 * i, width: 120, height: 30)
@@ -1702,7 +1743,7 @@ class QmeraVideoViewController: UIViewController {
                         let i = self.dataPerson.count - 1
                         self.scrollRemoteView.addSubview(self.listRemoteViewFix[i])
                         self.listRemoteViewFix[i].frame = CGRect(x: 0, y: 170 * i, width: 120, height: 160)
-                        self.listRemoteViewFix[i].backgroundColor = .clear
+                        self.listRemoteViewFix[i].backgroundColor = .white
                         self.listRemoteViewFix[i].makeRoundedView(radius: 8.0)
                         self.scrollRemoteView.addSubview(self.containerLabelName[i])
                         self.containerLabelName[i].frame = CGRect(x: 0, y: 170 * i, width: 120, height: 30)

+ 10 - 2
NexilisLite/NexilisLite/Source/View/Chat/ChatGPTBotView.swift

@@ -1580,7 +1580,11 @@ extension ChatGPTBotView: UIContextMenuInteractionDelegate {
                                         }
                                         else if FileEncryption.shared.isSecureExists(filename: imageURL.lastPathComponent) {
                                             do {
-                                                if let imageData = try FileEncryption.shared.readSecure(filename: imageURL.lastPathComponent) {
+                                                if var imageData = try FileEncryption.shared.readSecure(filename: imageURL.lastPathComponent) {
+                                                    let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: imageData)
+                                                    if dataDecrypt != nil {
+                                                        imageData = dataDecrypt!
+                                                    }
                                                     let image = UIImage(data: imageData)
                                                     UIPasteboard.general.image = image
                                                     self.view.makeToast("Image coppied to clipboard".localized(), duration: 3)
@@ -1614,7 +1618,11 @@ extension ChatGPTBotView: UIContextMenuInteractionDelegate {
                                         }
                                         else if FileEncryption.shared.isSecureExists(filename: imageURL.lastPathComponent) {
                                             do {
-                                                if let imageData = try FileEncryption.shared.readSecure(filename: imageURL.lastPathComponent) {
+                                                if var imageData = try FileEncryption.shared.readSecure(filename: imageURL.lastPathComponent) {
+                                                    let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: imageData)
+                                                    if dataDecrypt != nil {
+                                                        imageData = dataDecrypt!
+                                                    }
                                                     let image = UIImage(data: imageData)
                                                     UIPasteboard.general.image = image
                                                     self.view.makeToast("Image coppied to clipboard".localized(), duration: 3)

+ 15 - 4
NexilisLite/NexilisLite/Source/View/Chat/ChatWALikeVC.swift

@@ -473,7 +473,11 @@ public class ChatWALikeVC: UIViewController, UITableViewDataSource, UITableViewD
                         }
                     }
                     else if FileEncryption.shared.isSecureExists(filename: data.file) {
-                        if let dataFile = try? FileEncryption.shared.readSecure(filename: data.file) {
+                        if var dataFile = try? FileEncryption.shared.readSecure(filename: data.file) {
+                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: dataFile)
+                            if dataDecrypt != nil {
+                                dataFile = dataDecrypt!
+                            }
                             var sizeOfFile = Int(dataFile.count / 1000000)
                             if (sizeOfFile < 1) {
                                 sizeOfFile = Int(dataFile.count / 1000)
@@ -929,8 +933,11 @@ public class ChatWALikeVC: UIViewController, UITableViewDataSource, UITableViewD
                     self.present(previewController, animated: true)
                 } else if FileEncryption.shared.isSecureExists(filename: sender.file_id) {
                     do {
-                        if let docData = try FileEncryption.shared.readSecure(filename: sender.file_id) {
-                            
+                        if var docData = try FileEncryption.shared.readSecure(filename: sender.file_id) {
+                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: docData)
+                            if dataDecrypt != nil {
+                                docData = dataDecrypt!
+                            }
                             let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                             let tempPath = cachesDirectory.appendingPathComponent(sender.file_id)
                             try docData.write(to: tempPath)
@@ -983,7 +990,11 @@ public class ChatWALikeVC: UIViewController, UITableViewDataSource, UITableViewD
                     }
                 } else if FileEncryption.shared.isSecureExists(filename: sender.audio_id) {
                     do {
-                        if let audioData = try FileEncryption.shared.readSecure(filename: sender.audio_id) {
+                        if var audioData = try FileEncryption.shared.readSecure(filename: sender.audio_id) {
+                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: audioData)
+                            if dataDecrypt != nil {
+                                audioData = dataDecrypt!
+                            }
                             let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                             let tempPath = cachesDirectory.appendingPathComponent(sender.audio_id)
                             try audioData.write(to: tempPath)

+ 106 - 53
NexilisLite/NexilisLite/Source/View/Chat/EditorGroup.swift

@@ -1668,7 +1668,7 @@ public class EditorGroup: UIViewController, CLLocationManagerDelegate {
             let duration: CGFloat = info[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber as! CGFloat
             
             if self.constraintViewTextField.constant != keyboardHeight - 60 {
-                if self.contraintBottomMention.constant < self.contraintBottomMention.constant + keyboardHeight - 60 {
+                if self.contraintBottomMention.constant > 0 && self.contraintBottomMention.constant < self.contraintBottomMention.constant + keyboardHeight - 60 {
                     self.contraintBottomMention.constant = self.contraintBottomMention.constant + keyboardHeight - 60
                 }
                 self.constraintViewTextField.constant = keyboardHeight - 60
@@ -1825,18 +1825,32 @@ public class EditorGroup: UIViewController, CLLocationManagerDelegate {
         if message_text.contains("@") && listMentionInTextField.count > 0 {
             var diff: Int = 0
             for i in 0..<listMentionInTextField.count {
-                let nameWithMention = ("@" + listMentionInTextField[i].firstName + " " + listMentionInTextField[i].lastName).trimmingCharacters(in: .whitespaces)
-                let upperBound = Int(listMentionInTextField[i].ex_block!)! + diff - 1
-                let lowerBound = Int(listMentionInTextField[i].ex_block!)! + diff - nameWithMention.count
+                let mention = listMentionInTextField[i]
+                guard let exBlockStr = mention.ex_block, let exBlock = Int(exBlockStr) else {
+                    continue // skip if ex_block is nil or not an integer
+                }
+                let nameWithMention = ("@" + mention.firstName + " " + mention.lastName).trimmingCharacters(in: .whitespaces)
+                let pinString = "@\(mention.pin)"
+                let upperBound = exBlock + diff - 1
+                let lowerBound = upperBound - nameWithMention.count + 1
+                guard lowerBound >= 0, upperBound < message_text.count else {
+                    continue // prevent index out-of-range
+                }
                 var afterMention = ""
-                if upperBound + 1 != message_text.count && message_text.substring(from: upperBound + 1, to: upperBound + 1) != "\n" && message_text.substring(from: upperBound + 1, to: upperBound + 1) != " " && message_text.substring(from: upperBound + 1, to: upperBound + 1) != "" {
-                    afterMention = " "
+                let nextCharIndex = message_text.index(message_text.startIndex, offsetBy: upperBound + 1, limitedBy: message_text.endIndex)
+                if let index = nextCharIndex, index < message_text.endIndex {
+                    let nextChar = message_text[index]
+                    if nextChar != "\n" && nextChar != " " {
+                        afterMention = " "
+                    }
                 }
                 let startIndex = message_text.index(message_text.startIndex, offsetBy: lowerBound)
                 let endIndex = message_text.index(message_text.startIndex, offsetBy: upperBound + 1)
                 let range = startIndex..<endIndex
-                message_text = message_text.replacingOccurrences(of: nameWithMention, with: "@\(listMentionInTextField[i].pin)" + afterMention, range: range)
-                diff += "@\(listMentionInTextField[i].pin)".count - nameWithMention.count
+                if message_text[range] == nameWithMention {
+                    message_text.replaceSubrange(range, with: pinString + afterMention)
+                    diff += (pinString + afterMention).count - nameWithMention.count
+                }
             }
         }
         let message = CoreMessage_TMessageBank.sendMessage(l_pin: dataGroup["group_id"]  as? String ?? "", message_scope_id: message_scope_id, status: status, message_text: message_text, credential: credential, attachment_flag: attachment_flag, ex_blog_id: ex_blog_id, message_large_text: message_large_text, ex_format: ex_format, image_id: image_id, audio_id: audio_id, video_id: video_id, file_id: file_id, thumb_id: thumb_id, reff_id: reff_id, read_receipts: read_receipts, chat_id: dataTopic["chat_id"]  as? String ?? "", is_call_center: is_call_center, call_center_id: call_center_id, opposite_pin: opposite_pin, gif_id: gif_id, isForwarded: "\(is_forwarded)")
@@ -2105,7 +2119,6 @@ public class EditorGroup: UIViewController, CLLocationManagerDelegate {
                             return
                         }
                         do {
-                            let secureName = try FileEncryption.shared.writeSecure(filename: name)?[0]  as? String ?? ""
                             let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
                             let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
                             let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
@@ -2118,8 +2131,12 @@ public class EditorGroup: UIViewController, CLLocationManagerDelegate {
                                         UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
                                     }
                                 }
-                                else if FileEncryption.shared.isSecureExists(filename: secureName) {
-                                    if let secureData = try FileEncryption.shared.readSecure(filename: secureName) {
+                                else if FileEncryption.shared.isSecureExists(filename: self.dataMessages[index]["image_id"]  as? String ?? "") {
+                                    if var secureData = try FileEncryption.shared.readSecure(filename: self.dataMessages[index]["image_id"]  as? String ?? "") {
+                                        let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: secureData)
+                                        if dataDecrypt != nil {
+                                            secureData = dataDecrypt!
+                                        }
                                         let image = UIImage(data: secureData)
                                         let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
                                         if save {
@@ -2145,7 +2162,6 @@ public class EditorGroup: UIViewController, CLLocationManagerDelegate {
                             return
                         }
                         do {
-                            let secureName = try FileEncryption.shared.writeSecure(filename: name)?[0]  as? String ?? ""
                             let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
                             let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
                             let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
@@ -2161,8 +2177,12 @@ public class EditorGroup: UIViewController, CLLocationManagerDelegate {
                                         }
                                     }
                                 }
-                                else if FileEncryption.shared.isSecureExists(filename: secureName) {
-                                    if let secureData = try FileEncryption.shared.readSecure(filename: secureName) {
+                                else if FileEncryption.shared.isSecureExists(filename: self.dataMessages[index]["video_id"]  as? String ?? "") {
+                                    if var secureData = try FileEncryption.shared.readSecure(filename: self.dataMessages[index]["video_id"]  as? String ?? "") {
+                                        let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: secureData)
+                                        if dataDecrypt != nil {
+                                            secureData = dataDecrypt!
+                                        }
                                         let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                                         let tempPath = cachesDirectory.appendingPathComponent(name)
                                         try secureData.write(to: tempPath)
@@ -2194,11 +2214,6 @@ public class EditorGroup: UIViewController, CLLocationManagerDelegate {
                     Download().startHTTP(forKey: dataMessages[index]["file_id"]  as? String ?? "", isImage: false) { (name, progress) in
                         guard progress == 100 else {
                             return
-                        }
-                        do {
-                            try FileEncryption.shared.writeSecure(filename: name)
-                        } catch {
-                            
                         }
                         DispatchQueue.main.async { [self] in
                             let section = dataDates.firstIndex(of: dataMessages[index]["chat_date"]  as? String ?? "")
@@ -3520,7 +3535,7 @@ extension EditorGroup: UIContextMenuInteractionDelegate {
             constraintHeighteditTextView = editTextView.heightAnchor.constraint(equalToConstant: 40)
             constraintBottomeditTextView.isActive = true
             constraintHeighteditTextView.isActive = true
-            editTextView.text = oldText
+            editTextView.attributedText = oldText.richText(group_id: self.dataGroup["group_id"]  as? String ?? "")
             editTextView.becomeFirstResponder()
             
             buttonSendEdit.setImage(resizeImage(image: self.traitCollection.userInterfaceStyle == .dark ? UIImage(named: "Send-(White)", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withTintColor(.blackDarkMode) : UIImage(named: "Send-(White)", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, targetSize: CGSize(width: 30, height: 30)).withRenderingMode(.alwaysOriginal), for: .normal)
@@ -3592,7 +3607,7 @@ extension EditorGroup: UIContextMenuInteractionDelegate {
             messageText.trailingAnchor.constraint(equalTo: viewMessage.trailingAnchor, constant: -15).isActive = true
             messageText.textColor = self.traitCollection.userInterfaceStyle == .dark ? .white : .black
             messageText.font = .systemFont(ofSize: 12 + offset())
-            messageText.text = oldText
+            messageText.attributedText = oldText.richText(group_id: self.dataGroup["group_id"]  as? String ?? "")
         }
         editVC.modalTransitionStyle = .crossDissolve
         editVC.modalPresentationStyle = .overFullScreen
@@ -3962,7 +3977,11 @@ extension EditorGroup: UIContextMenuInteractionDelegate {
                                     }
                                     else if FileEncryption.shared.isSecureExists(filename: imageURL.lastPathComponent) {
                                         do {
-                                            if let imageData = try FileEncryption.shared.readSecure(filename: imageURL.lastPathComponent) {
+                                            if var imageData = try FileEncryption.shared.readSecure(filename: imageURL.lastPathComponent) {
+                                                let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: imageData)
+                                                if dataDecrypt != nil {
+                                                    imageData = dataDecrypt!
+                                                }
                                                 let image = UIImage(data: imageData)
                                                 UIPasteboard.general.image = image
                                                 self.view.makeToast("Image coppied to clipboard".localized(), duration: 3)
@@ -3993,7 +4012,11 @@ extension EditorGroup: UIContextMenuInteractionDelegate {
                                         self.view.makeToast("Image coppied to clipboard".localized(), duration: 3)
                                     } else if FileEncryption.shared.isSecureExists(filename: imageURL.lastPathComponent) {
                                         do {
-                                            if let imageData = try FileEncryption.shared.readSecure(filename: imageURL.lastPathComponent) {
+                                            if var imageData = try FileEncryption.shared.readSecure(filename: imageURL.lastPathComponent) {
+                                                let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: imageData)
+                                                if dataDecrypt != nil {
+                                                    imageData = dataDecrypt!
+                                                }
                                                 let image = UIImage(data: imageData)
                                                 UIPasteboard.general.image = image
                                                 self.view.makeToast("Image coppied to clipboard".localized(), duration: 3)
@@ -4994,7 +5017,11 @@ extension EditorGroup: UITableViewDelegate, UITableViewDataSource, AVAudioPlayer
                 } else {
                     if !FileManager.default.fileExists(atPath: audioURL.path) {
                         do {
-                            if let audioData = try FileEncryption.shared.readSecure(filename: audioChat) {
+                            if var audioData = try FileEncryption.shared.readSecure(filename: audioChat) {
+                                let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: audioData)
+                                if dataDecrypt != nil {
+                                    audioData = dataDecrypt!
+                                }
                                 let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                                 let tempPath = cachesDirectory.appendingPathComponent(audioChat)
                                 try audioData.write(to: tempPath)
@@ -5246,11 +5273,16 @@ extension EditorGroup: UITableViewDelegate, UITableViewDataSource, AVAudioPlayer
 //                                imageGif.animationRepeatCount = 4
                             } else if FileEncryption.shared.isSecureExists(filename: gifChat){
                                 do {
-                                    let data = try FileEncryption.shared.readSecure(filename: gifChat)
-                                    if let imageData = SDAnimatedImage(data: data!) {
-                                        imageGif.image = imageData
-//                                        imageGif.shouldCustomLoopCount = true
-//                                        imageGif.animationRepeatCount = 4
+                                    if var data = try FileEncryption.shared.readSecure(filename: gifChat) {
+                                        let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: data)
+                                        if dataDecrypt != nil {
+                                            data = dataDecrypt!
+                                        }
+                                        if let imageData = SDAnimatedImage(data: data) {
+                                            imageGif.image = imageData
+    //                                        imageGif.shouldCustomLoopCount = true
+    //                                        imageGif.animationRepeatCount = 4
+                                        }
                                     }
                                 }
                                 catch {
@@ -5339,7 +5371,11 @@ extension EditorGroup: UITableViewDelegate, UITableViewDataSource, AVAudioPlayer
                 }
                 else if FileEncryption.shared.isSecureExists(filename: fileChat) {
                     do {
-                        if let dataFile = try FileEncryption.shared.readSecure(filename: fileChat), textChat.isEmpty {
+                        if var dataFile = try FileEncryption.shared.readSecure(filename: fileChat), textChat.isEmpty {
+                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: dataFile)
+                            if dataDecrypt != nil {
+                                dataFile = dataDecrypt!
+                            }
                             var sizeOfFile = Int(dataFile.count / 1000000)
                             if (sizeOfFile < 1) {
                                 sizeOfFile = Int(dataFile.count / 1000)
@@ -6040,14 +6076,19 @@ extension EditorGroup: UITableViewDelegate, UITableViewDataSource, AVAudioPlayer
                     self.present(previewImageVC, animated: true, completion: nil)
                 } else if FileEncryption.shared.isSecureExists(filename: sender.image_id) {
                     do {
-                        let data = try FileEncryption.shared.readSecure(filename: sender.image_id)
-                        let image = UIImage(data: data!)
-                        let previewImageVC = PreviewAttachmentImageVideo(nibName: "PreviewAttachmentImageVideo", bundle: Bundle.resourceBundle(for: Nexilis.self))
-                        previewImageVC.image = image
-                        previewImageVC.isHiddenTextField = true
-                        previewImageVC.modalPresentationStyle = .custom
-                        previewImageVC.modalTransitionStyle  = .crossDissolve
-                        self.present(previewImageVC, animated: true, completion: nil)
+                        if var data = try FileEncryption.shared.readSecure(filename: sender.image_id) {
+                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: data)
+                            if dataDecrypt != nil {
+                                data = dataDecrypt!
+                            }
+                            let image = UIImage(data: data)
+                            let previewImageVC = PreviewAttachmentImageVideo(nibName: "PreviewAttachmentImageVideo", bundle: Bundle.resourceBundle(for: Nexilis.self))
+                            previewImageVC.image = image
+                            previewImageVC.isHiddenTextField = true
+                            previewImageVC.modalPresentationStyle = .custom
+                            previewImageVC.modalTransitionStyle  = .crossDissolve
+                            self.present(previewImageVC, animated: true, completion: nil)
+                        }
                     }
                     catch {
                         print("Error reading secure file")
@@ -6070,7 +6111,6 @@ extension EditorGroup: UITableViewDelegate, UITableViewDataSource, AVAudioPlayer
                             return
                         }
                         do {
-                            let secureName = try FileEncryption.shared.writeSecure(filename: name)?[0]  as? String ?? ""
                             let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
                             let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
                             let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
@@ -6083,8 +6123,12 @@ extension EditorGroup: UITableViewDelegate, UITableViewDataSource, AVAudioPlayer
                                         UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
                                     }
                                 }
-                                else if FileEncryption.shared.isSecureExists(filename: secureName) {
-                                    if let secureData = try FileEncryption.shared.readSecure(filename: secureName) {
+                                else if FileEncryption.shared.isSecureExists(filename: sender.image_id) {
+                                    if var secureData = try FileEncryption.shared.readSecure(filename: sender.image_id) {
+                                        let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: secureData)
+                                        if dataDecrypt != nil {
+                                            secureData = dataDecrypt!
+                                        }
                                         let image = UIImage(data: secureData)
                                         let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
                                         if save {
@@ -6115,7 +6159,11 @@ extension EditorGroup: UITableViewDelegate, UITableViewDataSource, AVAudioPlayer
                     }
                 } else if FileEncryption.shared.isSecureExists(filename: sender.gif_id) {
                     do {
-                        if let secureData = try FileEncryption.shared.readSecure(filename: sender.gif_id) {
+                        if var secureData = try FileEncryption.shared.readSecure(filename: sender.gif_id) {
+                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: secureData)
+                            if dataDecrypt != nil {
+                                secureData = dataDecrypt!
+                            }
                             APIS.openImageNexilis(image: UIImage(), data: secureData, isGIF: true)
                         }
                     } catch {
@@ -6134,7 +6182,11 @@ extension EditorGroup: UITableViewDelegate, UITableViewDataSource, AVAudioPlayer
                     self.present(playerVC, animated: true, completion: nil)
                 } else if FileEncryption.shared.isSecureExists(filename: sender.video_id) {
                     do {
-                        if let secureData = try FileEncryption.shared.readSecure(filename: sender.video_id) {
+                        if var secureData = try FileEncryption.shared.readSecure(filename: sender.video_id) {
+                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: secureData)
+                            if dataDecrypt != nil {
+                                secureData = dataDecrypt!
+                            }
                             let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                             let tempPath = cachesDirectory.appendingPathComponent(sender.video_id)
                             try secureData.write(to: tempPath)
@@ -6202,11 +6254,14 @@ extension EditorGroup: UITableViewDelegate, UITableViewDataSource, AVAudioPlayer
                                     }
                                 }
                                 else if FileEncryption.shared.isSecureExists(filename: videoURL.lastPathComponent) {
-                                    if let secureName = try FileEncryption.shared.writeSecure(filename: name)?[0] as? String {
-                                        let secureData = try FileEncryption.shared.readSecure(filename: secureName)
+                                    if var secureData = try FileEncryption.shared.readSecure(filename: videoURL.lastPathComponent) {
+                                        let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: secureData)
+                                        if dataDecrypt != nil {
+                                            secureData = dataDecrypt!
+                                        }
                                         let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                                         let tempPath = cachesDirectory.appendingPathComponent(name)
-                                        try secureData!.write(to: tempPath)
+                                        try secureData.write(to: tempPath)
                                         let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
                                         if save {
                                             PHPhotoLibrary.shared().performChanges({
@@ -6244,8 +6299,11 @@ extension EditorGroup: UITableViewDelegate, UITableViewDataSource, AVAudioPlayer
                     self.present(previewController, animated: true)
                 } else if FileEncryption.shared.isSecureExists(filename: sender.file_id) {
                     do {
-                        if let docData = try FileEncryption.shared.readSecure(filename: sender.file_id) {
-                            
+                        if var docData = try FileEncryption.shared.readSecure(filename: sender.file_id) {
+                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: docData)
+                            if dataDecrypt != nil {
+                                docData = dataDecrypt!
+                            }
                             let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                             let tempPath = cachesDirectory.appendingPathComponent(sender.file_id)
                             try docData.write(to: tempPath)
@@ -6301,11 +6359,6 @@ extension EditorGroup: UITableViewDelegate, UITableViewDataSource, AVAudioPlayer
                             guard progress == 100 else {
                                 shapeLoading.strokeEnd = CGFloat(progress / 100)
                                 return
-                            }
-                            do {
-                                try FileEncryption.shared.writeSecure(filename: name)
-                            } catch {
-                                
                             }
                             let idx = self.dataMessages.firstIndex(where: { $0["file_id"]  as? String ?? "" == sender.file_id})
                             if idx != nil {

+ 127 - 67
NexilisLite/NexilisLite/Source/View/Chat/EditorPersonal.swift

@@ -2835,7 +2835,7 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
         DispatchQueue.global().async {
             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getAddFriendApproval(lPin: lPin ?? "", isAccept: isAccept), timeout: 5 * 1000) {
                 if response.isOk() {
-                    self.deleteMessage(l_pin: User.getMyPin() ?? "", message_id: messageId ?? "", scope: MessageScope.WHISPER, type: "1", chat: "")
+                    self.deleteMessage(l_pin: self.dataPerson["f_pin"]!!, message_id: messageId ?? "", scope: MessageScope.WHISPER, type: "1", chat: "")
                     let idx = self.dataMessages.firstIndex(where: { $0["message_id"] as? String == messageId})
                     if idx != nil {
                         self.dataMessages.remove(at: idx!)
@@ -2856,8 +2856,10 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                                 } else {
                                     self.navigationController?.popViewController(animated: true)
                                 }
-                                UIApplication.shared.visibleViewController?.view.makeToast(sender.tag == 0 ? "Friend request has been accepted".localized() : "Friend request has been rejected".localized(), duration: 3)
+                            } else {
+                                self.tableChatView.reloadData()
                             }
+                            UIApplication.shared.visibleViewController?.view.makeToast(sender.tag == 0 ? "Friend request has been accepted".localized() : "Friend request has been rejected".localized(), duration: 3)
                         }
                     }
                 } else {
@@ -3289,7 +3291,6 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                                     return
                                 }
                                 do {
-                                    let secureName = try FileEncryption.shared.writeSecure(filename: valueListGroupImages[i].imageId)?[0]
                                     let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
                                     let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
                                     let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
@@ -3303,7 +3304,11 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                                             }
                                         }
                                         else if FileEncryption.shared.isSecureExists(filename: valueListGroupImages[i].imageId) {
-                                            if let secureData = try FileEncryption.shared.readSecure(filename: valueListGroupImages[i].imageId) {
+                                            if var secureData = try FileEncryption.shared.readSecure(filename: valueListGroupImages[i].imageId) {
+                                                let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: secureData)
+                                                if dataDecrypt != nil {
+                                                    secureData = dataDecrypt!
+                                                }
                                                 let image = UIImage(data: secureData)
                                                 let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
                                                 if save {
@@ -3331,7 +3336,6 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                                 return
                             }
                             do {
-                                let secureName = try FileEncryption.shared.writeSecure(filename: self.dataMessages[index]["image_id"] as? String)?[0]  as? String ?? ""
                                 let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
                                 let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
                                 let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
@@ -3344,8 +3348,12 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                                             UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
                                         }
                                     }
-                                    else if FileEncryption.shared.isSecureExists(filename: secureName) {
-                                        if let secureData = try FileEncryption.shared.readSecure(filename: secureName) {
+                                    else if FileEncryption.shared.isSecureExists(filename: self.dataMessages[index]["image_id"]  as? String ?? "") {
+                                        if var secureData = try FileEncryption.shared.readSecure(filename: self.dataMessages[index]["image_id"]  as? String ?? "") {
+                                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: secureData)
+                                            if dataDecrypt != nil {
+                                                secureData = dataDecrypt!
+                                            }
                                             let image = UIImage(data: secureData)
                                             let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
                                             if save {
@@ -3372,7 +3380,6 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                             return
                         }
                         do {
-                            let secureName = try FileEncryption.shared.writeSecure(filename: self.dataMessages[index]["video_id"] as? String)?[0]  as? String ?? ""
                             let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
                             let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
                             let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
@@ -3388,8 +3395,12 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                                         }
                                     }
                                 }
-                                else if FileEncryption.shared.isSecureExists(filename: secureName) {
-                                    if let secureData = try FileEncryption.shared.readSecure(filename: secureName) {
+                                else if FileEncryption.shared.isSecureExists(filename: self.dataMessages[index]["video_id"]  as? String ?? "") {
+                                    if var secureData = try FileEncryption.shared.readSecure(filename: self.dataMessages[index]["video_id"]  as? String ?? "") {
+                                        let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: secureData)
+                                        if dataDecrypt != nil {
+                                            secureData = dataDecrypt!
+                                        }
                                         let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                                         let tempPath = cachesDirectory.appendingPathComponent(name)
                                         try secureData.write(to: tempPath)
@@ -3420,11 +3431,6 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                     Download().startHTTP(forKey: dataMessages[index]["file_id"]  as? String ?? "", isImage: false) { (name, progress) in
                         guard progress == 100 else {
                             return
-                        }
-                        do {
-                            try FileEncryption.shared.writeSecure(filename: name)
-                        } catch {
-                            
                         }
                         DispatchQueue.main.async { [self] in
                             let section = dataDates.firstIndex(of: dataMessages[index]["chat_date"]  as? String ?? "")
@@ -5145,7 +5151,11 @@ extension EditorPersonal: UIContextMenuInteractionDelegate {
                                         self.view.makeToast("Image coppied to clipboard".localized(), duration: 3)
                                     } else if FileEncryption.shared.isSecureExists(filename: imageURL.lastPathComponent) {
                                         do {
-                                            if let imageData = try FileEncryption.shared.readSecure(filename: imageURL.lastPathComponent) {
+                                            if var imageData = try FileEncryption.shared.readSecure(filename: imageURL.lastPathComponent) {
+                                                let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: imageData)
+                                                if dataDecrypt != nil {
+                                                    imageData = dataDecrypt!
+                                                }
                                                 let image = UIImage(data: imageData)
                                                 UIPasteboard.general.image = image
                                                 self.view.makeToast("Image coppied to clipboard".localized(), duration: 3)
@@ -5176,7 +5186,11 @@ extension EditorPersonal: UIContextMenuInteractionDelegate {
                                         self.view.makeToast("Image coppied to clipboard".localized(), duration: 3)
                                     } else if FileEncryption.shared.isSecureExists(filename: imageURL.lastPathComponent) {
                                         do {
-                                            if let imageData = try FileEncryption.shared.readSecure(filename: imageURL.lastPathComponent) {
+                                            if var imageData = try FileEncryption.shared.readSecure(filename: imageURL.lastPathComponent) {
+                                                let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: imageData)
+                                                if dataDecrypt != nil {
+                                                    imageData = dataDecrypt!
+                                                }
                                                 let image = UIImage(data: imageData)
                                                 UIPasteboard.general.image = image
                                                 self.view.makeToast("Image coppied to clipboard".localized(), duration: 3)
@@ -6484,7 +6498,11 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource, AVAudioPla
                 } else {
                     if !FileManager.default.fileExists(atPath: audioURL.path) {
                         do {
-                            if let audioData = try FileEncryption.shared.readSecure(filename: audioChat) {
+                            if var audioData = try FileEncryption.shared.readSecure(filename: audioChat) {
+                                let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: audioData)
+                                if dataDecrypt != nil {
+                                    audioData = dataDecrypt!
+                                }
                                 let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                                 let tempPath = cachesDirectory.appendingPathComponent(audioChat)
                                 try audioData.write(to: tempPath)
@@ -6672,18 +6690,44 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource, AVAudioPla
                 let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
                 if let dirPath = paths.first {
                     let thumbURL = URL(fileURLWithPath: dirPath).appendingPathComponent(thumbChat)
-                    DispatchQueue.main.async {
-                        let image : UIImage? =  {
-                            if let img = Nexilis.imageCache.object(forKey: thumbChat as NSString) {
-                                return img
-                            }
-                            else if let img = UIImage(contentsOfFile: thumbURL.path)?.resize(target: CGSize(width: 500, height: 500)) {
-                                    Nexilis.imageCache.setObject(img, forKey: thumbChat as NSString)
+                    if FileManager.default.fileExists(atPath: thumbURL.path) {
+                        DispatchQueue.main.async {
+                            let image : UIImage? =  {
+                                if let img = Nexilis.imageCache.object(forKey: thumbChat as NSString) {
                                     return img
+                                }
+                                else if let img = UIImage(contentsOfFile: thumbURL.path)?.resize(target: CGSize(width: 500, height: 500)) {
+                                        Nexilis.imageCache.setObject(img, forKey: thumbChat as NSString)
+                                        return img
+                                }
+                                return nil
+                            }()
+                            imageThumb.image = image
+                        }
+                    } else if FileEncryption.shared.isSecureExists(filename: thumbChat) {
+                        do {
+                            if var data = try FileEncryption.shared.readSecure(filename: thumbChat) {
+                                let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: data)
+                                if dataDecrypt != nil {
+                                    data = dataDecrypt!
+                                }
+                                DispatchQueue.main.async {
+                                    let image : UIImage? =  {
+                                        if let img = Nexilis.imageCache.object(forKey: thumbChat as NSString) {
+                                            return img
+                                        }
+                                        else if let img = UIImage(data: data)?.resize(target: CGSize(width: 500, height: 500)) {
+                                            Nexilis.imageCache.setObject(img, forKey: thumbChat as NSString)
+                                            return img
+                                        }
+                                        return nil
+                                    }()
+                                    imageThumb.image = image
+                                }
                             }
-                            return nil
-                        }()
-                        imageThumb.image = image
+                        } catch {
+                            
+                        }
                     }
 //                    let image = UIGraphicsRenderer.renderImageAt(url: thumbURL as NSURL, size: CGSize(width: 250, height: 250))
                     let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent(imageChat)
@@ -6736,11 +6780,16 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource, AVAudioPla
 //                                imageGif.animationRepeatCount = 4
                             } else if FileEncryption.shared.isSecureExists(filename: gifChat){
                                 do {
-                                    let data = try FileEncryption.shared.readSecure(filename: gifChat)
-                                    if let imageData = SDAnimatedImage(data: data!) {
-                                        imageGif.image = imageData
-//                                        imageGif.shouldCustomLoopCount = true
-//                                        imageGif.animationRepeatCount = 4
+                                    if var data = try FileEncryption.shared.readSecure(filename: gifChat) {
+                                        let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: data)
+                                        if dataDecrypt != nil {
+                                            data = dataDecrypt!
+                                        }
+                                        if let imageData = SDAnimatedImage(data: data) {
+                                            imageGif.image = imageData
+    //                                        imageGif.shouldCustomLoopCount = true
+    //                                        imageGif.animationRepeatCount = 4
+                                        }
                                     }
                                 }
                                 catch {
@@ -6828,7 +6877,11 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource, AVAudioPla
                     }
                 }
                 else if FileEncryption.shared.isSecureExists(filename: fileChat) {
-                    if let dataFile = try? FileEncryption.shared.readSecure(filename: fileChat), textChat.isEmpty {
+                    if var dataFile = try? FileEncryption.shared.readSecure(filename: fileChat), textChat.isEmpty {
+                        let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: dataFile)
+                        if dataDecrypt != nil {
+                            dataFile = dataDecrypt!
+                        }
                         var sizeOfFile = Int(dataFile.count / 1000000)
                         if (sizeOfFile < 1) {
                             sizeOfFile = Int(dataFile.count / 1000)
@@ -7585,14 +7638,19 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource, AVAudioPla
                     self.present(previewImageVC, animated: true, completion: nil)
                 } else if FileEncryption.shared.isSecureExists(filename: sender.image_id) {
                     do {
-                        let data = try FileEncryption.shared.readSecure(filename: sender.image_id)
-                        let image = UIImage(data: data!)
-                        let previewImageVC = PreviewAttachmentImageVideo(nibName: "PreviewAttachmentImageVideo", bundle: Bundle.resourceBundle(for: Nexilis.self))
-                        previewImageVC.image = image
-                        previewImageVC.isHiddenTextField = true
-                        previewImageVC.modalPresentationStyle = .custom
-                        previewImageVC.modalTransitionStyle  = .crossDissolve
-                        self.present(previewImageVC, animated: true, completion: nil)
+                        if var data = try FileEncryption.shared.readSecure(filename: sender.image_id) {
+                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: data)
+                            if dataDecrypt != nil {
+                                data = dataDecrypt!
+                            }
+                            let image = UIImage(data: data)
+                            let previewImageVC = PreviewAttachmentImageVideo(nibName: "PreviewAttachmentImageVideo", bundle: Bundle.resourceBundle(for: Nexilis.self))
+                            previewImageVC.image = image
+                            previewImageVC.isHiddenTextField = true
+                            previewImageVC.modalPresentationStyle = .custom
+                            previewImageVC.modalTransitionStyle  = .crossDissolve
+                            self.present(previewImageVC, animated: true, completion: nil)
+                        }
                     }
                     catch {
                         print("Error reading secure file")
@@ -7615,7 +7673,6 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource, AVAudioPla
                             return
                         }
                         do {
-                            let secureName = try FileEncryption.shared.writeSecure(filename: name)?[0]  as? String ?? ""
                             let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
                             let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
                             let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
@@ -7628,8 +7685,12 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource, AVAudioPla
                                         UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
                                     }
                                 }
-                                else if FileEncryption.shared.isSecureExists(filename: secureName) {
-                                    if let secureData = try FileEncryption.shared.readSecure(filename: secureName) {
+                                else if FileEncryption.shared.isSecureExists(filename: sender.image_id) {
+                                    if var secureData = try FileEncryption.shared.readSecure(filename: sender.image_id) {
+                                        let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: secureData)
+                                        if dataDecrypt != nil {
+                                            secureData = dataDecrypt!
+                                        }
                                         let image = UIImage(data: secureData)
                                         let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
                                         if save {
@@ -7660,7 +7721,11 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource, AVAudioPla
                     }
                 } else if FileEncryption.shared.isSecureExists(filename: sender.gif_id) {
                     do {
-                        if let secureData = try FileEncryption.shared.readSecure(filename: sender.gif_id) {
+                        if var secureData = try FileEncryption.shared.readSecure(filename: sender.gif_id) {
+                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: secureData)
+                            if dataDecrypt != nil {
+                                secureData = dataDecrypt!
+                            }
                             APIS.openImageNexilis(image: UIImage(), data: secureData, isGIF: true)
                         }
                     } catch {
@@ -7679,7 +7744,11 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource, AVAudioPla
                     self.present(playerVC, animated: true, completion: nil)
                 } else if FileEncryption.shared.isSecureExists(filename: sender.video_id) {
                     do {
-                        if let secureData = try FileEncryption.shared.readSecure(filename: sender.video_id) {
+                        if var secureData = try FileEncryption.shared.readSecure(filename: sender.video_id) {
+                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: secureData)
+                            if dataDecrypt != nil {
+                                secureData = dataDecrypt!
+                            }
                             let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                             let tempPath = cachesDirectory.appendingPathComponent(sender.video_id)
                             try secureData.write(to: tempPath)
@@ -7735,27 +7804,20 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource, AVAudioPla
                                 return
                             }
                             do {
-                                if let secureName = try FileEncryption.shared.writeSecure(filename: name)?[0] as? String {
-                                    let secureData = try FileEncryption.shared.readSecure(filename: secureName)
+                                if var secureData = try FileEncryption.shared.readSecure(filename: sender.video_id) {
+                                    let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: secureData)
+                                    if dataDecrypt != nil {
+                                        secureData = dataDecrypt!
+                                    }
                                     let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                                     let tempPath = cachesDirectory.appendingPathComponent(name)
-                                    try secureData!.write(to: tempPath)
+                                    try secureData.write(to: tempPath)
                                     let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
                                     if save {
                                         PHPhotoLibrary.shared().performChanges({
                                             PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: tempPath)
                                         }) { saved, error in
                                             
-                                        }
-                                    }
-                                } else {
-                                    let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
-                                    if save {
-                                        let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(sender.video_id)
-                                        PHPhotoLibrary.shared().performChanges({
-                                            PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: videoURL)
-                                        }) { saved, error in
-                                            
                                         }
                                     }
                                 }
@@ -7785,8 +7847,11 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource, AVAudioPla
                     self.present(previewController, animated: true)
                 } else if FileEncryption.shared.isSecureExists(filename: sender.file_id) {
                     do {
-                        if let docData = try FileEncryption.shared.readSecure(filename: sender.file_id) {
-                            
+                        if var docData = try FileEncryption.shared.readSecure(filename: sender.file_id) {
+                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: docData)
+                            if dataDecrypt != nil {
+                                docData = dataDecrypt!
+                            }
                             let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                             let tempPath = cachesDirectory.appendingPathComponent(sender.file_id)
                             try docData.write(to: tempPath)
@@ -7842,11 +7907,6 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource, AVAudioPla
                             guard progress == 100 else {
                                 shapeLoading.strokeEnd = CGFloat(progress / 100)
                                 return
-                            }
-                            do {
-                                try FileEncryption.shared.writeSecure(filename: name)
-                            } catch {
-                                
                             }
                             let idx = self.dataMessages.firstIndex(where: { $0["file_id"]  as? String ?? "" == sender.file_id})
                             if idx != nil {

+ 50 - 35
NexilisLite/NexilisLite/Source/View/Chat/EditorStarMessages.swift

@@ -576,7 +576,11 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
                     }
                 }
                 else if FileEncryption.shared.isSecureExists(filename: fileChat) {
-                    if let dataFile = try? FileEncryption.shared.readSecure(filename: fileChat) {
+                    if var dataFile = try? FileEncryption.shared.readSecure(filename: fileChat) {
+                        let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: dataFile)
+                        if dataDecrypt != nil {
+                            dataFile = dataDecrypt!
+                        }
                         var sizeOfFile = Int(dataFile.count / 1000000)
                         if (sizeOfFile < 1) {
                             sizeOfFile = Int(dataFile.count / 1000)
@@ -981,14 +985,19 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
                     self.present(previewImageVC, animated: true, completion: nil)
                 } else if FileEncryption.shared.isSecureExists(filename: sender.image_id) {
                     do {
-                        let data = try FileEncryption.shared.readSecure(filename: sender.image_id)
-                        let image = UIImage(data: data!)
-                        let previewImageVC = PreviewAttachmentImageVideo(nibName: "PreviewAttachmentImageVideo", bundle: Bundle.resourceBundle(for: Nexilis.self))
-                        previewImageVC.image = image
-                        previewImageVC.isHiddenTextField = true
-                        previewImageVC.modalPresentationStyle = .custom
-                        previewImageVC.modalTransitionStyle  = .crossDissolve
-                        self.present(previewImageVC, animated: true, completion: nil)
+                        if var data = try FileEncryption.shared.readSecure(filename: sender.image_id) {
+                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: data)
+                            if dataDecrypt != nil {
+                                data = dataDecrypt!
+                            }
+                            let image = UIImage(data: data)
+                            let previewImageVC = PreviewAttachmentImageVideo(nibName: "PreviewAttachmentImageVideo", bundle: Bundle.resourceBundle(for: Nexilis.self))
+                            previewImageVC.image = image
+                            previewImageVC.isHiddenTextField = true
+                            previewImageVC.modalPresentationStyle = .custom
+                            previewImageVC.modalTransitionStyle  = .crossDissolve
+                            self.present(previewImageVC, animated: true, completion: nil)
+                        }
                     }
                     catch {
                         print("Error reading secure file")
@@ -1012,7 +1021,6 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
                         }
                         
                         do {
-                            let secureName = try FileEncryption.shared.writeSecure(filename: name)?[0] as! String
                             let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
                             let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
                             let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
@@ -1025,8 +1033,12 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
                                         UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
                                     }
                                 }
-                                else if FileEncryption.shared.isSecureExists(filename: secureName) {
-                                    if let secureData = try FileEncryption.shared.readSecure(filename: secureName) {
+                                else if FileEncryption.shared.isSecureExists(filename: sender.image_id) {
+                                    if var secureData = try FileEncryption.shared.readSecure(filename: sender.image_id) {
+                                        let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: secureData)
+                                        if dataDecrypt != nil {
+                                            secureData = dataDecrypt!
+                                        }
                                         let image = UIImage(data: secureData)
                                         let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
                                         if save {
@@ -1057,7 +1069,11 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
                     self.present(playerVC, animated: true, completion: nil)
                 } else if FileEncryption.shared.isSecureExists(filename: sender.video_id) {
                     do {
-                        if let secureData = try FileEncryption.shared.readSecure(filename: sender.video_id) {
+                        if var secureData = try FileEncryption.shared.readSecure(filename: sender.video_id) {
+                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: secureData)
+                            if dataDecrypt != nil {
+                                secureData = dataDecrypt!
+                            }
                             let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                             let tempPath = cachesDirectory.appendingPathComponent(sender.video_id)
                             try secureData.write(to: tempPath)
@@ -1113,27 +1129,20 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
                                 return
                             }
                             do {
-                                if let secureName = try FileEncryption.shared.writeSecure(filename: name)?[0] as? String {
-                                    let secureData = try FileEncryption.shared.readSecure(filename: secureName)
+                                if var secureData = try FileEncryption.shared.readSecure(filename: sender.video_id) {
+                                    let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: secureData)
+                                    if dataDecrypt != nil {
+                                        secureData = dataDecrypt!
+                                    }
                                     let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                                     let tempPath = cachesDirectory.appendingPathComponent(name)
-                                    try secureData!.write(to: tempPath)
+                                    try secureData.write(to: tempPath)
                                     let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
                                     if save {
                                         PHPhotoLibrary.shared().performChanges({
                                             PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: tempPath)
                                         }) { saved, error in
                                             
-                                        }
-                                    }
-                                } else {
-                                    let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
-                                    if save {
-                                        let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(sender.video_id)
-                                        PHPhotoLibrary.shared().performChanges({
-                                            PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: videoURL)
-                                        }) { saved, error in
-                                            
                                         }
                                     }
                                 }
@@ -1163,8 +1172,11 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
                     self.present(previewController, animated: true)
                 } else if FileEncryption.shared.isSecureExists(filename: sender.file_id) {
                     do {
-                        if let docData = try FileEncryption.shared.readSecure(filename: sender.file_id) {
-                            
+                        if var docData = try FileEncryption.shared.readSecure(filename: sender.file_id) {
+                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: docData)
+                            if dataDecrypt != nil {
+                                docData = dataDecrypt!
+                            }
                             let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                             let tempPath = cachesDirectory.appendingPathComponent(sender.file_id)
                             try docData.write(to: tempPath)
@@ -1220,11 +1232,6 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
                             guard progress == 100 else {
                                 shapeLoading.strokeEnd = CGFloat(progress / 100)
                                 return
-                            }
-                            do {
-                                try FileEncryption.shared.writeSecure(filename: name)
-                            } catch {
-                                
                             }
                             let idx = self.dataMessages.firstIndex(where: { $0["file_id"] as! String == sender.file_id})
                             if idx != nil {
@@ -1415,7 +1422,11 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
                             self.view.makeToast("Image coppied to clipboard".localized(), duration: 3)
                         } else if FileEncryption.shared.isSecureExists(filename: imageURL.lastPathComponent) {
                             do {
-                                if let imageData = try FileEncryption.shared.readSecure(filename: imageURL.lastPathComponent) {
+                                if var imageData = try FileEncryption.shared.readSecure(filename: imageURL.lastPathComponent) {
+                                    let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: imageData)
+                                    if dataDecrypt != nil {
+                                        imageData = dataDecrypt!
+                                    }
                                     let image    = UIImage(data: imageData)
                                     UIPasteboard.general.image = image
                                     self.view.makeToast("Image coppied to clipboard".localized(), duration: 3)
@@ -1472,7 +1483,11 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
                                     self.view.makeToast("Image coppied to clipboard".localized(), duration: 3)
                                 } else if FileEncryption.shared.isSecureExists(filename: imageURL.lastPathComponent) {
                                     do {
-                                        if let imageData = try FileEncryption.shared.readSecure(filename: imageURL.lastPathComponent) {
+                                        if var imageData = try FileEncryption.shared.readSecure(filename: imageURL.lastPathComponent) {
+                                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: imageData)
+                                            if dataDecrypt != nil {
+                                                imageData = dataDecrypt!
+                                            }
                                             let image    = UIImage(data: imageData)
                                             UIPasteboard.general.image = image
                                             self.view.makeToast("Image coppied to clipboard".localized(), duration: 3)

+ 16 - 12
NexilisLite/NexilisLite/Source/View/Chat/ListGroupImages.swift

@@ -149,7 +149,11 @@ class ListGroupImages: UIViewController, UITableViewDataSource, UITableViewDeleg
                         else if let img = UIImage(contentsOfFile: imageURL.path)?.resize(target: CGSize(width: 1000, height: 1000)) {
                             Nexilis.imageCache.setObject(img, forKey: imageId as NSString)
                             return img
-                        } else if let imgData = try FileEncryption.shared.readSecure(filename: imageId) {
+                        } else if var imgData = try FileEncryption.shared.readSecure(filename: imageId) {
+                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: imgData)
+                            if dataDecrypt != nil {
+                                imgData = dataDecrypt!
+                            }
                             let img = UIImage(data: imgData)?.resize(target: CGSize(width: 1000, height: 1000))
                             Nexilis.imageCache.setObject(img!, forKey: imageId as NSString)
                             return img
@@ -356,8 +360,6 @@ class ListGroupImages: UIViewController, UITableViewDataSource, UITableViewDeleg
                         }
                         
                         do {
-                            
-                            let secureName = try FileEncryption.shared.writeSecure(filename: name)?[0] as! String
                             let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent(self.listGroupingImages[indexPath.row].imageId)
                             if FileManager.default.fileExists(atPath: imageURL.path){
                                 let image    = UIImage(contentsOfFile: imageURL.path)
@@ -366,8 +368,12 @@ class ListGroupImages: UIViewController, UITableViewDataSource, UITableViewDeleg
                                     UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
                                 }
                             }
-                            else if FileEncryption.shared.isSecureExists(filename: secureName){
-                                if let imageData = try FileEncryption.shared.readSecure(filename: secureName) {
+                            else if FileEncryption.shared.isSecureExists(filename: self.listGroupingImages[indexPath.row].imageId){
+                                if var imageData = try FileEncryption.shared.readSecure(filename: self.listGroupingImages[indexPath.row].imageId) {
+                                    let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: imageData)
+                                    if dataDecrypt != nil {
+                                        imageData = dataDecrypt!
+                                    }
                                     let image    = UIImage(data: imageData)
                                     let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
                                     if save {
@@ -658,7 +664,11 @@ class ListGroupImages: UIViewController, UITableViewDataSource, UITableViewDeleg
                     imagePath = UIImage(contentsOfFile: imageURL.path)
                 }
                 else if FileEncryption.shared.isSecureExists(filename: image) {
-                    if let imageData = try FileEncryption.shared.readSecure(filename: image) {
+                    if var imageData = try FileEncryption.shared.readSecure(filename: image) {
+                        let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: imageData)
+                        if dataDecrypt != nil {
+                            imageData = dataDecrypt!
+                        }
                         imagePath = UIImage(data: imageData)
                     }
                 }
@@ -667,12 +677,6 @@ class ListGroupImages: UIViewController, UITableViewDataSource, UITableViewDeleg
                         guard progress == 100 else {
                             return
                         }
-                        do {
-                            try FileEncryption.shared.writeSecure(filename: image)
-                        }
-                        catch {
-                            
-                        }
                     }
                     imagePath = UIImage(named: "Send-Image", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)
                 }

+ 5 - 1
NexilisLite/NexilisLite/Source/View/Chat/MessageInfo.swift

@@ -899,7 +899,11 @@ class MessageInfo: UIViewController, UITableViewDelegate, UITableViewDataSource,
                         }
                     }
                     else if FileEncryption.shared.isSecureExists(filename: fileChat) {
-                        if let dataFile = try? FileEncryption.shared.readSecure(filename: fileChat) {
+                        if var dataFile = try? FileEncryption.shared.readSecure(filename: fileChat) {
+                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: dataFile)
+                            if dataDecrypt != nil {
+                                dataFile = dataDecrypt!
+                            }
                             var sizeOfFile = Int(dataFile.count / 1000000)
                             if (sizeOfFile < 1) {
                                 sizeOfFile = Int(dataFile.count / 1000)

+ 23 - 11
NexilisLite/NexilisLite/Source/View/Chat/SecureFolderView.swift

@@ -185,14 +185,19 @@ class SecureFolderViewController: UIViewController, UISearchBarDelegate, UIColle
         if fileItem.imageId != "" {
             print("this image")
             do {
-                let data = try FileEncryption.shared.readSecure(filename: fileItem.filename)
-                let image = UIImage(data: data!)
-                let previewImageVC = PreviewAttachmentImageVideo(nibName: "PreviewAttachmentImageVideo", bundle: Bundle.resourceBundle(for: Nexilis.self))
-                previewImageVC.image = image
-                previewImageVC.isHiddenTextField = true
-                previewImageVC.modalPresentationStyle = .custom
-                previewImageVC.modalTransitionStyle  = .crossDissolve
-                self.present(previewImageVC, animated: true, completion: nil)
+                if var data = try FileEncryption.shared.readSecure(filename: fileItem.filename) {
+                    let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: data)
+                    if dataDecrypt != nil {
+                        data = dataDecrypt!
+                    }
+                    let image = UIImage(data: data)
+                    let previewImageVC = PreviewAttachmentImageVideo(nibName: "PreviewAttachmentImageVideo", bundle: Bundle.resourceBundle(for: Nexilis.self))
+                    previewImageVC.image = image
+                    previewImageVC.isHiddenTextField = true
+                    previewImageVC.modalPresentationStyle = .custom
+                    previewImageVC.modalTransitionStyle  = .crossDissolve
+                    self.present(previewImageVC, animated: true, completion: nil)
+                }
             }
             catch {
                 print("Error reading secure file")
@@ -201,7 +206,11 @@ class SecureFolderViewController: UIViewController, UISearchBarDelegate, UIColle
         else if fileItem.videoId != "" {
             print("this video")
             do {
-                if let secureData = try FileEncryption.shared.readSecure(filename: fileItem.filename) {
+                if var secureData = try FileEncryption.shared.readSecure(filename: fileItem.filename) {
+                    let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: secureData)
+                    if dataDecrypt != nil {
+                        secureData = dataDecrypt!
+                    }
                     let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                     let tempPath = cachesDirectory.appendingPathComponent(fileItem.filename)
                     try secureData.write(to: tempPath)
@@ -218,8 +227,11 @@ class SecureFolderViewController: UIViewController, UISearchBarDelegate, UIColle
         else if fileItem.fileId != "" {
             print("this file")
             do {
-                if let docData = try FileEncryption.shared.readSecure(filename: fileItem.filename) {
-                    
+                if var docData = try FileEncryption.shared.readSecure(filename: fileItem.filename) {
+                    let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: docData)
+                    if dataDecrypt != nil {
+                        docData = dataDecrypt!
+                    }
                     let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                     let tempPath = cachesDirectory.appendingPathComponent(fileItem.filename)
                     try docData.write(to: tempPath)

+ 5 - 0
NexilisLite/NexilisLite/Source/View/Control/BroadcastViewController.swift

@@ -412,6 +412,11 @@ class BroadcastViewController: UITableViewController, UITextFieldDelegate, UITex
             Network().uploadHTTP(name: String(thumbId)) { (result1, progress) in
                 if result1 {
                     if progress == 100 {
+                        do {
+                            try FileEncryption.shared.writeSecure(filename: String(self.thumbId))
+                        } catch {
+                            
+                        }
                         Network().uploadHTTP(name: String(self.fileId)) { (result2, progress) in
                             if result2 {
                                 if progress == 100 {

+ 5 - 0
NexilisLite/NexilisLite/Source/View/Control/GroupDetailViewController.swift

@@ -1066,6 +1066,11 @@ extension GroupDetailViewController: ImageVideoPickerDelegate {
                     Network().uploadHTTP(name: fileDir.lastPathComponent) { result, progress in
                         guard result, progress == 100 else {
                             return
+                        }
+                        do {
+                            try FileEncryption.shared.writeSecure(filename: fileDir.lastPathComponent)
+                        } catch {
+                            
                         }
                         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

+ 5 - 1
NexilisLite/NexilisLite/Source/View/Control/NotificationSound.swift

@@ -157,7 +157,11 @@ public class NotificationSound: UIViewController, UITableViewDelegate, UITableVi
                         }
                     } else if FileEncryption.shared.isSecureExists(filename: nameSound) {
                         do {
-                            if let audioData = try FileEncryption.shared.readSecure(filename: nameSound) {
+                            if var audioData = try FileEncryption.shared.readSecure(filename: nameSound) {
+                                let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: audioData)
+                                if dataDecrypt != nil {
+                                    audioData = dataDecrypt!
+                                }
                                 let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                                 let tempPath = cachesDirectory.appendingPathComponent(nameSound)
                                 try audioData.write(to: tempPath)

+ 18 - 8
NexilisLite/NexilisLite/Source/View/Control/ProfileViewController.swift

@@ -679,14 +679,19 @@ public class ProfileViewController: UITableViewController, UITextFieldDelegate {
                     self.present(previewImageVC, animated: true, completion: nil)
                 } else if FileEncryption.shared.isSecureExists(filename: self.user!.thumb) {
                     do {
-                        let data = try FileEncryption.shared.readSecure(filename: self.user!.thumb)
-                        let image = UIImage(data: data!)
-                        let previewImageVC = PreviewAttachmentImageVideo(nibName: "PreviewAttachmentImageVideo", bundle: Bundle.resourceBundle(for: Nexilis.self))
-                        previewImageVC.image = image
-                        previewImageVC.isHiddenTextField = true
-                        previewImageVC.modalPresentationStyle = .custom
-                        previewImageVC.modalTransitionStyle  = .crossDissolve
-                        self.present(previewImageVC, animated: true, completion: nil)
+                        if var data = try FileEncryption.shared.readSecure(filename: self.user!.thumb) {
+                            let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: data)
+                            if dataDecrypt != nil {
+                                data = dataDecrypt!
+                            }
+                            let image = UIImage(data: data)
+                            let previewImageVC = PreviewAttachmentImageVideo(nibName: "PreviewAttachmentImageVideo", bundle: Bundle.resourceBundle(for: Nexilis.self))
+                            previewImageVC.image = image
+                            previewImageVC.isHiddenTextField = true
+                            previewImageVC.modalPresentationStyle = .custom
+                            previewImageVC.modalTransitionStyle  = .crossDissolve
+                            self.present(previewImageVC, animated: true, completion: nil)
+                        }
                     }
                     catch {
                         print("Error reading secure file")
@@ -891,6 +896,11 @@ extension ProfileViewController: ImageVideoPickerDelegate {
                         }
                         guard progress == 100 else {
                             return
+                        }
+                        do {
+                            try FileEncryption.shared.writeSecure(filename: fileDir.lastPathComponent)
+                        } catch {
+                            
                         }
                         if let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getChangePersonImage(thumb_id: fileDir.lastPathComponent)), response.isOk() {
                             Database.shared.database?.inTransaction({ fmdb, rollback in

+ 1 - 1
NexilisLite/NexilisLite/Source/View/Control/SettingTableViewController.swift

@@ -598,7 +598,7 @@ public class SettingTableViewController: UITableViewController, UIGestureRecogni
                             if Utils.getForceAnonymous() {
                                 self.deleteAllRecordDatabase()
                                 SecureUserDefaults.shared.removeValue(forKey: "device_id")
-                                FileEncryption.shared.wipeFolder()
+//                                FileEncryption.shared.wipeFolder()
                                 Nexilis.destroyAll()
                                 _ = Nexilis.write(message: CoreMessage_TMessageBank.getPostRegistration(p_pin: id))
                             }

+ 5 - 1
NexilisLite/NexilisLite/Source/View/Streaming/QmeraCreateStreamingViewController.swift

@@ -241,7 +241,11 @@ public class QmeraCreateStreamingViewController: UITableViewController {
             }
             var data: [String: Any] = [:]
             if !isJoin && !self.data.isEmpty {
-                data = self.data
+                let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
+                imageView.tintColor = .white
+                let banner = FloatingNotificationBanner(title: "The streaming session has ended".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()
+                return
             } else if self.data.isEmpty {
                 guard let streamingTitle = titleView.text else {
                     return

+ 12 - 0
NexilisLite/NexilisLite/Source/View/Streaming/QmeraStreamingViewController.swift

@@ -644,6 +644,18 @@ extension QmeraStreamingViewController: LiveStreamingDelegate {
                     self.imageView.transform = CGAffineTransform.init(scaleX: 1.9, y: 2.2).rotated(by: camera == 1 ? (CGFloat.pi * 5)/2 : (CGFloat.pi)/2)
                 }
             }
+            DispatchQueue.global().asyncAfter(deadline: .now() + 1, execute: {
+                API.adjustVolume(fValue: 10.0)
+                var bAudioEngineIsAvtive: Bool! = false
+                repeat {
+                    API.turnSpeakerPhone(bSPon: true)
+                    Thread.sleep(forTimeInterval: 1)
+                    bAudioEngineIsAvtive = API.bAudioEngineIsRunning()
+                    if (bAudioEngineIsAvtive) {
+                        break
+                    }
+                } while (!bAudioEngineIsAvtive)
+            })
             sendJoin()
         } else if state == Nexilis.AUDIO_CALL_RINGING {
             let m = message.split(separator: ",")