浏览代码

File encryption secure folder

kevin 8 月之前
父节点
当前提交
fb51c47c83

+ 137 - 6
NexilisLite/NexilisLite.xcodeproj/project.pbxproj

@@ -7,6 +7,10 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		1241AEBC2D017E8C0088175A /* MasterKeyUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1241AEBB2D017E8C0088175A /* MasterKeyUtil.swift */; };
+		1241AEBD2D017E8C0088175A /* FileEncryption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1241AEBA2D017E8C0088175A /* FileEncryption.swift */; };
+		3AA890FECDE6363EFE1216A2 /* Pods_NexilisLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05DE800165B7FA8135DD726B /* Pods_NexilisLite.framework */; };
+		6727D8C17B895F1A290AA89B /* Pods_NexilisLite_NexilisLiteTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F397F48A7642BC0DB5A8D144 /* Pods_NexilisLite_NexilisLiteTests.framework */; };
 		CD1E6E6D2A0B7C3600BF871F /* NexilisLite.docc in Sources */ = {isa = PBXBuildFile; fileRef = CD1E6E6C2A0B7C3600BF871F /* NexilisLite.docc */; };
 		CD1E6E732A0B7C3600BF871F /* NexilisLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD1E6E682A0B7C3600BF871F /* NexilisLite.framework */; };
 		CD1E6E782A0B7C3600BF871F /* NexilisLiteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD1E6E772A0B7C3600BF871F /* NexilisLiteTests.swift */; };
@@ -249,6 +253,13 @@
 /* End PBXCopyFilesBuildPhase section */
 
 /* Begin PBXFileReference section */
+		05DE800165B7FA8135DD726B /* Pods_NexilisLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NexilisLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		1241AEBA2D017E8C0088175A /* FileEncryption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileEncryption.swift; sourceTree = "<group>"; };
+		1241AEBB2D017E8C0088175A /* MasterKeyUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MasterKeyUtil.swift; sourceTree = "<group>"; };
+		2B2ED86C8610C9011EBC7B85 /* Pods-NexilisLite-NexilisLiteTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NexilisLite-NexilisLiteTests.release.xcconfig"; path = "Target Support Files/Pods-NexilisLite-NexilisLiteTests/Pods-NexilisLite-NexilisLiteTests.release.xcconfig"; sourceTree = "<group>"; };
+		36C68FFC41F4DA0F806DD5BD /* Pods-NexilisLite.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NexilisLite.debug.xcconfig"; path = "Target Support Files/Pods-NexilisLite/Pods-NexilisLite.debug.xcconfig"; sourceTree = "<group>"; };
+		506228B53B8F36AD707C0E89 /* Pods-NexilisLite.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NexilisLite.release.xcconfig"; path = "Target Support Files/Pods-NexilisLite/Pods-NexilisLite.release.xcconfig"; sourceTree = "<group>"; };
+		ADFED0199C4F4A1E1C3E0DF8 /* Pods-NexilisLite-NexilisLiteTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NexilisLite-NexilisLiteTests.debug.xcconfig"; path = "Target Support Files/Pods-NexilisLite-NexilisLiteTests/Pods-NexilisLite-NexilisLiteTests.debug.xcconfig"; sourceTree = "<group>"; };
 		CD1E6E682A0B7C3600BF871F /* NexilisLite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = NexilisLite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		CD1E6E6B2A0B7C3600BF871F /* NexilisLite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NexilisLite.h; sourceTree = "<group>"; };
 		CD1E6E6C2A0B7C3600BF871F /* NexilisLite.docc */ = {isa = PBXFileReference; lastKnownFileType = folder.documentationcatalog; path = NexilisLite.docc; sourceTree = "<group>"; };
@@ -469,6 +480,7 @@
 		CDDF46792A2EF0A700049A19 /* ScreenSharingViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScreenSharingViewController.swift; sourceTree = "<group>"; };
 		CDE3BED62C86E3A000B0BF36 /* pb_call_in.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = pb_call_in.mp3; sourceTree = "<group>"; };
 		CDE3BED72C86E3A000B0BF36 /* pb_call_out.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = pb_call_out.mp3; sourceTree = "<group>"; };
+		F397F48A7642BC0DB5A8D144 /* Pods_NexilisLite_NexilisLiteTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NexilisLite_NexilisLiteTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -476,6 +488,7 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				3AA890FECDE6363EFE1216A2 /* Pods_NexilisLite.framework in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -484,6 +497,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				CD1E6E732A0B7C3600BF871F /* NexilisLite.framework in Frameworks */,
+				6727D8C17B895F1A290AA89B /* Pods_NexilisLite_NexilisLiteTests.framework in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -507,6 +521,8 @@
 				CD1E79142A0CA43600BF871F /* SDWebImage.framework */,
 				CD1E79152A0CA43600BF871F /* SnapKit.framework */,
 				CD1E79162A0CA43600BF871F /* Toast_Swift.framework */,
+				05DE800165B7FA8135DD726B /* Pods_NexilisLite.framework */,
+				F397F48A7642BC0DB5A8D144 /* Pods_NexilisLite_NexilisLiteTests.framework */,
 			);
 			name = Frameworks;
 			sourceTree = "<group>";
@@ -515,6 +531,10 @@
 			isa = PBXGroup;
 			children = (
 				CD46A0BE2A0CE4FD009E4C87 /* NexilisLite.podspec */,
+				36C68FFC41F4DA0F806DD5BD /* Pods-NexilisLite.debug.xcconfig */,
+				506228B53B8F36AD707C0E89 /* Pods-NexilisLite.release.xcconfig */,
+				ADFED0199C4F4A1E1C3E0DF8 /* Pods-NexilisLite-NexilisLiteTests.debug.xcconfig */,
+				2B2ED86C8610C9011EBC7B85 /* Pods-NexilisLite-NexilisLiteTests.release.xcconfig */,
 			);
 			path = Pods;
 			sourceTree = "<group>";
@@ -563,6 +583,8 @@
 		CD1E714E2A0BA86100BF871F /* Source */ = {
 			isa = PBXGroup;
 			children = (
+				1241AEBA2D017E8C0088175A /* FileEncryption.swift */,
+				1241AEBB2D017E8C0088175A /* MasterKeyUtil.swift */,
 				CD1E71532A0BA86100BF871F /* APIS.swift */,
 				CD1E71B22A0BA86100BF871F /* Callback.swift */,
 				CD1E71B12A0BA86100BF871F /* CoreMessage_TMessageBank.swift */,
@@ -900,11 +922,13 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = CD1E6E7C2A0B7C3600BF871F /* Build configuration list for PBXNativeTarget "NexilisLite" */;
 			buildPhases = (
+				BED1F52D24C088F2C6CBADCB /* [CP] Check Pods Manifest.lock */,
 				CD1E6E632A0B7C3600BF871F /* Headers */,
 				CD1E6E642A0B7C3600BF871F /* Sources */,
 				CD1E6E652A0B7C3600BF871F /* Frameworks */,
 				CD1E6E662A0B7C3600BF871F /* Resources */,
 				CD469E162A0CA6C9009E4C87 /* Embed Frameworks */,
+				E5337755D33CF7D1B634D6AE /* [CP] Copy Pods Resources */,
 			);
 			buildRules = (
 			);
@@ -920,9 +944,12 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = CD1E6E7F2A0B7C3600BF871F /* Build configuration list for PBXNativeTarget "NexilisLiteTests" */;
 			buildPhases = (
+				A715B856D2E42F6596CFB125 /* [CP] Check Pods Manifest.lock */,
 				CD1E6E6E2A0B7C3600BF871F /* Sources */,
 				CD1E6E6F2A0B7C3600BF871F /* Frameworks */,
 				CD1E6E702A0B7C3600BF871F /* Resources */,
+				0F218E5C23838C239124E5D5 /* [CP] Embed Pods Frameworks */,
+				FE56B22938D1E57C12FF3D75 /* [CP] Copy Pods Resources */,
 			);
 			buildRules = (
 			);
@@ -1122,6 +1149,104 @@
 		};
 /* End PBXResourcesBuildPhase section */
 
+/* Begin PBXShellScriptBuildPhase section */
+		0F218E5C23838C239124E5D5 /* [CP] Embed Pods Frameworks */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-NexilisLite-NexilisLiteTests/Pods-NexilisLite-NexilisLiteTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
+			);
+			name = "[CP] Embed Pods Frameworks";
+			outputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-NexilisLite-NexilisLiteTests/Pods-NexilisLite-NexilisLiteTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NexilisLite-NexilisLiteTests/Pods-NexilisLite-NexilisLiteTests-frameworks.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
+		A715B856D2E42F6596CFB125 /* [CP] Check Pods Manifest.lock */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+			);
+			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
+			);
+			name = "[CP] Check Pods Manifest.lock";
+			outputFileListPaths = (
+			);
+			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-NexilisLite-NexilisLiteTests-checkManifestLockResult.txt",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+			showEnvVarsInLog = 0;
+		};
+		BED1F52D24C088F2C6CBADCB /* [CP] Check Pods Manifest.lock */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+			);
+			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
+			);
+			name = "[CP] Check Pods Manifest.lock";
+			outputFileListPaths = (
+			);
+			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-NexilisLite-checkManifestLockResult.txt",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+			showEnvVarsInLog = 0;
+		};
+		E5337755D33CF7D1B634D6AE /* [CP] Copy Pods Resources */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-NexilisLite/Pods-NexilisLite-resources-${CONFIGURATION}-input-files.xcfilelist",
+			);
+			name = "[CP] Copy Pods Resources";
+			outputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-NexilisLite/Pods-NexilisLite-resources-${CONFIGURATION}-output-files.xcfilelist",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NexilisLite/Pods-NexilisLite-resources.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
+		FE56B22938D1E57C12FF3D75 /* [CP] Copy Pods Resources */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-NexilisLite-NexilisLiteTests/Pods-NexilisLite-NexilisLiteTests-resources-${CONFIGURATION}-input-files.xcfilelist",
+			);
+			name = "[CP] Copy Pods Resources";
+			outputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-NexilisLite-NexilisLiteTests/Pods-NexilisLite-NexilisLiteTests-resources-${CONFIGURATION}-output-files.xcfilelist",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NexilisLite-NexilisLiteTests/Pods-NexilisLite-NexilisLiteTests-resources.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
+/* End PBXShellScriptBuildPhase section */
+
 /* Begin PBXSourcesBuildPhase section */
 		CD1E6E642A0B7C3600BF871F /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
@@ -1156,6 +1281,8 @@
 				CD1E72112A0BA86100BF871F /* WhiteboardReceiver.swift in Sources */,
 				CD1E725F2A0BA86100BF871F /* CoreMessage_TMessageBank.swift in Sources */,
 				CD1E72222A0BA86100BF871F /* FormEditor.swift in Sources */,
+				1241AEBC2D017E8C0088175A /* MasterKeyUtil.swift in Sources */,
+				1241AEBD2D017E8C0088175A /* FileEncryption.swift in Sources */,
 				CD1E725A2A0BA86100BF871F /* ScannerViewController.swift in Sources */,
 				CD1E72462A0BA86100BF871F /* GroupTopicViewController.swift in Sources */,
 				CD1E72302A0BA86100BF871F /* CallProviderDelegate.swift in Sources */,
@@ -1398,12 +1525,13 @@
 		};
 		CD1E6E7D2A0B7C3600BF871F /* Debug */ = {
 			isa = XCBuildConfiguration;
+			baseConfigurationReference = 36C68FFC41F4DA0F806DD5BD /* Pods-NexilisLite.debug.xcconfig */;
 			buildSettings = {
 				BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
 				DEFINES_MODULE = YES;
-				DEVELOPMENT_TEAM = FR2C2CZUYZ;
+				DEVELOPMENT_TEAM = 4R36B4D29V;
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
@@ -1437,12 +1565,13 @@
 		};
 		CD1E6E7E2A0B7C3600BF871F /* Release */ = {
 			isa = XCBuildConfiguration;
+			baseConfigurationReference = 506228B53B8F36AD707C0E89 /* Pods-NexilisLite.release.xcconfig */;
 			buildSettings = {
 				BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
 				DEFINES_MODULE = YES;
-				DEVELOPMENT_TEAM = FR2C2CZUYZ;
+				DEVELOPMENT_TEAM = 4R36B4D29V;
 				DYLIB_COMPATIBILITY_VERSION = 1;
 				DYLIB_CURRENT_VERSION = 1;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
@@ -1476,11 +1605,12 @@
 		};
 		CD1E6E802A0B7C3600BF871F /* Debug */ = {
 			isa = XCBuildConfiguration;
+			baseConfigurationReference = ADFED0199C4F4A1E1C3E0DF8 /* Pods-NexilisLite-NexilisLiteTests.debug.xcconfig */;
 			buildSettings = {
 				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)";
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_TEAM = FR2C2CZUYZ;
+				DEVELOPMENT_TEAM = 4R36B4D29V;
 				GENERATE_INFOPLIST_FILE = YES;
 				MARKETING_VERSION = 1.0;
 				PRODUCT_BUNDLE_IDENTIFIER = io.nexilis.NexilisLiteTests;
@@ -1493,11 +1623,12 @@
 		};
 		CD1E6E812A0B7C3600BF871F /* Release */ = {
 			isa = XCBuildConfiguration;
+			baseConfigurationReference = 2B2ED86C8610C9011EBC7B85 /* Pods-NexilisLite-NexilisLiteTests.release.xcconfig */;
 			buildSettings = {
 				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)";
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_TEAM = FR2C2CZUYZ;
+				DEVELOPMENT_TEAM = 4R36B4D29V;
 				GENERATE_INFOPLIST_FILE = YES;
 				MARKETING_VERSION = 1.0;
 				PRODUCT_BUNDLE_IDENTIFIER = io.nexilis.NexilisLiteTests;
@@ -1514,7 +1645,7 @@
 				CODE_SIGN_STYLE = Automatic;
 				COMBINE_HIDPI_IMAGES = YES;
 				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_TEAM = FR2C2CZUYZ;
+				DEVELOPMENT_TEAM = 4R36B4D29V;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_KEY_NSHumanReadableCopyright = "";
 				INFOPLIST_KEY_NSPrincipalClass = "";
@@ -1536,7 +1667,7 @@
 				CODE_SIGN_STYLE = Automatic;
 				COMBINE_HIDPI_IMAGES = YES;
 				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_TEAM = FR2C2CZUYZ;
+				DEVELOPMENT_TEAM = 4R36B4D29V;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_KEY_NSHumanReadableCopyright = "";
 				INFOPLIST_KEY_NSPrincipalClass = "";

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

@@ -357,6 +357,10 @@ extension NSObject {
             if FileManager().fileExists(atPath: file.path) {
                 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 image = UIImage(data: tempData)?.sd_resizedImage(with: CGSize(width: 400, height: 400), scaleMode: .aspectFill)
+                FileEncryption.shared.wipeData(&tempData)
+                completion(true, true, isCircle ? image?.circleMasked : image)
             } else {
                 completion(false, false, placeholderImage)
                 Download().startHTTP(forKey: url) { (name, progress) in
@@ -371,8 +375,19 @@ extension NSObject {
                             tableView!.endUpdates()
                         }
                         if type(of: self).urlStore[tmpAddress] == name {
-                            let image = UIImage(contentsOfFile: file.path)?.sd_resizedImage(with: CGSize(width: 400, height: 400), scaleMode: .aspectFill)
-                            completion(true, true, isCircle ? image?.circleMasked : image)
+                            if FileManager().fileExists(atPath: file.path) {
+                                let image = UIImage(contentsOfFile: file.path)?.sd_resizedImage(with: CGSize(width: 400, height: 400), scaleMode: .aspectFill)
+                                completion(true, true, isCircle ? image?.circleMasked : image)
+                            } else if FileEncryption.shared.isSecureExists(filename: url) {
+                                do {
+                                    if let imageData = try FileEncryption.shared.readSecure(filename: url) {
+                                        let image = UIImage(data: imageData)?.sd_resizedImage(with: CGSize(width: 400, height: 400), scaleMode: .aspectFill)
+                                        completion(true, true, isCircle ? image?.circleMasked : image)
+                                    }
+                                } catch {
+                                    
+                                }
+                            }
                         }
                     }
                 }

+ 19 - 4
NexilisLite/NexilisLite/Source/FileEncryption.swift

@@ -41,16 +41,17 @@ public class FileEncryption {
         return try decryptToMemory(fileURL)
     }
     
-    func writeSecure(filename: String? = nil, fileURL : URL? = nil) throws -> [Any]? {
+    func writeSecure(filename: String? = nil, fileURL : URL? = nil, data: Data? = nil) throws -> [Any]? {
         let fileManager = FileManager.default
         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 data = encryptFile(inputURL) else { return nil }
-        try data.write(to: outputURL)
+        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 {
@@ -73,6 +74,16 @@ public class FileEncryption {
         
     }
     
+    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
@@ -80,8 +91,12 @@ public class FileEncryption {
     
     func encryptFile(_ fileURL: URL) -> Data? {
         guard let fileData = readDataFromFile(fileURL: fileURL) else { return nil }
+        return encryptFile(fileData)
+    }
+    
+    func encryptFile(_ data: Data) -> Data? {
         do {
-            let sealedBox = try AES.GCM.seal(fileData, using: MasterKeyUtil.shared.getMasterKey())
+            let sealedBox = try AES.GCM.seal(data, using: MasterKeyUtil.shared.getMasterKey())
             return sealedBox.combined
         } catch {
             print("Encryption failed: \(error)")

+ 108 - 11
NexilisLite/NexilisLite/Source/Nexilis.swift

@@ -423,6 +423,20 @@ public class Nexilis: NSObject {
                                     let ad = jsonData["authentication_duration"] as! String
                                     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 convertJsonFA = try? JSONSerialization.data(withJSONObject: jsonFA, options: .prettyPrinted) {
                                 if let jsonFAString = String(data: convertJsonFA, encoding: .utf8) {
@@ -1589,13 +1603,27 @@ public class Nexilis: NSObject {
     }
     
     static func resizedImage(at url: URL, for size: CGSize) -> UIImage? {
-        guard let image = UIImage(contentsOfFile: url.path) else {
+        var image : UIImage?
+        if FileManager.default.fileExists(atPath: url.path){
+            image = UIImage(contentsOfFile: url.path)
+        }
+        else if FileEncryption.shared.isSecureExists(filename: url.lastPathComponent) {
+            do {
+                if let imageData = try FileEncryption.shared.readSecure(filename: url.lastPathComponent) {
+                    image = UIImage(data: imageData)
+                }
+            }
+            catch {
+                
+            }
+        }
+        if image == nil {
             return nil
         }
         
         let renderer = UIGraphicsImageRenderer(size: size)
         return renderer.image { (context) in
-            image.draw(in: CGRect(origin: .zero, size: size))
+            image!.draw(in: CGRect(origin: .zero, size: size))
         }
     }
     
@@ -2511,14 +2539,50 @@ extension Nexilis: MessageDelegate {
                                     } else {
                                         UIApplication.shared.visibleViewController?.present(previewImageVC, animated: true, completion: nil)
                                     }
+                                } 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)
+                                        }
+                                    } catch {
+                                        
+                                    }
                                 } else {
                                     Download().startHTTP(forKey: image) { (name, progress) in
                                         guard progress == 100 else {
                                             return
                                         }
+                                        
+                                        do {
+                                            try FileEncryption.shared.writeSecure(filename: image)
+                                        } catch {
+                                            
+                                        }
                 
                                         DispatchQueue.main.async {
-                                            let image    = UIImage(contentsOfFile: imageURL.path)
+                                            var image : UIImage?
+                                            if FileManager.default.fileExists(atPath: imageURL.path) {
+                                                image    = UIImage(contentsOfFile: imageURL.path)
+                                            }
+                                            else if FileEncryption.shared.isSecureExists(filename: imageURL.lastPathComponent) {
+                                                do {
+                                                    if let imageData = try FileEncryption.shared.readSecure(filename: imageURL.lastPathComponent) {
+                                                        image = UIImage(data: imageData)
+                                                    }
+                                                } catch {
+                                                    
+                                                }
+                                            }
+                                            
                                             let previewImageVC = PreviewAttachmentImageVideo(nibName: "PreviewAttachmentImageVideo", bundle: Bundle.resourceBundle(for: Nexilis.self))
                                             previewImageVC.image = image
                                             previewImageVC.isHiddenTextField = true
@@ -2560,25 +2624,58 @@ extension Nexilis: MessageDelegate {
                                     } else {
                                         UIApplication.shared.visibleViewController?.present(previewController, animated: true, completion: nil)
                                     }
-                                } else {
-                                    Download().startHTTP(forKey: file) { (name, progress) in
-                                        DispatchQueue.main.async {
-                                            guard progress == 100 else {
-                                                return
-                                            }
-                                            previewItem = fileURL as NSURL
+                                } else if FileEncryption.shared.isSecureExists(filename: file) {
+                                    do {
+                                        if let docData = try FileEncryption.shared.readSecure(filename: file) {
+                                            let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
+                                            let tempPath = cachesDirectory.appendingPathComponent(file)
+                                            try docData.write(to: tempPath)
+                                            previewItem = tempPath as NSURL
                                             let previewController = QLPreviewController()
                                             let rightBarButton = UIBarButtonItem()
                                             previewController.navigationItem.rightBarButtonItem = rightBarButton
                                             previewController.dataSource = self
                                             previewController.modalPresentationStyle = .overFullScreen
-                
+                                            
                                             if UIApplication.shared.visibleViewController?.navigationController != nil {
                                                 UIApplication.shared.visibleViewController?.navigationController?.present(previewController, animated: true, completion: nil)
                                             } else {
                                                 UIApplication.shared.visibleViewController?.present(previewController, animated: true, completion: nil)
                                             }
                                         }
+                                    } catch {
+                                        
+                                    }
+                                } else {
+                                    Download().startHTTP(forKey: file) { (name, progress) in
+                                        DispatchQueue.main.async {
+                                            guard progress == 100 else {
+                                                return
+                                            }
+                                            do {
+                                                let secureFilename = try FileEncryption.shared.writeSecure(filename: name)
+                                                if let docData = try FileEncryption.shared.readSecure(filename: secureFilename?[0] as! String) {
+                                                    let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
+                                                    let tempPath = cachesDirectory.appendingPathComponent(file)
+                                                    try docData.write(to: tempPath)
+                                                    previewItem = tempPath as NSURL
+                                                    let previewController = QLPreviewController()
+                                                    let rightBarButton = UIBarButtonItem()
+                                                    previewController.navigationItem.rightBarButtonItem = rightBarButton
+                                                    previewController.dataSource = self
+                                                    previewController.modalPresentationStyle = .overFullScreen
+                                                    
+                                                    if UIApplication.shared.visibleViewController?.navigationController != nil {
+                                                        UIApplication.shared.visibleViewController?.navigationController?.present(previewController, animated: true, completion: nil)
+                                                    } else {
+                                                        UIApplication.shared.visibleViewController?.present(previewController, animated: true, completion: nil)
+                                                    }
+                                                }
+                                            }
+                                            catch {
+                                                
+                                            }
+                                        }
                                     }
                                 }
                             }

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

@@ -195,6 +195,11 @@ class OutgoingThread {
                                                 print("Access database error: \(error.localizedDescription)")
                                             }
                                         })
+                                        do {
+                                            try FileEncryption.shared.writeSecure(filename: fileName)
+                                        } catch {
+                                            
+                                        }
                                     } else {
                                         self.retryUpload(message: message, fileName: fileName)
                                     }
@@ -228,6 +233,11 @@ class OutgoingThread {
                                         print("Access database error: \(error.localizedDescription)")
                                     }
                                 })
+                                do{
+                                    try FileEncryption.shared.writeSecure(filename: fileName)
+                                } catch {
+                                    
+                                }
                             } else {
                                 self.retryUpload(message: message, fileName: fileName)
                             }

+ 46 - 18
NexilisLite/NexilisLite/Source/View/Chat/ChatGPTBotView.swift

@@ -710,17 +710,19 @@ class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
                         if let dirPath = paths.first {
                             let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["video_id"] as! String)
                             let fileURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["file_id"] as! String)
-                            if ((row["video_id"] as! String) != "") {
-                                if FileManager.default.fileExists(atPath: videoURL.path){
-                                    row["progress"] = 100.0
-                                } else {
-                                    row["progress"] = 0.0
-                                }
-                            } else {
-                                if FileManager.default.fileExists(atPath: fileURL.path){
-                                    row["progress"] = 100.0
+                            do {
+                                if ((row["video_id"] as! String) != "") {
+                                    if FileManager.default.fileExists(atPath: videoURL.path) || FileEncryption.shared.isSecureExists(filename: row["video_id"] as! String){
+                                        row["progress"] = 100.0
+                                    } else {
+                                        row["progress"] = 0.0
+                                    }
                                 } else {
-                                    row["progress"] = 0.0
+                                    if FileManager.default.fileExists(atPath: fileURL.path) || FileEncryption.shared.isSecureExists(filename: row["file_id"] as! String){
+                                        row["progress"] = 100.0
+                                    } else {
+                                        row["progress"] = 0.0
+                                    }
                                 }
                             }
                         }
@@ -1643,10 +1645,23 @@ extension ChatGPTBotView: UIContextMenuInteractionDelegate {
                                 let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
                                 if let dirPath = paths.first {
                                     let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent(dataMessages[indexPath.row]["image_id"] as! String)
-                                    if FileManager.default.fileExists(atPath: imageURL.path) {
-                                        let image    = UIImage(contentsOfFile: imageURL.path)
-                                        UIPasteboard.general.image = image
-                                        self.showToast(message: "Image coppied to clipboard".localized(), font: UIFont.systemFont(ofSize: 12, weight: .medium), controller: self)
+                                    if FileManager.default.fileExists(atPath: imageURL.path) || FileEncryption.shared.isSecureExists(filename: imageURL.lastPathComponent) {
+                                        if FileManager.default.fileExists(atPath: imageURL.path) {
+                                            let image    = UIImage(contentsOfFile: imageURL.path)
+                                            UIPasteboard.general.image = image
+                                            self.showToast(message: "Image coppied to clipboard".localized(), font: UIFont.systemFont(ofSize: 12, weight: .medium), controller: self)
+                                        }
+                                        else if FileEncryption.shared.isSecureExists(filename: imageURL.lastPathComponent) {
+                                            do {
+                                                if let imageData = try FileEncryption.shared.readSecure(filename: imageURL.lastPathComponent) {
+                                                    let image = UIImage(data: imageData)
+                                                    UIPasteboard.general.image = image
+                                                    self.showToast(message: "Image coppied to clipboard".localized(), font: UIFont.systemFont(ofSize: 12, weight: .medium), controller: self)
+                                                }
+                                            } catch {
+                                                
+                                            }
+                                        }
                                     }
                                 }
                             }
@@ -1664,10 +1679,23 @@ extension ChatGPTBotView: UIContextMenuInteractionDelegate {
                                 let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
                                 if let dirPath = paths.first {
                                     let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent(dataMessages[indexPath.row]["image_id"] as! String)
-                                    if FileManager.default.fileExists(atPath: imageURL.path) {
-                                        let image    = UIImage(contentsOfFile: imageURL.path)
-                                        UIPasteboard.general.image = image
-                                        self.showToast(message: "Image coppied to clipboard".localized(), font: UIFont.systemFont(ofSize: 12, weight: .medium), controller: self)
+                                    if FileManager.default.fileExists(atPath: imageURL.path) || FileEncryption.shared.isSecureExists(filename: imageURL.lastPathComponent ) {
+                                        if FileManager.default.fileExists(atPath: imageURL.path) {
+                                            let image    = UIImage(contentsOfFile: imageURL.path)
+                                            UIPasteboard.general.image = image
+                                            self.showToast(message: "Image coppied to clipboard".localized(), font: UIFont.systemFont(ofSize: 12, weight: .medium), controller: self)
+                                        }
+                                        else if FileEncryption.shared.isSecureExists(filename: imageURL.lastPathComponent) {
+                                            do {
+                                                if let imageData = try FileEncryption.shared.readSecure(filename: imageURL.lastPathComponent) {
+                                                    let image = UIImage(data: imageData)
+                                                    UIPasteboard.general.image = image
+                                                    self.showToast(message: "Image coppied to clipboard".localized(), font: UIFont.systemFont(ofSize: 12, weight: .medium), controller: self)
+                                                }
+                                            } catch {
+                                                
+                                            }
+                                        }
                                     }
                                 }
                             }

文件差异内容过多而无法显示
+ 745 - 562
NexilisLite/NexilisLite/Source/View/Chat/EditorGroup.swift


+ 260 - 64
NexilisLite/NexilisLite/Source/View/Chat/EditorPersonal.swift

@@ -881,13 +881,13 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                             let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["video_id"] as! String)
                             let fileURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["file_id"] as! String)
                             if ((row["video_id"] as! String) != "") {
-                                if FileManager.default.fileExists(atPath: videoURL.path){
+                                if FileManager.default.fileExists(atPath: videoURL.path) || FileEncryption.shared.isSecureExists(filename: videoURL.lastPathComponent){
                                     row["progress"] = 100.0
                                 } else {
                                     row["progress"] = 0.0
                                 }
                             } else {
-                                if FileManager.default.fileExists(atPath: fileURL.path){
+                                if FileManager.default.fileExists(atPath: fileURL.path) || FileEncryption.shared.isSecureExists(filename: fileURL.lastPathComponent){
                                     row["progress"] = 100.0
                                 } else {
                                     row["progress"] = 0.0
@@ -1056,13 +1056,13 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                             let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["video_id"] as! String)
                             let fileURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["file_id"] as! String)
                             if ((row["video_id"] as! String) != "") {
-                                if FileManager.default.fileExists(atPath: videoURL.path){
+                                if FileManager.default.fileExists(atPath: videoURL.path) || FileEncryption.shared.isSecureExists(filename: videoURL.lastPathComponent){
                                     row["progress"] = 100.0
                                 } else {
                                     row["progress"] = 0.0
                                 }
                             } else {
-                                if FileManager.default.fileExists(atPath: fileURL.path){
+                                if FileManager.default.fileExists(atPath: fileURL.path) || FileEncryption.shared.isSecureExists(filename: fileURL.lastPathComponent){
                                     row["progress"] = 100.0
                                 } else {
                                     row["progress"] = 0.0
@@ -2921,16 +2921,33 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                                 guard progress == 100 else {
                                     return
                                 }
-                                let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
-                                let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
-                                let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
-                                if let dirPath = paths.first {
-                                    let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent(valueListGroupImages[i].imageId)
-                                    let image    = UIImage(contentsOfFile: imageURL.path)
-                                    let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
-                                    if save {
-                                        UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
+                                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)
+                                    if let dirPath = paths.first {
+                                        let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent(valueListGroupImages[i].imageId)
+                                        if FileManager.default.fileExists(atPath: imageURL.path) {
+                                            let image    = UIImage(contentsOfFile: imageURL.path)
+                                            let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
+                                            if save {
+                                                UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
+                                            }
+                                        }
+                                        else if FileEncryption.shared.isSecureExists(filename: valueListGroupImages[i].imageId) {
+                                            if let secureData = try FileEncryption.shared.readSecure(filename: valueListGroupImages[i].imageId) {
+                                                let image = UIImage(data: secureData)
+                                                let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
+                                                if save {
+                                                    UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
+                                                }
+                                            }
+                                        }
                                     }
+                                }
+                                catch {
+                                    
                                 }
                                 DispatchQueue.main.async { [self] in
                                     let section = dataDates.firstIndex(of: dataMessages[index]["chat_date"] as! String)
@@ -2946,16 +2963,32 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                             guard progress == 100 else {
                                 return
                             }
-                            let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
-                            let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
-                            let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
-                            if let dirPath = paths.first {
-                                let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent(self.dataMessages[index]["image_id"] as! String)
-                                let image    = UIImage(contentsOfFile: imageURL.path)
-                                let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
-                                if save {
-                                    UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
+                            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)
+                                if let dirPath = paths.first {
+                                    let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent(self.dataMessages[index]["image_id"] as! String)
+                                    if FileManager.default.fileExists(atPath: imageURL.path) {
+                                        let image    = UIImage(contentsOfFile: imageURL.path)
+                                        let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
+                                        if save {
+                                            UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
+                                        }
+                                    }
+                                    else if FileEncryption.shared.isSecureExists(filename: secureName) {
+                                        if let secureData = try FileEncryption.shared.readSecure(filename: secureName) {
+                                            let image = UIImage(data: secureData)
+                                            let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
+                                            if save {
+                                                UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
+                                            }
+                                        }
+                                    }
                                 }
+                            } catch {
+                                
                             }
                             DispatchQueue.main.async { [self] in
                                 let section = dataDates.firstIndex(of: dataMessages[index]["chat_date"] as! String)
@@ -2971,19 +3004,41 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                         guard progress == 100 else {
                             return
                         }
-                        let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
-                        let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
-                        let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
-                        if let dirPath = paths.first {
-                            let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(self.dataMessages[index]["video_id"] as! String)
-                            let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
-                            if save {
-                                PHPhotoLibrary.shared().performChanges({
-                                    PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: videoURL)
-                                }) { saved, error in
-                                    
+                        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)
+                            if let dirPath = paths.first {
+                                let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(self.dataMessages[index]["video_id"] as! String)
+                                if FileManager.default.fileExists(atPath: videoURL.path) {
+                                    let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
+                                    if save {
+                                        PHPhotoLibrary.shared().performChanges({
+                                            PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: videoURL)
+                                        }) { saved, error in
+                                            
+                                        }
+                                    }
+                                }
+                                else if FileEncryption.shared.isSecureExists(filename: secureName) {
+                                    if let secureData = try FileEncryption.shared.readSecure(filename: secureName) {
+                                        let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
+                                        let tempPath = cachesDirectory.appendingPathComponent(name)
+                                        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
+                                                
+                                            }
+                                        }
+                                    }
                                 }
                             }
+                        } catch {
+                            
                         }
                         DispatchQueue.main.async { [self] in
                             let section = dataDates.firstIndex(of: dataMessages[index]["chat_date"] as! String)
@@ -2998,6 +3053,11 @@ public class EditorPersonal: UIViewController, ImageVideoPickerDelegate, UIGestu
                     Download().startHTTP(forKey: dataMessages[index]["file_id"] as! String) { (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)
@@ -4241,6 +4301,16 @@ extension EditorPersonal: UIContextMenuInteractionDelegate {
                                         let image    = UIImage(contentsOfFile: imageURL.path)
                                         UIPasteboard.general.image = image
                                         self.showToast(message: "Image coppied to clipboard".localized(), font: UIFont.systemFont(ofSize: 12, weight: .medium), controller: self)
+                                    } else if FileEncryption.shared.isSecureExists(filename: imageURL.lastPathComponent) {
+                                        do {
+                                            if let imageData = try FileEncryption.shared.readSecure(filename: imageURL.lastPathComponent) {
+                                                let image = UIImage(data: imageData)
+                                                UIPasteboard.general.image = image
+                                                self.showToast(message: "Image coppied to clipboard".localized(), font: UIFont.systemFont(ofSize: 12, weight: .medium), controller: self)
+                                            }
+                                        } catch {
+                                            
+                                        }
                                     }
                                 }
                             }
@@ -4262,6 +4332,16 @@ extension EditorPersonal: UIContextMenuInteractionDelegate {
                                         let image    = UIImage(contentsOfFile: imageURL.path)
                                         UIPasteboard.general.image = image
                                         self.showToast(message: "Image coppied to clipboard".localized(), font: UIFont.systemFont(ofSize: 12, weight: .medium), controller: self)
+                                    } else if FileEncryption.shared.isSecureExists(filename: imageURL.lastPathComponent) {
+                                        do {
+                                            if let imageData = try FileEncryption.shared.readSecure(filename: imageURL.lastPathComponent) {
+                                                let image = UIImage(data: imageData)
+                                                UIPasteboard.general.image = image
+                                                self.showToast(message: "Image coppied to clipboard".localized(), font: UIFont.systemFont(ofSize: 12, weight: .medium), controller: self)
+                                            }
+                                        } catch {
+                                            
+                                        }
                                     }
                                 }
                             }
@@ -4492,7 +4572,7 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource {
                 let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
                 if let dirPath = paths.first {
                     let fileURL = URL(fileURLWithPath: dirPath).appendingPathComponent(file)
-                    if !FileManager.default.fileExists(atPath: fileURL.path) {
+                    if !FileManager.default.fileExists(atPath: fileURL.path) && !FileEncryption.shared.isSecureExists(filename: fileURL.lastPathComponent) {
                         return
                     }
                 }
@@ -4886,7 +4966,7 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource {
                 let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
                 if let dirPath = paths.first {
                     let fileURL = URL(fileURLWithPath: dirPath).appendingPathComponent(file)
-                    if !FileManager.default.fileExists(atPath: fileURL.path) {
+                    if !FileManager.default.fileExists(atPath: fileURL.path) && !FileEncryption.shared.isSecureExists(filename: fileURL.lastPathComponent) {
                         showSelectedImage = false
                     }
                 }
@@ -5355,7 +5435,7 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource {
                         listImageThumb[i].image = image
 
                         let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent(listImages[i].imageId)
-                        if !FileManager.default.fileExists(atPath: imageURL.path) {
+                        if !FileManager.default.fileExists(atPath: imageURL.path) && !FileEncryption.shared.isSecureExists(filename: imageURL.lastPathComponent) {
                             let blurEffect = UIBlurEffect(style: UIBlurEffect.Style.light)
                             let blurEffectView = UIVisualEffectView(effect: blurEffect)
                             blurEffectView.frame = CGRect(x: 0, y: 0, width: listImageThumb[i].frame.size.width, height: listImageThumb[i].frame.size.height)
@@ -5477,7 +5557,7 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource {
 //                    let image = UIGraphicsRenderer.renderImageAt(url: thumbURL as NSURL, size: CGSize(width: 250, height: 250))
                     let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(videoChat)
                     let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent(imageChat)
-                    if !FileManager.default.fileExists(atPath: imageURL.path) || !FileManager.default.fileExists(atPath: videoURL.path) {
+                    if !FileManager.default.fileExists(atPath: imageURL.path) && !FileManager.default.fileExists(atPath: videoURL.path) && !FileEncryption.shared.isSecureExists(filename: imageURL.lastPathComponent) && !FileEncryption.shared.isSecureExists(filename: videoURL.lastPathComponent) {
                         let blurEffect = UIBlurEffect(style: UIBlurEffect.Style.light)
                         let blurEffectView = UIVisualEffectView(effect: blurEffect)
                         blurEffectView.frame = CGRect(x: 0, y: 0, width: imageThumb.frame.size.width, height: imageThumb.frame.size.height)
@@ -5561,24 +5641,47 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource {
             let finalExtFile = arrExtFile[arrExtFile.count - 1]
             if let dirPath = paths.first {
                 let fileURL = URL(fileURLWithPath: dirPath).appendingPathComponent(fileChat)
-                if let dataFile = try? Data(contentsOf: fileURL) {
-                    var sizeOfFile = Int(dataFile.count / 1000000)
-                    if (sizeOfFile < 1) {
-                        sizeOfFile = Int(dataFile.count / 1000)
-                        if (finalExtFile.count > 4) {
-                            messageText.text = "\(sizeOfFile) kB \u{2022} TXT"
-                        }else {
-                            messageText.text = "\(sizeOfFile) kB \u{2022} \(finalExtFile.uppercased())"
+                if FileManager.default.fileExists(atPath: fileURL.path) {
+                    if let dataFile = try? Data(contentsOf: fileURL) {
+                        var sizeOfFile = Int(dataFile.count / 1000000)
+                        if (sizeOfFile < 1) {
+                            sizeOfFile = Int(dataFile.count / 1000)
+                            if (finalExtFile.count > 4) {
+                                messageText.text = "\(sizeOfFile) kB \u{2022} TXT"
+                            }else {
+                                messageText.text = "\(sizeOfFile) kB \u{2022} \(finalExtFile.uppercased())"
+                            }
+                        } else {
+                            if (finalExtFile.count > 4) {
+                                messageText.text = "\(sizeOfFile) MB \u{2022} TXT"
+                            }else {
+                                messageText.text = "\(sizeOfFile) MB \u{2022} \(finalExtFile.uppercased())"
+                            }
                         }
                     } else {
-                        if (finalExtFile.count > 4) {
-                            messageText.text = "\(sizeOfFile) MB \u{2022} TXT"
-                        }else {
-                            messageText.text = "\(sizeOfFile) MB \u{2022} \(finalExtFile.uppercased())"
+                        messageText.text = ""
+                    }
+                }
+                else if FileEncryption.shared.isSecureExists(filename: fileChat) {
+                    if let dataFile = try? FileEncryption.shared.readSecure(filename: fileChat) {
+                        var sizeOfFile = Int(dataFile.count / 1000000)
+                        if (sizeOfFile < 1) {
+                            sizeOfFile = Int(dataFile.count / 1000)
+                            if (finalExtFile.count > 4) {
+                                messageText.text = "\(sizeOfFile) kB \u{2022} TXT"
+                            }else {
+                                messageText.text = "\(sizeOfFile) kB \u{2022} \(finalExtFile.uppercased())"
+                            }
+                        } else {
+                            if (finalExtFile.count > 4) {
+                                messageText.text = "\(sizeOfFile) MB \u{2022} TXT"
+                            }else {
+                                messageText.text = "\(sizeOfFile) MB \u{2022} \(finalExtFile.uppercased())"
+                            }
                         }
+                    } else {
+                        messageText.text = ""
                     }
-                } else {
-                    messageText.text = ""
                 }
             }
             
@@ -6210,6 +6313,20 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource {
                     previewImageVC.modalPresentationStyle = .custom
                     previewImageVC.modalTransitionStyle  = .crossDissolve
                     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)
+                    }
+                    catch {
+                        print("Error reading secure file")
+                    }
                 } else {
                     for view in sender.imageView.subviews {
                         if view is UIImageView {
@@ -6227,11 +6344,32 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource {
                         guard progress == 100 else {
                             return
                         }
-                        let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent(sender.image_id)
-                        let image    = UIImage(contentsOfFile: imageURL.path)
-                        let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
-                        if save {
-                            UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
+                        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)
+                            if let dirPath = paths.first {
+                                let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent(sender.image_id)
+                                if FileManager.default.fileExists(atPath: imageURL.path) {
+                                    let image    = UIImage(contentsOfFile: imageURL.path)
+                                    let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
+                                    if save {
+                                        UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
+                                    }
+                                }
+                                else if FileEncryption.shared.isSecureExists(filename: secureName) {
+                                    if let secureData = try FileEncryption.shared.readSecure(filename: secureName) {
+                                        let image = UIImage(data: secureData)
+                                        let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
+                                        if save {
+                                            UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
+                                        }
+                                    }
+                                }
+                            }
+                        } catch {
+                            
                         }
                         DispatchQueue.main.async {
                             activityIndicator.stopAnimating()
@@ -6249,6 +6387,21 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource {
                     playerVC.modalPresentationStyle = .custom
                     playerVC.player = player
                     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) {
+                            let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
+                            let tempPath = cachesDirectory.appendingPathComponent(sender.video_id)
+                            try secureData.write(to: tempPath)
+                            let player = AVPlayer(url: tempPath as URL)
+                            let playerVC = AVPlayerViewController()
+                            playerVC.modalPresentationStyle = .custom
+                            playerVC.player = player
+                            self.present(playerVC, animated: true, completion: nil)
+                        }
+                    } catch {
+                        
+                    }
                 } else {
                     for view in sender.imageView.subviews {
                         if view is UIImageView {
@@ -6291,14 +6444,33 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource {
                                 shapeLoading.strokeEnd = CGFloat(progress / 100)
                                 return
                             }
-                            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
-                                    
+                            do {
+                                if let secureName = try FileEncryption.shared.writeSecure(filename: name)?[0] as? String {
+                                    let secureData = try FileEncryption.shared.readSecure(filename: secureName)
+                                    let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
+                                    let tempPath = cachesDirectory.appendingPathComponent(name)
+                                    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
+                                            
+                                        }
+                                    }
                                 }
+                            } catch {
+                                
                             }
                             let idx = self.dataMessages.firstIndex(where: { $0["video_id"] as! String == sender.video_id})
                             if idx != nil {
@@ -6321,7 +6493,26 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource {
                     previewController.modalPresentationStyle = .custom
                     
                     self.present(previewController, animated: true)
-                } else {
+                } else if FileEncryption.shared.isSecureExists(filename: sender.file_id) {
+                    do {
+                        if let docData = try FileEncryption.shared.readSecure(filename: sender.file_id) {
+                            
+                            let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
+                            let tempPath = cachesDirectory.appendingPathComponent(sender.file_id)
+                            try docData.write(to: tempPath)
+                            self.previewItem = tempPath as NSURL
+                            let previewController = QLPreviewController()
+                            let rightBarButton = UIBarButtonItem()
+                            previewController.navigationItem.rightBarButtonItem = rightBarButton
+                            previewController.dataSource = self
+                            previewController.modalPresentationStyle = .custom
+                            self.present(previewController,animated: true)
+                        }
+                    }
+                    catch {
+                        
+                    }
+                }   else {
                     for view in sender.containerFile.subviews {
                         if !(view is UIImageView) && !(view is UILabel) {
                             view.removeFromSuperview()
@@ -6361,6 +6552,11 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource {
                             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 {

+ 167 - 29
NexilisLite/NexilisLite/Source/View/Chat/EditorStarMessages.swift

@@ -499,7 +499,7 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
                 
                 let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(videoChat)
                 let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent(imageChat)
-                if !FileManager.default.fileExists(atPath: imageURL.path) || !FileManager.default.fileExists(atPath: videoURL.path){
+                if !FileManager.default.fileExists(atPath: imageURL.path) && !FileManager.default.fileExists(atPath: videoURL.path) && !FileEncryption.shared.isSecureExists(filename: imageURL.lastPathComponent) && !FileEncryption.shared.isSecureExists(filename: videoURL.lastPathComponent){
                     let blurEffect = UIBlurEffect(style: UIBlurEffect.Style.light)
                     let blurEffectView = UIVisualEffectView(effect: blurEffect)
                     blurEffectView.frame = CGRect(x: 0, y: 0, width: imageThumb.frame.size.width, height: imageThumb.frame.size.height)
@@ -577,24 +577,47 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
             let finalExtFile = arrExtFile![arrExtFile!.count - 1]
             if let dirPath = paths.first {
                 let fileURL = URL(fileURLWithPath: dirPath).appendingPathComponent(fileChat)
-                if let dataFile = try? Data(contentsOf: fileURL) {
-                    var sizeOfFile = Int(dataFile.count / 1000000)
-                    if (sizeOfFile < 1) {
-                        sizeOfFile = Int(dataFile.count / 1000)
-                        if (finalExtFile.count > 4) {
-                            messageText.text = "\(sizeOfFile) kB \u{2022} TXT"
-                        }else {
-                            messageText.text = "\(sizeOfFile) kB \u{2022} \(finalExtFile.uppercased())"
+                if FileManager.default.fileExists(atPath: fileURL.path) {
+                    if let dataFile = try? Data(contentsOf: fileURL) {
+                        var sizeOfFile = Int(dataFile.count / 1000000)
+                        if (sizeOfFile < 1) {
+                            sizeOfFile = Int(dataFile.count / 1000)
+                            if (finalExtFile.count > 4) {
+                                messageText.text = "\(sizeOfFile) kB \u{2022} TXT"
+                            }else {
+                                messageText.text = "\(sizeOfFile) kB \u{2022} \(finalExtFile.uppercased())"
+                            }
+                        } else {
+                            if (finalExtFile.count > 4) {
+                                messageText.text = "\(sizeOfFile) MB \u{2022} TXT"
+                            }else {
+                                messageText.text = "\(sizeOfFile) MB \u{2022} \(finalExtFile.uppercased())"
+                            }
                         }
                     } else {
-                        if (finalExtFile.count > 4) {
-                            messageText.text = "\(sizeOfFile) MB \u{2022} TXT"
-                        }else {
-                            messageText.text = "\(sizeOfFile) MB \u{2022} \(finalExtFile.uppercased())"
+                        messageText.text = ""
+                    }
+                }
+                else if FileEncryption.shared.isSecureExists(filename: fileChat) {
+                    if let dataFile = try? FileEncryption.shared.readSecure(filename: fileChat) {
+                        var sizeOfFile = Int(dataFile.count / 1000000)
+                        if (sizeOfFile < 1) {
+                            sizeOfFile = Int(dataFile.count / 1000)
+                            if (finalExtFile.count > 4) {
+                                messageText.text = "\(sizeOfFile) kB \u{2022} TXT"
+                            }else {
+                                messageText.text = "\(sizeOfFile) kB \u{2022} \(finalExtFile.uppercased())"
+                            }
+                        } else {
+                            if (finalExtFile.count > 4) {
+                                messageText.text = "\(sizeOfFile) MB \u{2022} TXT"
+                            }else {
+                                messageText.text = "\(sizeOfFile) MB \u{2022} \(finalExtFile.uppercased())"
+                            }
                         }
+                    } else {
+                        messageText.text = ""
                     }
-                } else {
-                    messageText.text = ""
                 }
             }
             
@@ -989,13 +1012,13 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
                             let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["video_id"] as! String)
                             let fileURL = URL(fileURLWithPath: dirPath).appendingPathComponent(row["file_id"] as! String)
                             if ((row["video_id"] as! String) != "") {
-                                if FileManager.default.fileExists(atPath: videoURL.path){
+                                if FileManager.default.fileExists(atPath: videoURL.path) || FileEncryption.shared.isSecureExists(filename: videoURL.lastPathComponent){
                                     row["progress"] = 100.0
                                 } else {
                                     row["progress"] = 0.0
                                 }
                             } else {
-                                if FileManager.default.fileExists(atPath: fileURL.path){
+                                if FileManager.default.fileExists(atPath: fileURL.path) || FileEncryption.shared.isSecureExists(filename: fileURL.lastPathComponent){
                                     row["progress"] = 100.0
                                 } else {
                                     row["progress"] = 0.0
@@ -1074,6 +1097,20 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
                     previewImageVC.modalPresentationStyle = .custom
                     previewImageVC.modalTransitionStyle  = .crossDissolve
                     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)
+                    }
+                    catch {
+                        print("Error reading secure file")
+                    }
                 } else {
                     for view in sender.imageView.subviews {
                         if view is UIImageView {
@@ -1092,11 +1129,32 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
                             return
                         }
                         
-                        let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent(sender.image_id)
-                        let image    = UIImage(contentsOfFile: imageURL.path)
-                        let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
-                        if save {
-                            UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
+                        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)
+                            if let dirPath = paths.first {
+                                let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent(sender.image_id)
+                                if FileManager.default.fileExists(atPath: imageURL.path) {
+                                    let image    = UIImage(contentsOfFile: imageURL.path)
+                                    let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
+                                    if save {
+                                        UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
+                                    }
+                                }
+                                else if FileEncryption.shared.isSecureExists(filename: secureName) {
+                                    if let secureData = try FileEncryption.shared.readSecure(filename: secureName) {
+                                        let image = UIImage(data: secureData)
+                                        let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
+                                        if save {
+                                            UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
+                                        }
+                                    }
+                                }
+                            }
+                        } catch {
+                            
                         }
                         
                         DispatchQueue.main.async {
@@ -1115,6 +1173,21 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
                     playerVC.modalPresentationStyle = .custom
                     playerVC.player = player
                     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) {
+                            let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
+                            let tempPath = cachesDirectory.appendingPathComponent(sender.video_id)
+                            try secureData.write(to: tempPath)
+                            let player = AVPlayer(url: tempPath as URL)
+                            let playerVC = AVPlayerViewController()
+                            playerVC.modalPresentationStyle = .custom
+                            playerVC.player = player
+                            self.present(playerVC, animated: true, completion: nil)
+                        }
+                    } catch {
+                        
+                    }
                 } else {
                     for view in sender.imageView.subviews {
                         if view is UIImageView {
@@ -1157,14 +1230,33 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
                                 shapeLoading.strokeEnd = CGFloat(progress / 100)
                                 return
                             }
-                            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
-                                    
+                            do {
+                                if let secureName = try FileEncryption.shared.writeSecure(filename: name)?[0] as? String {
+                                    let secureData = try FileEncryption.shared.readSecure(filename: secureName)
+                                    let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
+                                    let tempPath = cachesDirectory.appendingPathComponent(name)
+                                    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
+                                            
+                                        }
+                                    }
                                 }
+                            } catch {
+                                
                             }
                             let idx = self.dataMessages.firstIndex(where: { $0["video_id"] as! String == sender.video_id})
                             if idx != nil {
@@ -1187,6 +1279,25 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
                     previewController.modalPresentationStyle = .custom
                     
                     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) {
+                            
+                            let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
+                            let tempPath = cachesDirectory.appendingPathComponent(sender.file_id)
+                            try docData.write(to: tempPath)
+                            self.previewItem = tempPath as NSURL
+                            let previewController = QLPreviewController()
+                            let rightBarButton = UIBarButtonItem()
+                            previewController.navigationItem.rightBarButtonItem = rightBarButton
+                            previewController.dataSource = self
+                            previewController.modalPresentationStyle = .custom
+                        }
+                    } catch {
+                        
+                    }
+                    
+                    
                 } else {
                     for view in sender.containerFile.subviews {
                         if !(view is UIImageView) && !(view is UILabel) {
@@ -1227,6 +1338,11 @@ 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,6 +1531,17 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
                             let image    = UIImage(contentsOfFile: imageURL.path)
                             UIPasteboard.general.image = image
                             self.showToast(message: "Image coppied to clipboard".localized(), font: UIFont.systemFont(ofSize: 12, weight: .medium), controller: self)
+                        } else if FileEncryption.shared.isSecureExists(filename: imageURL.lastPathComponent) {
+                            do {
+                                if let imageData = try FileEncryption.shared.readSecure(filename: imageURL.lastPathComponent) {
+                                    let image    = UIImage(data: imageData)
+                                    UIPasteboard.general.image = image
+                                    self.showToast(message: "Image coppied to clipboard".localized(), seconds: 1)
+                                }
+                            } catch {
+                                
+                            }
+                            
                         }
                     }
                 }
@@ -1461,6 +1588,17 @@ public class EditorStarMessages: UIViewController, UITableViewDataSource, UITabl
                                     let image    = UIImage(contentsOfFile: imageURL.path)
                                     UIPasteboard.general.image = image
                                     self.showToast(message: "Image coppied to clipboard".localized(), font: UIFont.systemFont(ofSize: 12, weight: .medium), controller: self)
+                                } else if FileEncryption.shared.isSecureExists(filename: imageURL.lastPathComponent) {
+                                    do {
+                                        if let imageData = try FileEncryption.shared.readSecure(filename: imageURL.lastPathComponent) {
+                                            let image    = UIImage(data: imageData)
+                                            UIPasteboard.general.image = image
+                                            self.showToast(message: "Image coppied to clipboard".localized(), font: UIFont.systemFont(ofSize: 12, weight: .medium), controller: self)
+                                        }
+                                    } catch {
+                                        
+                                    }
+                                    
                                 }
                             }
                         }

+ 61 - 17
NexilisLite/NexilisLite/Source/View/Chat/ListGroupImages.swift

@@ -142,12 +142,20 @@ class ListGroupImages: UIViewController, UITableViewDataSource, UITableViewDeleg
             let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent(imageId)
             DispatchQueue.main.async {
                 let image : UIImage? =  {
-                    if let img = Nexilis.imageCache.object(forKey: imageId as NSString) {
-                        return img
-                    }
-                    else if let img = UIImage(contentsOfFile: imageURL.path)?.resize(target: CGSize(width: 1000, height: 1000)) {
+                    do {
+                        if let img = Nexilis.imageCache.object(forKey: imageId as NSString) {
+                            return img
+                        }
+                        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) {
+                            let img = UIImage(data: imgData)?.resize(target: CGSize(width: 1000, height: 1000))
+                            Nexilis.imageCache.setObject(img!, forKey: imageId as NSString)
+                            return img
+                        }
+                    } catch {
+                        
                     }
                     return nil
                 }()
@@ -168,7 +176,7 @@ class ListGroupImages: UIViewController, UITableViewDataSource, UITableViewDeleg
                     containerImages.image = image
                 }
             }
-            if !FileManager.default.fileExists(atPath: imageURL.path) {
+            if !FileManager.default.fileExists(atPath: imageURL.path) && !FileEncryption.shared.isSecureExists(filename: imageURL.lastPathComponent) {
                 let blurEffect = UIBlurEffect(style: UIBlurEffect.Style.light)
                 let blurEffectView = UIVisualEffectView(effect: blurEffect)
                 blurEffectView.frame = CGRect(x: 0, y: 0, width: containerImages.frame.size.width, height: containerImages.frame.size.height)
@@ -341,17 +349,34 @@ class ListGroupImages: UIViewController, UITableViewDataSource, UITableViewDeleg
             if let dirPath = paths.first {
                 let imageId = listGroupingImages[indexPath.row].imageId
                 let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent(imageId)
-                if !FileManager.default.fileExists(atPath: imageURL.path) {
+                if !FileManager.default.fileExists(atPath: imageURL.path) && !FileEncryption.shared.isSecureExists(filename: imageURL.lastPathComponent) {
                     Download().startHTTP(forKey: listGroupingImages[indexPath.row].imageId) { (name, progress) in
                         guard progress == 100 else {
                             return
                         }
                         
-                        let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent(self.listGroupingImages[indexPath.row].imageId)
-                        let image    = UIImage(contentsOfFile: imageURL.path)
-                        let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
-                        if save {
-                            UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
+                        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)
+                                let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
+                                if save {
+                                    UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
+                                }
+                            }
+                            else if FileEncryption.shared.isSecureExists(filename: secureName){
+                                if let imageData = try FileEncryption.shared.readSecure(filename: secureName) {
+                                    let image    = UIImage(data: imageData)
+                                    let save: Bool = SecureUserDefaults.shared.value(forKey: "saveToGallery") ?? false
+                                    if save {
+                                        UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
+                                    }
+                                }
+                            }
+                        } catch {
+                            
                         }
                         
                         DispatchQueue.main.async { [self] in
@@ -627,14 +652,33 @@ class ListGroupImages: UIViewController, UITableViewDataSource, UITableViewDeleg
         let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
         if let dirPath = paths.first {
             let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent(image)
-            var imagePath = UIImage(contentsOfFile: imageURL.path)
-            if imagePath == nil {
-                Download().startHTTP(forKey: image) { (name, progress) in
-                    guard progress == 100 else {
-                        return
+            var imagePath : UIImage?
+            do {
+                if FileManager.default.fileExists(atPath: imageURL.path) {
+                    imagePath = UIImage(contentsOfFile: imageURL.path)
+                }
+                else if FileEncryption.shared.isSecureExists(filename: image) {
+                    if let imageData = try FileEncryption.shared.readSecure(filename: image) {
+                        imagePath = UIImage(data: imageData)
                     }
                 }
-                imagePath = UIImage(named: "Send-Image", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)
+                if imagePath == nil {
+                    Download().startHTTP(forKey: image) { (name, progress) in
+                        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)
+                }
+            }
+            catch {
+                
             }
             let imageWidth = imagePath!.size.width
             let imageHeight = imagePath!.size.height

+ 38 - 15
NexilisLite/NexilisLite/Source/View/Chat/MessageInfo.swift

@@ -713,7 +713,7 @@ class MessageInfo: UIViewController, UITableViewDelegate, UITableViewDataSource
                     
                     let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(videoChat)
                     let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent(imageChat)
-                    if !FileManager.default.fileExists(atPath: imageURL.path) || !FileManager.default.fileExists(atPath: videoURL.path) {
+                    if !FileManager.default.fileExists(atPath: imageURL.path) && !FileManager.default.fileExists(atPath: videoURL.path) && !FileEncryption.shared.isSecureExists(filename: imageURL.lastPathComponent) && !FileEncryption.shared.isSecureExists(filename: videoURL.lastPathComponent) {
                         let blurEffect = UIBlurEffect(style: UIBlurEffect.Style.light)
                         let blurEffectView = UIVisualEffectView(effect: blurEffect)
                         blurEffectView.frame = CGRect(x: 0, y: 0, width: imageThumb.frame.size.width, height: imageThumb.frame.size.height)
@@ -786,24 +786,47 @@ class MessageInfo: UIViewController, UITableViewDelegate, UITableViewDataSource
                 let finalExtFile = arrExtFile[arrExtFile.count - 1]
                 if let dirPath = paths.first {
                     let fileURL = URL(fileURLWithPath: dirPath).appendingPathComponent(fileChat)
-                    if let dataFile = try? Data(contentsOf: fileURL) {
-                        var sizeOfFile = Int(dataFile.count / 1000000)
-                        if (sizeOfFile < 1) {
-                            sizeOfFile = Int(dataFile.count / 1000)
-                            if (finalExtFile.count > 4) {
-                                messageText.text = "\(sizeOfFile) kB \u{2022} TXT"
-                            }else {
-                                messageText.text = "\(sizeOfFile) kB \u{2022} \(finalExtFile.uppercased())"
+                    if FileManager.default.fileExists(atPath: fileURL.path) {
+                        if let dataFile = try? Data(contentsOf: fileURL) {
+                            var sizeOfFile = Int(dataFile.count / 1000000)
+                            if (sizeOfFile < 1) {
+                                sizeOfFile = Int(dataFile.count / 1000)
+                                if (finalExtFile.count > 4) {
+                                    messageText.text = "\(sizeOfFile) kB \u{2022} TXT"
+                                }else {
+                                    messageText.text = "\(sizeOfFile) kB \u{2022} \(finalExtFile.uppercased())"
+                                }
+                            } else {
+                                if (finalExtFile.count > 4) {
+                                    messageText.text = "\(sizeOfFile) MB \u{2022} TXT"
+                                }else {
+                                    messageText.text = "\(sizeOfFile) MB \u{2022} \(finalExtFile.uppercased())"
+                                }
                             }
                         } else {
-                            if (finalExtFile.count > 4) {
-                                messageText.text = "\(sizeOfFile) MB \u{2022} TXT"
-                            }else {
-                                messageText.text = "\(sizeOfFile) MB \u{2022} \(finalExtFile.uppercased())"
+                            messageText.text = ""
+                        }
+                    }
+                    else if FileEncryption.shared.isSecureExists(filename: fileChat) {
+                        if let dataFile = try? FileEncryption.shared.readSecure(filename: fileChat) {
+                            var sizeOfFile = Int(dataFile.count / 1000000)
+                            if (sizeOfFile < 1) {
+                                sizeOfFile = Int(dataFile.count / 1000)
+                                if (finalExtFile.count > 4) {
+                                    messageText.text = "\(sizeOfFile) kB \u{2022} TXT"
+                                }else {
+                                    messageText.text = "\(sizeOfFile) kB \u{2022} \(finalExtFile.uppercased())"
+                                }
+                            } else {
+                                if (finalExtFile.count > 4) {
+                                    messageText.text = "\(sizeOfFile) MB \u{2022} TXT"
+                                }else {
+                                    messageText.text = "\(sizeOfFile) MB \u{2022} \(finalExtFile.uppercased())"
+                                }
                             }
+                        } else {
+                            messageText.text = ""
                         }
-                    } else {
-                        messageText.text = ""
                     }
                 }
                 

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

@@ -416,6 +416,11 @@ class BroadcastViewController: UITableViewController, UITextFieldDelegate, UITex
                             if result2 {
                                 if progress == 100 {
                                     self.sendMsg(startTime: startTime, endTime: endTime)
+                                    do {
+                                        try FileEncryption.shared.writeSecure(filename: self.fileId)
+                                    } catch {
+                                        
+                                    }
                                 }
                             }
                         }
@@ -427,6 +432,11 @@ class BroadcastViewController: UITableViewController, UITextFieldDelegate, UITex
                 if result2 {
                     if progress == 100 {
                         self.sendMsg(startTime: startTime, endTime: endTime)
+                        do {
+                            try FileEncryption.shared.writeSecure(filename: self.fileId)
+                        } catch {
+                            
+                        }
                     }
                 }
             }

部分文件因为文件数量过多而无法显示