Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3393391
D10502.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
15 KB
Referenced Files
None
Subscribers
None
D10502.diff
View Options
diff --git a/native/android/app/CMakeLists.txt b/native/android/app/CMakeLists.txt
--- a/native/android/app/CMakeLists.txt
+++ b/native/android/app/CMakeLists.txt
@@ -130,6 +130,7 @@
"../../native_rust_library/RustAESCrypto.cpp"
"../../native_rust_library/RustCSAMetadataEmitter.cpp"
"../../native_rust_library/RustSecureStore.cpp"
+ "../../native_rust_library/RustBackupExecutor.cpp"
)
file(GLOB CRYPTO_NATIVE_CODE "../../cpp/CommonCpp/CryptoTools/*.cpp")
file(GLOB DB_NATIVE_CODE "../../cpp/CommonCpp/DatabaseManagers/*.cpp")
diff --git a/native/android/app/src/cpp/PlatformSpecificTools.cpp b/native/android/app/src/cpp/PlatformSpecificTools.cpp
--- a/native/android/app/src/cpp/PlatformSpecificTools.cpp
+++ b/native/android/app/src/cpp/PlatformSpecificTools.cpp
@@ -31,6 +31,27 @@
cls->getStaticMethod<JString()>("getNotificationsCryptoAccountPath");
return method(cls)->toStdString();
}
+
+ static std::string getBackupDirectoryPath() {
+ static const auto cls = javaClassStatic();
+ static auto method =
+ cls->getStaticMethod<JString()>("getBackupDirectoryPath");
+ return method(cls)->toStdString();
+ }
+
+ static std::string
+ getBackupFilePath(std::string backupID, bool isAttachments) {
+ static const auto cls = javaClassStatic();
+ static auto method =
+ cls->getStaticMethod<JString(std::string, bool)>("getBackupFilePath");
+ return method(cls, backupID, isAttachments)->toStdString();
+ }
+
+ static void removeBackupDirectory() {
+ static const auto cls = javaClassStatic();
+ static auto method = cls->getStaticMethod<void()>("removeBackupDirectory");
+ method(cls);
+ }
};
namespace comm {
@@ -55,4 +76,28 @@
return path;
}
+std::string PlatformSpecificTools::getBackupDirectoryPath() {
+ std::string path;
+ NativeAndroidAccessProvider::runTask([&path]() {
+ path = PlatformSpecificToolsJavaClass::getBackupDirectoryPath();
+ });
+ return path;
+}
+
+std::string PlatformSpecificTools::getBackupFilePath(
+ std::string backupID,
+ bool isAttachments) {
+ std::string path;
+ NativeAndroidAccessProvider::runTask([&path, backupID, isAttachments]() {
+ path = PlatformSpecificToolsJavaClass::getBackupFilePath(
+ backupID, isAttachments);
+ });
+ return path;
+}
+
+void PlatformSpecificTools::removeBackupDirectory() {
+ NativeAndroidAccessProvider::runTask(
+ []() { PlatformSpecificToolsJavaClass::removeBackupDirectory(); });
+}
+
} // namespace comm
diff --git a/native/android/app/src/main/java/app/comm/android/fbjni/PlatformSpecificTools.java b/native/android/app/src/main/java/app/comm/android/fbjni/PlatformSpecificTools.java
--- a/native/android/app/src/main/java/app/comm/android/fbjni/PlatformSpecificTools.java
+++ b/native/android/app/src/main/java/app/comm/android/fbjni/PlatformSpecificTools.java
@@ -3,9 +3,12 @@
import android.content.Context;
import android.util.Log;
import app.comm.android.MainApplication;
+import java.io.File;
+import java.lang.SecurityException;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
+
public class PlatformSpecificTools {
static SecureRandom secureRandom = new SecureRandom();
@@ -26,4 +29,73 @@
.getFileStreamPath("comm_notifications_crypto_account")
.getPath();
}
+
+ public static String getBackupDirectoryPath() {
+ Context mainApplicationContext =
+ MainApplication.getMainApplicationContext();
+ if (mainApplicationContext == null) {
+ throw new RuntimeException(
+ "Failed to resolve backup path - main application context not initialized.");
+ }
+
+ String filesDirPath = mainApplicationContext.getFilesDir().getPath();
+ String backupDirPath = String.join(File.separator, filesDirPath, "backup");
+
+ try {
+ File backupDirectory = new File(backupDirPath);
+ if (!backupDirectory.exists() && !backupDirectory.mkdirs()) {
+ throw new RuntimeException("Failed to create backup directory.");
+ }
+ return backupDirPath;
+ } catch (SecurityException | NullPointerException e) {
+ throw new RuntimeException(
+ "Failed to check if backup directory exists or to attempt its creation. Details: " +
+ e.getMessage());
+ }
+ }
+
+ public static String
+ getBackupFilePath(String backupID, boolean isAttachments) {
+ String backupDirPath = PlatformSpecificTools.getBackupDirectoryPath();
+
+ String filename;
+ if (isAttachments) {
+ filename = String.join("_", "backup", backupID, "attachments");
+ } else {
+ filename = String.join("_", "backup", backupID);
+ }
+ return String.join(File.separator, backupDirPath, filename);
+ }
+
+ public static void removeBackupDirectory() {
+ String backupDirPath = PlatformSpecificTools.getBackupDirectoryPath();
+ try {
+ File backupDirectory = new File(backupDirPath);
+ if (!backupDirectory.exists()) {
+ return;
+ }
+
+ File[] files = backupDirectory.listFiles();
+ if (files == null && !backupDirectory.delete()) {
+ throw new RuntimeException("Failed to remove backup directory.");
+ } else if (files == null) {
+ return;
+ }
+
+ // Backup directory structure is supposed to be flat.
+ for (File file : files) {
+ if (!file.delete()) {
+ throw new RuntimeException(
+ "Failed to remove backup file at path: " + file.getPath());
+ }
+ }
+
+ if (!backupDirectory.delete()) {
+ throw new RuntimeException("Failed to remove backup directory.");
+ }
+ } catch (NullPointerException | SecurityException e) {
+ throw new RuntimeException(
+ "Failed to remove backup directory. Details: " + e.getMessage());
+ }
+ }
}
diff --git a/native/cpp/CommonCpp/DatabaseManagers/DatabaseManager.cpp b/native/cpp/CommonCpp/DatabaseManagers/DatabaseManager.cpp
--- a/native/cpp/CommonCpp/DatabaseManagers/DatabaseManager.cpp
+++ b/native/cpp/CommonCpp/DatabaseManagers/DatabaseManager.cpp
@@ -2,6 +2,7 @@
#include "../Notifications/BackgroundDataStorage/NotificationsCryptoModule.h"
#include "../Tools/CommSecureStore.h"
#include "Logger.h"
+#include "PlatformSpecificTools.h"
#include "SQLiteQueryExecutor.h"
namespace comm {
@@ -34,6 +35,7 @@
CommSecureStore::set(CommSecureStore::deviceID, "");
CommSecureStore::set(CommSecureStore::commServicesAccessToken, "");
SQLiteQueryExecutor::clearSensitiveData();
+ PlatformSpecificTools::removeBackupDirectory();
NotificationsCryptoModule::clearSensitiveData();
DatabaseManager::setDatabaseStatusAsWorkable();
}
diff --git a/native/cpp/CommonCpp/Tools/PlatformSpecificTools.h b/native/cpp/CommonCpp/Tools/PlatformSpecificTools.h
--- a/native/cpp/CommonCpp/Tools/PlatformSpecificTools.h
+++ b/native/cpp/CommonCpp/Tools/PlatformSpecificTools.h
@@ -9,6 +9,10 @@
static void generateSecureRandomBytes(crypto::OlmBuffer &buffer, size_t size);
static std::string getDeviceOS();
static std::string getNotificationsCryptoAccountPath();
+ static std::string getBackupDirectoryPath();
+ static std::string
+ getBackupFilePath(std::string backupID, bool isAttachments);
+ static void removeBackupDirectory();
};
} // namespace comm
diff --git a/native/ios/Comm.xcodeproj/project.pbxproj b/native/ios/Comm.xcodeproj/project.pbxproj
--- a/native/ios/Comm.xcodeproj/project.pbxproj
+++ b/native/ios/Comm.xcodeproj/project.pbxproj
@@ -81,6 +81,7 @@
CBCA09062A8E0E7400F75B3E /* StaffUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CBCA09052A8E0E6B00F75B3E /* StaffUtils.cpp */; };
CBCA09072A8E0E7D00F75B3E /* StaffUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CBCA09052A8E0E6B00F75B3E /* StaffUtils.cpp */; };
CBDEC69B28ED867000C17588 /* GlobalDBSingleton.mm in Sources */ = {isa = PBXBuildFile; fileRef = CBDEC69A28ED867000C17588 /* GlobalDBSingleton.mm */; };
+ CBFBEEBA2B4ED90600729F1D /* RustBackupExecutor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CBFBEEB82B4ED90600729F1D /* RustBackupExecutor.cpp */; };
CBFE58292885852B003B94C9 /* ThreadOperations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CBFE58282885852B003B94C9 /* ThreadOperations.cpp */; };
D7DB6E0F85B2DBE15B01EC21 /* libPods-Comm.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 994BEBDD4E4959F69CEA0BC3 /* libPods-Comm.a */; };
DFD5E77C2B05181400C32B6A /* RustSecureStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFD5E77B2B05181400C32B6A /* RustSecureStore.cpp */; };
@@ -277,6 +278,8 @@
CBCF57AB2B05096F00EC4BC0 /* AESCryptoModuleObjCCompat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AESCryptoModuleObjCCompat.h; path = Comm/CommAESCryptoUtils/AESCryptoModuleObjCCompat.h; sourceTree = "<group>"; };
CBDEC69928ED859600C17588 /* GlobalDBSingleton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GlobalDBSingleton.h; sourceTree = "<group>"; };
CBDEC69A28ED867000C17588 /* GlobalDBSingleton.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = GlobalDBSingleton.mm; path = Comm/GlobalDBSingleton.mm; sourceTree = "<group>"; };
+ CBFBEEB82B4ED90600729F1D /* RustBackupExecutor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RustBackupExecutor.cpp; sourceTree = "<group>"; };
+ CBFBEEB92B4ED90600729F1D /* RustBackupExecutor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RustBackupExecutor.h; sourceTree = "<group>"; };
CBFE58272885852B003B94C9 /* ThreadOperations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadOperations.h; path = PersistentStorageUtilities/ThreadOperationsUtilities/ThreadOperations.h; sourceTree = "<group>"; };
CBFE58282885852B003B94C9 /* ThreadOperations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadOperations.cpp; path = PersistentStorageUtilities/ThreadOperationsUtilities/ThreadOperations.cpp; sourceTree = "<group>"; };
DFD5E77A2B05181400C32B6A /* RustSecureStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RustSecureStore.h; sourceTree = "<group>"; };
@@ -593,6 +596,8 @@
8B99AF6B28D50D4800EB5ADB /* native_rust_library */ = {
isa = PBXGroup;
children = (
+ CBFBEEB82B4ED90600729F1D /* RustBackupExecutor.cpp */,
+ CBFBEEB92B4ED90600729F1D /* RustBackupExecutor.h */,
CB74AB1E2B2B0C0900CBB494 /* RustCSAMetadataEmitter.cpp */,
CB74AB1F2B2B0C0900CBB494 /* RustCSAMetadataEmitter.h */,
DFD5E7842B052B1400C32B6A /* RustAESCrypto.cpp */,
@@ -1094,6 +1099,7 @@
CBFE58292885852B003B94C9 /* ThreadOperations.cpp in Sources */,
CB74AB1C2B2AFF6E00CBB494 /* CommServicesAuthMetadataEmitter.mm in Sources */,
8E3994552B039A7C00D5E950 /* UserStore.cpp in Sources */,
+ CBFBEEBA2B4ED90600729F1D /* RustBackupExecutor.cpp in Sources */,
7FBB2A7829E945C2002C6493 /* CommUtilsModule.cpp in Sources */,
CB38B48228771C7A00171182 /* NonBlockingLock.mm in Sources */,
718DE99E2653D41C00365824 /* WorkerThread.cpp in Sources */,
diff --git a/native/ios/Comm/PlatformSpecificTools.mm b/native/ios/Comm/PlatformSpecificTools.mm
--- a/native/ios/Comm/PlatformSpecificTools.mm
+++ b/native/ios/Comm/PlatformSpecificTools.mm
@@ -37,4 +37,74 @@
.path UTF8String]);
}
+NSURL *getBackupDirAsURL() {
+ NSError *err = nil;
+ NSURL *documentsUrl =
+ [NSFileManager.defaultManager URLForDirectory:NSDocumentDirectory
+ inDomain:NSUserDomainMask
+ appropriateForURL:nil
+ create:false
+ error:&err];
+ if (err) {
+ NSLog(@"Error: %@", err);
+ throw std::runtime_error(
+ "Failed to resolve backup path - could not find documentsUrl. "
+ "Details: " +
+ std::string([err.localizedDescription UTF8String]));
+ }
+
+ NSURL *backupDir = [documentsUrl URLByAppendingPathComponent:@"backup"];
+ NSError *backupDirCreateError = nil;
+ if (![NSFileManager.defaultManager fileExistsAtPath:backupDir.path]) {
+ [NSFileManager.defaultManager createDirectoryAtURL:backupDir
+ withIntermediateDirectories:YES
+ attributes:nil
+ error:&backupDirCreateError];
+ }
+ if (backupDirCreateError) {
+ throw std::runtime_error(
+ "Failed to create backup directory. Details: " +
+ std::string([backupDirCreateError.localizedDescription UTF8String]));
+ }
+ return backupDir;
+}
+
+std::string PlatformSpecificTools::getBackupDirectoryPath() {
+ return [getBackupDirAsURL().path UTF8String];
+}
+
+std::string PlatformSpecificTools::getBackupFilePath(
+ std::string backupID,
+ bool isAttachments) {
+
+ NSURL *backupDir = getBackupDirAsURL();
+ NSString *backupIDObjC = [NSString stringWithCString:backupID.c_str()
+ encoding:NSUTF8StringEncoding];
+ NSString *filename;
+ if (isAttachments) {
+ filename = [@[ @"backup", backupIDObjC, @"attachments" ]
+ componentsJoinedByString:@"_"];
+ } else {
+ filename = [@[ @"backup", backupIDObjC ] componentsJoinedByString:@"_"];
+ }
+ return [[backupDir URLByAppendingPathComponent:filename].path UTF8String];
+}
+
+void PlatformSpecificTools::removeBackupDirectory() {
+ NSURL *backupDir = getBackupDirAsURL();
+ if (![NSFileManager.defaultManager fileExistsAtPath:backupDir.path]) {
+ return;
+ }
+
+ NSError *backupDirRemovalError = nil;
+ [NSFileManager.defaultManager removeItemAtURL:backupDir
+ error:&backupDirRemovalError];
+
+ if (backupDirRemovalError) {
+ throw std::runtime_error(
+ "Failed to remove backup directory. Details: " +
+ std::string([backupDirRemovalError.localizedDescription UTF8String]));
+ }
+}
+
}; // namespace comm
diff --git a/native/native_rust_library/RustBackupExecutor.h b/native/native_rust_library/RustBackupExecutor.h
new file mode 100644
--- /dev/null
+++ b/native/native_rust_library/RustBackupExecutor.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#include "cxx.h"
+
+namespace comm {
+
+rust::String getBackupDirectoryPath();
+rust::String getBackupFilePath(rust::String backupID, bool isAttachments);
+
+} // namespace comm
diff --git a/native/native_rust_library/RustBackupExecutor.cpp b/native/native_rust_library/RustBackupExecutor.cpp
new file mode 100644
--- /dev/null
+++ b/native/native_rust_library/RustBackupExecutor.cpp
@@ -0,0 +1,16 @@
+#include "RustBackupExecutor.h"
+#include "../cpp/CommonCpp/Tools/PlatformSpecificTools.h"
+
+#include <string>
+
+namespace comm {
+
+rust::String getBackupDirectoryPath() {
+ return rust::String(PlatformSpecificTools::getBackupDirectoryPath());
+}
+
+rust::String getBackupFilePath(rust::String backupID, bool isAttachments) {
+ return rust::String(PlatformSpecificTools::getBackupFilePath(
+ std::string(backupID), isAttachments));
+}
+} // namespace comm
diff --git a/native/native_rust_library/src/lib.rs b/native/native_rust_library/src/lib.rs
--- a/native/native_rust_library/src/lib.rs
+++ b/native/native_rust_library/src/lib.rs
@@ -244,6 +244,23 @@
#[cxx_name = "secureStoreGet"]
fn secure_store_get(key: &str) -> Result<String>;
}
+
+ // C++ Backup creation
+ #[namespace = "comm"]
+ unsafe extern "C++" {
+ include!("RustBackupExecutor.h");
+
+ #[allow(unused)]
+ #[cxx_name = "getBackupDirectoryPath"]
+ fn get_backup_directory_path() -> Result<String>;
+
+ #[allow(unused)]
+ #[cxx_name = "getBackupFilePath"]
+ fn get_backup_file_path(
+ backup_id: String,
+ is_attachments: bool,
+ ) -> Result<String>;
+ }
}
fn handle_string_result_as_callback<E>(
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Dec 1, 1:37 PM (20 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2605131
Default Alt Text
D10502.diff (15 KB)
Attached To
Mode
D10502: Implement tools to manage backup files
Attached
Detach File
Event Timeline
Log In to Comment