diff --git a/native/android/app/CMakeLists.txt b/native/android/app/CMakeLists.txt index 5596c18c0..9fbfc6156 100644 --- a/native/android/app/CMakeLists.txt +++ b/native/android/app/CMakeLists.txt @@ -1,243 +1,245 @@ # For more information about using CMake with Android Studio, read the # documentation: https://d.android.com/studio/projects/add-native-code.html project(comm CXX C) set(CMAKE_CXX_STANDARD 17) # C0103 is a naming convention, but the variable names which need to be set # are determined by the upstream project # cmake-lint: disable=C0103 # Disable line length as some paths are hard to reduce without becoming cryptic # cmake-lint: disable=C0301 # Sets the minimum version of CMake required to build the native library. cmake_minimum_required(VERSION 3.18) # Creates and names a library, sets it as either STATIC # or SHARED, and provides the relative paths to its source code. # You can define multiple libraries, and CMake builds them for you. # Gradle automatically packages shared libraries with your APK. set(PACKAGE_NAME "comm_jni_module") find_library(log-lib log) find_package(fbjni REQUIRED CONFIG) set(BUILD_TESTING OFF) set(HAVE_SYMBOLIZE OFF) set(WITH_GTEST OFF CACHE BOOL "Use googletest" FORCE) set(WITH_GFLAGS OFF CACHE BOOL "Use gflags" FORCE) # General set(_third_party_dir ${CMAKE_CURRENT_SOURCE_DIR}/build/third-party-ndk) set(_android_build_dir build/${CMAKE_ANDROID_ARCH_ABI}) include(FetchContent) if(CMAKE_ANDROID_ARCH_ABI STREQUAL arm64-v8a) set(Rust_CARGO_TARGET aarch64-linux-android) elseif(CMAKE_ANDROID_ARCH_ABI STREQUAL x86_64) set(Rust_CARGO_TARGET x86_64-linux-android) elseif(CMAKE_ANDROID_ARCH_ABI STREQUAL armeabi-v7a) set(Rust_CARGO_TARGET armv7-linux-androideabi) endif() string(TOLOWER ${CMAKE_HOST_SYSTEM_NAME} CMAKE_HOST_SYSTEM_NAME_LOWER) set(_toolchain_path "$ENV{ANDROID_HOME}/ndk/${NDK_VERSION}/toolchains/llvm/prebuilt/${CMAKE_HOST_SYSTEM_NAME_LOWER}-x86_64/bin" ) if(EXISTS "${_toolchain_path}/${Rust_CARGO_TARGET}-ar") set(AR "${_toolchain_path}/${Rust_CARGO_TARGET}-ar") else() set(AR "${_toolchain_path}/llvm-ar") endif() FetchContent_Declare( Corrosion GIT_REPOSITORY https://github.com/corrosion-rs/corrosion.git GIT_TAG v0.2.1 ) FetchContent_MakeAvailable(Corrosion) include(../../../shared/cmake/corrosion-cxx.cmake) add_library_rust(PATH ../../native_rust_library NAMESPACE comm) # We're updating parameters below for Cmake's find_OpenSSL() function set(OPENSSL_ROOT_DIR "${_third_party_dir}/openssl/openssl-${OPENSSL_VERSION}/${_android_build_dir}" ) list(APPEND CMAKE_FIND_ROOT_PATH "${OPENSSL_ROOT_DIR}") # Override HAVE_EXECINFO_H in glog's CMakeLists.txt if( CMAKE_ANDROID_ARCH_ABI STREQUAL arm64-v8a OR CMAKE_ANDROID_ARCH_ABI STREQUAL armeabi-v7a ) set(HAVE_EXECINFO_H OFF CACHE BOOL "Whether platform has execinfo.h") endif() add_subdirectory(${_third_party_dir}/glog/glog-${GLOG_VERSION}/) file(GLOB LIBRN_DIR "${REACT_NATIVE_SO_DIR}/${ANDROID_ABI}") if (NOT LIBRN_DIR) # If /${ANDROID_ABI} dir not found, then ${REACT_NATIVE_SO_DIR} is probably: # ReactAndroid/build/react-ndk/exported file(GLOB LIBRN_DIR "${REACT_NATIVE_SO_DIR}") endif () include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/folly-target.cmake) include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/openssl-target.cmake) add_subdirectory(../../node_modules/olm ./build) set(_node_modules_dir ${CMAKE_CURRENT_SOURCE_DIR}/../../node_modules) set(_react_native_dir ${_node_modules_dir}/react-native) add_subdirectory(../../cpp/CommonCpp/ ${CMAKE_CURRENT_BINARY_DIR}/build/CommonCpp EXCLUDE_FROM_ALL ) file(GLOB SQLCIPHER "${_node_modules_dir}/@commapp/sqlcipher-amalgamation/src/*.c" ) # Add files which aren't a part of comm-tools list(APPEND ANDROID_NATIVE_CODE "./src/cpp/CommSecureStore.cpp" "./src/cpp/DatabaseInitializerJNIHelper.cpp" "./src/cpp/GlobalDBSingleton.cpp" "./src/cpp/Logger.cpp" "./src/cpp/MessageOperationsUtilitiesJNIHelper.cpp" "./src/cpp/PlatformSpecificTools.cpp" "./src/cpp/TerminateApp.cpp" "./src/cpp/ThreadOperationsJNIHelper.cpp" "./src/cpp/jsiInstaller.cpp" "./src/cpp/NotificationsCryptoModuleJNIHelper.cpp" "./src/cpp/StaffUtilsJNIHelper.cpp" "./src/cpp/AESCrypto.cpp" "./src/cpp/CommServicesAuthMetadataEmitter.cpp" ) list(APPEND GENERATED_NATIVE_CODE "../../cpp/CommonCpp/_generated/commJSI-generated.cpp" "../../cpp/CommonCpp/_generated/utilsJSI-generated.cpp" "../../cpp/CommonCpp/_generated/rustJSI-generated.cpp" ) list(APPEND RUST_NATIVE_CODE "../../native_rust_library/RustCallback.cpp" "../../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") file(GLOB DB_ENTITIES_NATIVE_CODE "../../cpp/CommonCpp/DatabaseManagers/entities/*.cpp") file(GLOB_RECURSE MODULE_NATIVE_CODE "../../cpp/CommonCpp/NativeModules/**/*.cpp") file(GLOB MODULE_ROOT_NATIVE_CODE "../../cpp/CommonCpp/NativeModules/*.cpp") file(GLOB NOTIFICATIONS_NATIVE_CODE "../../cpp/CommonCpp/Notifications/**/*.cpp") add_library( # Sets the name of the library ${PACKAGE_NAME} # Sets the library as a shared library SHARED # React dependencies ${_react_native_dir}/ReactCommon/jsi/jsi/jsi.cpp ${_react_native_dir}/ReactCommon/jsi/jsi/JSIDynamic.cpp ${_react_native_dir}/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/ReactCommon/CallInvokerHolder.cpp ${_react_native_dir}/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.cpp ${_react_native_dir}/ReactCommon/react/bridging/LongLivedObject.cpp ${_react_native_dir}/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleUtils.cpp # Third party dependencies ${SQLCIPHER} # comm code ${ANDROID_NATIVE_CODE} ${GENERATED_NATIVE_CODE} ${CRYPTO_NATIVE_CODE} ${DB_NATIVE_CODE} ${DB_ENTITIES_NATIVE_CODE} ${MODULE_NATIVE_CODE} ${MODULE_ROOT_NATIVE_CODE} ${TOOLS_NATIVE_CODE} ${NOTIFICATIONS_NATIVE_CODE} ${RUST_NATIVE_CODE} ) set(BUILD_DIR ${CMAKE_SOURCE_DIR}/build) target_include_directories( ${PACKAGE_NAME} PRIVATE # React Native ${_react_native_dir}/React ${_react_native_dir}/React/Base ${_react_native_dir}/ReactCommon ${_react_native_dir}/ReactCommon/jsi ${_react_native_dir}/ReactCommon/callinvoker ${_react_native_dir}/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/ReactCommon # SQLCipher amalgamation ${_node_modules_dir}/@commapp/sqlcipher-amalgamation/src # symlinked React Native headers ../headers # comm android specific code ./src/cpp # comm native mutual code ../../cpp/CommonCpp/ ../../cpp/CommonCpp/NativeModules ../../cpp/CommonCpp/NativeModules/InternalModules ../../cpp/CommonCpp/NativeModules/PersistentStorageUtilities ../../cpp/CommonCpp/NativeModules/PersistentStorageUtilities/BackupOperationsUtilities ../../cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores ../../cpp/CommonCpp/NativeModules/PersistentStorageUtilities/ThreadOperationsUtilities ../../cpp/CommonCpp/NativeModules/PersistentStorageUtilities/MessageOperationsUtilities ../../cpp/CommonCpp/NativeModules/PersistentStorageUtilities/MessageOperationsUtilities/MessageSpecs ../../cpp/CommonCpp/DatabaseManagers ../../cpp/CommonCpp/Notifications ../../cpp/CommonCpp/Notifications/BackgroundDataStorage # native rust library ${native_rust_library_include_dir} ) add_definitions( # SQLCipher -DSQLITE_THREADSAFE=0 -DSQLITE_HAS_CODEC -DSQLITE_TEMP_STORE=2 -DSQLCIPHER_CRYPTO_OPENSSL + -DSQLITE_ENABLE_SESSION + -DSQLITE_ENABLE_PREUPDATE_HOOK ) target_link_libraries( ${PACKAGE_NAME} fbjni::fbjni android ${log-lib} Folly::folly glog::glog olm openssl-crypto openssl-ssl comm::native_rust_library comm-tools ) # add a dummy library which is required by CallInvokerHolderImpl.java add_library( turbomodulejsijni # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). ./src/cpp/dummy.cpp ) diff --git a/native/cpp/CommonCpp/DatabaseManagers/CMakeLists.txt b/native/cpp/CommonCpp/DatabaseManagers/CMakeLists.txt index a63f7477b..c572ef11e 100644 --- a/native/cpp/CommonCpp/DatabaseManagers/CMakeLists.txt +++ b/native/cpp/CommonCpp/DatabaseManagers/CMakeLists.txt @@ -1,47 +1,51 @@ project(comm-databasemanagers) cmake_minimum_required(VERSION 3.4) include(GNUInstallDirs) set(DBM_HDRS "DatabaseManager.h" "DatabaseQueryExecutor.h" "SQLiteQueryExecutor.h" + "SQLiteConnectionManager.h" + "NativeSQLiteConnectionManager.h" "entities/SQLiteStatementWrapper.h" "entities/EntityQueryHelpers.h" "entities/SQLiteDataConverters.h" "entities/Draft.h" "entities/Media.h" "entities/Message.h" "entities/Metadata.h" "entities/OlmPersistAccount.h" "entities/OlmPersistSession.h" "entities/Thread.h" ) set(DBM_SRCS "SQLiteQueryExecutor.cpp" + "SQLiteConnectionManager.cpp" + "NativeSQLiteConnectionManager.cpp" "entities/SQLiteDataConverters.cpp" "entities/SQLiteStatementWrapper.cpp" ) add_library(comm-databasemanagers ${DBM_HDRS} ${DBM_SRCS} ) target_include_directories(comm-databasemanagers PUBLIC $ $ $ $ PRIVATE # HACK "../../../node_modules/react-native/ReactCommon/jsi" "../../../node_modules/olm/include" ) target_link_libraries(comm-databasemanagers Folly::folly ) diff --git a/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h b/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h index e28ca4830..c438ff9e3 100644 --- a/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h +++ b/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h @@ -1,106 +1,107 @@ #pragma once #include "../CryptoTools/Persist.h" #include "entities/Draft.h" #include "entities/KeyserverInfo.h" #include "entities/Message.h" #include "entities/MessageStoreThread.h" #include "entities/OlmPersistAccount.h" #include "entities/OlmPersistSession.h" #include "entities/PersistItem.h" #include "entities/Report.h" #include "entities/Thread.h" #include "entities/UserInfo.h" #include namespace comm { /** * if any initialization/cleaning up steps are required for specific * database managers they should appear in constructors/destructors * following the RAII pattern */ class DatabaseQueryExecutor { public: virtual std::string getDraft(std::string key) const = 0; virtual std::unique_ptr getThread(std::string threadID) const = 0; virtual void updateDraft(std::string key, std::string text) const = 0; virtual bool moveDraft(std::string oldKey, std::string newKey) const = 0; virtual std::vector getAllDrafts() const = 0; virtual void removeAllDrafts() const = 0; virtual void removeDrafts(const std::vector &ids) const = 0; virtual void removeAllMessages() const = 0; virtual std::vector>> getAllMessages() const = 0; virtual void removeMessages(const std::vector &ids) const = 0; virtual void removeMessagesForThreads(const std::vector &threadIDs) const = 0; virtual void replaceMessage(const Message &message) const = 0; virtual void rekeyMessage(std::string from, std::string to) const = 0; virtual void removeAllMedia() const = 0; virtual void replaceMessageStoreThreads( const std::vector &threads) const = 0; virtual void removeMessageStoreThreads(const std::vector &ids) const = 0; virtual void removeAllMessageStoreThreads() const = 0; virtual std::vector getAllMessageStoreThreads() const = 0; virtual void removeMediaForMessages(const std::vector &msg_ids) const = 0; virtual void removeMediaForMessage(std::string msg_id) const = 0; virtual void removeMediaForThreads(const std::vector &thread_ids) const = 0; virtual void replaceMedia(const Media &media) const = 0; virtual void rekeyMediaContainers(std::string from, std::string to) const = 0; virtual std::vector getAllThreads() const = 0; virtual void removeThreads(std::vector ids) const = 0; virtual void replaceThread(const Thread &thread) const = 0; virtual void removeAllThreads() const = 0; virtual void replaceReport(const Report &report) const = 0; virtual void removeReports(const std::vector &ids) const = 0; virtual void removeAllReports() const = 0; virtual std::vector getAllReports() const = 0; virtual void setPersistStorageItem(std::string key, std::string item) const = 0; virtual void removePersistStorageItem(std::string key) const = 0; virtual std::string getPersistStorageItem(std::string key) const = 0; virtual void replaceUser(const UserInfo &user_info) const = 0; virtual void removeUsers(const std::vector &ids) const = 0; virtual void removeAllUsers() const = 0; virtual std::vector getAllUsers() const = 0; virtual void replaceKeyserver(const KeyserverInfo &keyserver_info) const = 0; virtual void removeKeyservers(const std::vector &ids) const = 0; virtual void removeAllKeyservers() const = 0; virtual std::vector getAllKeyservers() const = 0; virtual void beginTransaction() const = 0; virtual void commitTransaction() const = 0; virtual void rollbackTransaction() const = 0; virtual std::vector getOlmPersistSessionsData() const = 0; virtual std::optional getOlmPersistAccountData() const = 0; virtual void storeOlmPersistSession(const OlmPersistSession &session) const = 0; virtual void storeOlmPersistAccount(const std::string &accountData) const = 0; virtual void storeOlmPersistData(crypto::Persist persist) const = 0; virtual void setNotifyToken(std::string token) const = 0; virtual void clearNotifyToken() const = 0; virtual void setCurrentUserID(std::string userID) const = 0; virtual std::string getCurrentUserID() const = 0; virtual void setMetadata(std::string entry_name, std::string data) const = 0; virtual void clearMetadata(std::string entry_name) const = 0; virtual std::string getMetadata(std::string entry_name) const = 0; virtual void restoreFromMainCompaction( std::string mainCompactionPath, std::string mainCompactionEncryptionKey) const = 0; #ifdef EMSCRIPTEN virtual std::vector getAllThreadsWeb() const = 0; virtual void replaceThreadWeb(const WebThread &thread) const = 0; virtual std::vector getAllMessagesWeb() const = 0; virtual void replaceMessageWeb(const WebMessage &message) const = 0; virtual NullableString getOlmPersistAccountDataWeb() const = 0; #else virtual void createMainCompaction(std::string backupID) const = 0; + virtual void captureBackupLogs() const = 0; #endif }; } // namespace comm diff --git a/native/cpp/CommonCpp/DatabaseManagers/NativeSQLiteConnectionManager.cpp b/native/cpp/CommonCpp/DatabaseManagers/NativeSQLiteConnectionManager.cpp new file mode 100644 index 000000000..1ea5e13e9 --- /dev/null +++ b/native/cpp/CommonCpp/DatabaseManagers/NativeSQLiteConnectionManager.cpp @@ -0,0 +1,126 @@ +#include "NativeSQLiteConnectionManager.h" +#include "PlatformSpecificTools.h" + +#include +#include +#include +#include +#include + +namespace comm { + +void NativeSQLiteConnectionManager::attachSession() { + int sessionCreationResult = + sqlite3session_create(dbConnection, "main", &backupLogsSession); + handleSQLiteError(sessionCreationResult, "Failed to create sqlite3 session."); + + static const std::vector tablesToMonitor = { + "drafts", + "messages", + "media", + "threads", + "message_store_threads", + "reports", + "keyservers", + "users"}; + + for (const auto &table : tablesToMonitor) { + int sessionAttachResult = + sqlite3session_attach(backupLogsSession, table.c_str()); + handleSQLiteError( + sessionAttachResult, + "Failed to attach sqlite3 session to " + table + " table."); + } +} + +void NativeSQLiteConnectionManager::detachSession() { + if (!backupLogsSession) { + return; + } + sqlite3session_delete(backupLogsSession); + backupLogsSession = nullptr; +} + +void NativeSQLiteConnectionManager::persistLog( + std::string backupID, + std::string logID, + std::uint8_t *patchsetPtr, + int patchsetSize) { + std::string finalFilePath = + PlatformSpecificTools::getBackupLogFilePath(backupID, logID, false); + std::string tempFilePath = finalFilePath + "_tmp"; + + std::ofstream tempFile( + tempFilePath, std::ofstream::out | std::ofstream::trunc); + + if (!tempFile.is_open()) { + throw std::runtime_error("Failed to open temporary log file."); + } + tempFile.write(reinterpret_cast(patchsetPtr), patchsetSize); + tempFile.close(); + if (std::rename(tempFilePath.c_str(), finalFilePath.c_str())) { + throw std::runtime_error( + "Failed to rename complete log file from temporary path to target " + "path."); + } +} + +NativeSQLiteConnectionManager::NativeSQLiteConnectionManager() + : backupLogsSession(nullptr) { +} + +void NativeSQLiteConnectionManager::setLogsMonitoring(bool enabled) { + if (!backupLogsSession) { + return; + } + sqlite3session_enable(backupLogsSession, enabled); +} + +void NativeSQLiteConnectionManager::initializeConnection( + std::string sqliteFilePath, + std::function on_db_open_callback) { + SQLiteConnectionManager::initializeConnection( + sqliteFilePath, on_db_open_callback); + attachSession(); + setLogsMonitoring(false); +} + +void NativeSQLiteConnectionManager::closeConnection() { + detachSession(); + SQLiteConnectionManager::closeConnectionInternal(); +} + +NativeSQLiteConnectionManager::~NativeSQLiteConnectionManager() { + detachSession(); +} + +bool NativeSQLiteConnectionManager::captureLogs( + std::string backupID, + std::string logID) { + int patchsetSize; + std::uint8_t *patchsetPtr; + int getPatchsetResult = sqlite3session_patchset( + backupLogsSession, &patchsetSize, (void **)&patchsetPtr); + handleSQLiteError(getPatchsetResult, "Failed to get patchset from session."); + + if (!patchsetPtr) { + return false; + } + + if (patchsetSize == 0) { + sqlite3_free(patchsetPtr); + return false; + } + + persistLog(backupID, logID, patchsetPtr, patchsetSize); + sqlite3_free(patchsetPtr); + + // The session is not "zeroed" after capturing log. + // See: https://www.sqlite.org/sessionintro.html + // So we need to delete and recreate session each + // time we capture log. + detachSession(); + attachSession(); + return true; +} +} // namespace comm diff --git a/native/cpp/CommonCpp/DatabaseManagers/NativeSQLiteConnectionManager.h b/native/cpp/CommonCpp/DatabaseManagers/NativeSQLiteConnectionManager.h new file mode 100644 index 000000000..5cfa00a74 --- /dev/null +++ b/native/cpp/CommonCpp/DatabaseManagers/NativeSQLiteConnectionManager.h @@ -0,0 +1,28 @@ +#pragma once + +#include "SQLiteConnectionManager.h" + +namespace comm { +class NativeSQLiteConnectionManager : public SQLiteConnectionManager { +private: + sqlite3_session *backupLogsSession; + + void attachSession(); + void detachSession(); + void persistLog( + std::string backupID, + std::string logID, + std::uint8_t *patchsetPtr, + int patchsetSize); + +public: + NativeSQLiteConnectionManager(); + void setLogsMonitoring(bool enabled); + void initializeConnection( + std::string sqliteFilePath, + std::function on_db_open_callback) override; + void closeConnection() override; + ~NativeSQLiteConnectionManager(); + bool captureLogs(std::string backupID, std::string logID); +}; +} // namespace comm diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteConnectionManager.cpp b/native/cpp/CommonCpp/DatabaseManagers/SQLiteConnectionManager.cpp new file mode 100644 index 000000000..e70e6db33 --- /dev/null +++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteConnectionManager.cpp @@ -0,0 +1,56 @@ +#include "SQLiteConnectionManager.h" + +#include +#include +#include +#include + +namespace comm { + +SQLiteConnectionManager::SQLiteConnectionManager() : dbConnection(nullptr) { +} + +sqlite3 *SQLiteConnectionManager::getConnection() { + return dbConnection; +} + +void SQLiteConnectionManager::handleSQLiteError( + int errorCode, + const std::string &errorMessagePrefix, + int expectedResultCode) { + if (errorCode != expectedResultCode) { + throw std::runtime_error( + errorMessagePrefix + " Details: " + sqlite3_errstr(errorCode)); + } +} + +void SQLiteConnectionManager::initializeConnection( + std::string sqliteFilePath, + std::function on_db_open_callback) { + if (dbConnection) { + return; + } + + int connectResult = sqlite3_open(sqliteFilePath.c_str(), &dbConnection); + handleSQLiteError(connectResult, "Failed to open database connection."); + on_db_open_callback(dbConnection); +} + +void SQLiteConnectionManager::closeConnectionInternal() { + if (!dbConnection) { + return; + } + + int closeResult = sqlite3_close(dbConnection); + handleSQLiteError(closeResult, "Failed to close database connection."); + dbConnection = nullptr; +} + +void SQLiteConnectionManager::closeConnection() { + closeConnectionInternal(); +} + +SQLiteConnectionManager::~SQLiteConnectionManager() { + closeConnectionInternal(); +} +} // namespace comm diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteConnectionManager.h b/native/cpp/CommonCpp/DatabaseManagers/SQLiteConnectionManager.h new file mode 100644 index 000000000..7af7b1552 --- /dev/null +++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteConnectionManager.h @@ -0,0 +1,30 @@ +#pragma once + +#ifndef SQLITE_ENABLE_SESSION +#define SQLITE_ENABLE_SESSION +#endif + +#include +#include +#include + +namespace comm { +class SQLiteConnectionManager { +protected: + sqlite3 *dbConnection; + static void handleSQLiteError( + int errorCode, + const std::string &errorMessagePrefix, + int expectedResultCode = SQLITE_OK); + void closeConnectionInternal(); + +public: + SQLiteConnectionManager(); + sqlite3 *getConnection(); + virtual void initializeConnection( + std::string sqliteFilePath, + std::function on_db_open_callback); + virtual void closeConnection(); + virtual ~SQLiteConnectionManager(); +}; +} // namespace comm diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp index 9e6d492d5..ee934f184 100644 --- a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp +++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp @@ -1,1885 +1,1885 @@ #include "SQLiteQueryExecutor.h" #include "Logger.h" #include "entities/EntityQueryHelpers.h" #include "entities/KeyserverInfo.h" #include "entities/Metadata.h" #include "entities/UserInfo.h" #include #include #include #ifndef EMSCRIPTEN #include "CommSecureStore.h" #include "PlatformSpecificTools.h" +#include "StaffUtils.h" #endif #define ACCOUNT_ID 1 namespace comm { std::string SQLiteQueryExecutor::sqliteFilePath; std::string SQLiteQueryExecutor::encryptionKey; std::once_flag SQLiteQueryExecutor::initialized; int SQLiteQueryExecutor::sqlcipherEncryptionKeySize = 64; std::string SQLiteQueryExecutor::secureStoreEncryptionKeyID = "comm.encryptionKey"; -sqlite3 *SQLiteQueryExecutor::dbConnection = nullptr; + +#ifndef EMSCRIPTEN +NativeSQLiteConnectionManager SQLiteQueryExecutor::connectionManager; +#else +SQLiteConnectionManager SQLiteQueryExecutor::connectionManager; +#endif bool create_table(sqlite3 *db, std::string query, std::string tableName) { char *error; sqlite3_exec(db, query.c_str(), nullptr, nullptr, &error); if (!error) { return true; } std::ostringstream stringStream; stringStream << "Error creating '" << tableName << "' table: " << error; Logger::log(stringStream.str()); sqlite3_free(error); return false; } bool create_drafts_table(sqlite3 *db) { std::string query = "CREATE TABLE IF NOT EXISTS drafts (threadID TEXT UNIQUE PRIMARY KEY, " "text TEXT);"; return create_table(db, query, "drafts"); } bool rename_threadID_to_key(sqlite3 *db) { sqlite3_stmt *key_column_stmt; sqlite3_prepare_v2( db, "SELECT name AS col_name FROM pragma_table_xinfo ('drafts') WHERE " "col_name='key';", -1, &key_column_stmt, nullptr); sqlite3_step(key_column_stmt); auto num_bytes = sqlite3_column_bytes(key_column_stmt, 0); sqlite3_finalize(key_column_stmt); if (num_bytes) { return true; } char *error; sqlite3_exec( db, "ALTER TABLE drafts RENAME COLUMN `threadID` TO `key`;", nullptr, nullptr, &error); if (error) { std::ostringstream stringStream; stringStream << "Error occurred renaming threadID column in drafts table " << "to key: " << error; Logger::log(stringStream.str()); sqlite3_free(error); return false; } return true; } bool create_persist_account_table(sqlite3 *db) { std::string query = "CREATE TABLE IF NOT EXISTS olm_persist_account(" "id INTEGER UNIQUE PRIMARY KEY NOT NULL, " "account_data TEXT NOT NULL);"; return create_table(db, query, "olm_persist_account"); } bool create_persist_sessions_table(sqlite3 *db) { std::string query = "CREATE TABLE IF NOT EXISTS olm_persist_sessions(" "target_user_id TEXT UNIQUE PRIMARY KEY NOT NULL, " "session_data TEXT NOT NULL);"; return create_table(db, query, "olm_persist_sessions"); } bool drop_messages_table(sqlite3 *db) { char *error; sqlite3_exec(db, "DROP TABLE IF EXISTS messages;", nullptr, nullptr, &error); if (!error) { return true; } std::ostringstream stringStream; stringStream << "Error dropping 'messages' table: " << error; Logger::log(stringStream.str()); sqlite3_free(error); return false; } bool recreate_messages_table(sqlite3 *db) { std::string query = "CREATE TABLE IF NOT EXISTS messages ( " "id TEXT UNIQUE PRIMARY KEY NOT NULL, " "local_id TEXT, " "thread TEXT NOT NULL, " "user TEXT NOT NULL, " "type INTEGER NOT NULL, " "future_type INTEGER, " "content TEXT, " "time INTEGER NOT NULL);"; return create_table(db, query, "messages"); } bool create_messages_idx_thread_time(sqlite3 *db) { char *error; sqlite3_exec( db, "CREATE INDEX IF NOT EXISTS messages_idx_thread_time " "ON messages (thread, time);", nullptr, nullptr, &error); if (!error) { return true; } std::ostringstream stringStream; stringStream << "Error creating (thread, time) index on messages table: " << error; Logger::log(stringStream.str()); sqlite3_free(error); return false; } bool create_media_table(sqlite3 *db) { std::string query = "CREATE TABLE IF NOT EXISTS media ( " "id TEXT UNIQUE PRIMARY KEY NOT NULL, " "container TEXT NOT NULL, " "thread TEXT NOT NULL, " "uri TEXT NOT NULL, " "type TEXT NOT NULL, " "extras TEXT NOT NULL);"; return create_table(db, query, "media"); } bool create_media_idx_container(sqlite3 *db) { char *error; sqlite3_exec( db, "CREATE INDEX IF NOT EXISTS media_idx_container " "ON media (container);", nullptr, nullptr, &error); if (!error) { return true; } std::ostringstream stringStream; stringStream << "Error creating (container) index on media table: " << error; Logger::log(stringStream.str()); sqlite3_free(error); return false; } bool create_threads_table(sqlite3 *db) { std::string query = "CREATE TABLE IF NOT EXISTS threads ( " "id TEXT UNIQUE PRIMARY KEY NOT NULL, " "type INTEGER NOT NULL, " "name TEXT, " "description TEXT, " "color TEXT NOT NULL, " "creation_time BIGINT NOT NULL, " "parent_thread_id TEXT, " "containing_thread_id TEXT, " "community TEXT, " "members TEXT NOT NULL, " "roles TEXT NOT NULL, " "current_user TEXT NOT NULL, " "source_message_id TEXT, " "replies_count INTEGER NOT NULL);"; return create_table(db, query, "threads"); } bool update_threadID_for_pending_threads_in_drafts(sqlite3 *db) { char *error; sqlite3_exec( db, "UPDATE drafts SET key = " "REPLACE(REPLACE(REPLACE(REPLACE(key, 'type4/', '')," "'type5/', ''),'type6/', ''),'type7/', '')" "WHERE key LIKE 'pending/%'", nullptr, nullptr, &error); if (!error) { return true; } std::ostringstream stringStream; stringStream << "Error update pending threadIDs on drafts table: " << error; Logger::log(stringStream.str()); sqlite3_free(error); return false; } bool enable_write_ahead_logging_mode(sqlite3 *db) { char *error; sqlite3_exec(db, "PRAGMA journal_mode=wal;", nullptr, nullptr, &error); if (!error) { return true; } std::ostringstream stringStream; stringStream << "Error enabling write-ahead logging mode: " << error; Logger::log(stringStream.str()); sqlite3_free(error); return false; } bool create_metadata_table(sqlite3 *db) { std::string query = "CREATE TABLE IF NOT EXISTS metadata ( " "name TEXT UNIQUE PRIMARY KEY NOT NULL, " "data TEXT);"; return create_table(db, query, "metadata"); } bool add_not_null_constraint_to_drafts(sqlite3 *db) { char *error; sqlite3_exec( db, "CREATE TABLE IF NOT EXISTS temporary_drafts (" "key TEXT UNIQUE PRIMARY KEY NOT NULL, " "text TEXT NOT NULL);" "INSERT INTO temporary_drafts SELECT * FROM drafts " "WHERE key IS NOT NULL AND text IS NOT NULL;" "DROP TABLE drafts;" "ALTER TABLE temporary_drafts RENAME TO drafts;", nullptr, nullptr, &error); if (!error) { return true; } std::ostringstream stringStream; stringStream << "Error adding NOT NULL constraint to drafts table: " << error; Logger::log(stringStream.str()); sqlite3_free(error); return false; } bool add_not_null_constraint_to_metadata(sqlite3 *db) { char *error; sqlite3_exec( db, "CREATE TABLE IF NOT EXISTS temporary_metadata (" "name TEXT UNIQUE PRIMARY KEY NOT NULL, " "data TEXT NOT NULL);" "INSERT INTO temporary_metadata SELECT * FROM metadata " "WHERE data IS NOT NULL;" "DROP TABLE metadata;" "ALTER TABLE temporary_metadata RENAME TO metadata;", nullptr, nullptr, &error); if (!error) { return true; } std::ostringstream stringStream; stringStream << "Error adding NOT NULL constraint to metadata table: " << error; Logger::log(stringStream.str()); sqlite3_free(error); return false; } bool add_avatar_column_to_threads_table(sqlite3 *db) { char *error; sqlite3_exec( db, "ALTER TABLE threads ADD COLUMN avatar TEXT;", nullptr, nullptr, &error); if (!error) { return true; } std::ostringstream stringStream; stringStream << "Error adding avatar column to threads table: " << error; Logger::log(stringStream.str()); sqlite3_free(error); return false; } bool add_pinned_count_column_to_threads(sqlite3 *db) { sqlite3_stmt *pinned_column_stmt; sqlite3_prepare_v2( db, "SELECT name AS col_name FROM pragma_table_xinfo ('threads') WHERE " "col_name='pinned_count';", -1, &pinned_column_stmt, nullptr); sqlite3_step(pinned_column_stmt); auto num_bytes = sqlite3_column_bytes(pinned_column_stmt, 0); sqlite3_finalize(pinned_column_stmt); if (num_bytes) { return true; } char *error; sqlite3_exec( db, "ALTER TABLE threads ADD COLUMN pinned_count INTEGER NOT NULL DEFAULT 0;", nullptr, nullptr, &error); if (!error) { return true; } std::ostringstream stringStream; stringStream << "Error adding pinned_count column to threads table: " << error; Logger::log(stringStream.str()); sqlite3_free(error); return false; } bool create_message_store_threads_table(sqlite3 *db) { std::string query = "CREATE TABLE IF NOT EXISTS message_store_threads (" " id TEXT UNIQUE PRIMARY KEY NOT NULL," " start_reached INTEGER NOT NULL," " last_navigated_to BIGINT NOT NULL," " last_pruned BIGINT NOT NULL" ");"; return create_table(db, query, "message_store_threads"); } bool create_reports_table(sqlite3 *db) { std::string query = "CREATE TABLE IF NOT EXISTS reports (" " id TEXT UNIQUE PRIMARY KEY NOT NULL," " report TEXT NOT NULL" ");"; return create_table(db, query, "reports"); } bool create_persist_storage_table(sqlite3 *db) { std::string query = "CREATE TABLE IF NOT EXISTS persist_storage (" " key TEXT UNIQUE PRIMARY KEY NOT NULL," " item TEXT NOT NULL" ");"; return create_table(db, query, "persist_storage"); } bool recreate_message_store_threads_table(sqlite3 *db) { char *errMsg = 0; // 1. Create table without `last_navigated_to` or `last_pruned`. std::string create_new_table_query = "CREATE TABLE IF NOT EXISTS temp_message_store_threads (" " id TEXT UNIQUE PRIMARY KEY NOT NULL," " start_reached INTEGER NOT NULL" ");"; if (sqlite3_exec(db, create_new_table_query.c_str(), NULL, NULL, &errMsg) != SQLITE_OK) { Logger::log( "Error creating temp_message_store_threads: " + std::string{errMsg}); sqlite3_free(errMsg); return false; } // 2. Dump data from existing `message_store_threads` table into temp table. std::string copy_data_query = "INSERT INTO temp_message_store_threads (id, start_reached)" "SELECT id, start_reached FROM message_store_threads;"; if (sqlite3_exec(db, copy_data_query.c_str(), NULL, NULL, &errMsg) != SQLITE_OK) { Logger::log( "Error dumping data from existing message_store_threads to " "temp_message_store_threads: " + std::string{errMsg}); sqlite3_free(errMsg); return false; } // 3. Drop the existing `message_store_threads` table. std::string drop_old_table_query = "DROP TABLE message_store_threads;"; if (sqlite3_exec(db, drop_old_table_query.c_str(), NULL, NULL, &errMsg) != SQLITE_OK) { Logger::log( "Error dropping message_store_threads table: " + std::string{errMsg}); sqlite3_free(errMsg); return false; } // 4. Rename the temp table back to `message_store_threads`. std::string rename_table_query = "ALTER TABLE temp_message_store_threads RENAME TO message_store_threads;"; if (sqlite3_exec(db, rename_table_query.c_str(), NULL, NULL, &errMsg) != SQLITE_OK) { Logger::log( "Error renaming temp_message_store_threads to message_store_threads: " + std::string{errMsg}); sqlite3_free(errMsg); return false; } return true; } bool create_users_table(sqlite3 *db) { std::string query = "CREATE TABLE IF NOT EXISTS users (" " id TEXT UNIQUE PRIMARY KEY NOT NULL," " user_info TEXT NOT NULL" ");"; return create_table(db, query, "users"); } bool create_keyservers_table(sqlite3 *db) { std::string query = "CREATE TABLE IF NOT EXISTS keyservers (" " id TEXT UNIQUE PRIMARY KEY NOT NULL," " keyserver_info TEXT NOT NULL" ");"; return create_table(db, query, "keyservers"); } bool enable_rollback_journal_mode(sqlite3 *db) { char *error; sqlite3_exec(db, "PRAGMA journal_mode=DELETE;", nullptr, nullptr, &error); if (!error) { return true; } std::stringstream error_message; error_message << "Error disabling write-ahead logging mode: " << error; Logger::log(error_message.str()); sqlite3_free(error); return false; } bool create_schema(sqlite3 *db) { char *error; sqlite3_exec( db, "CREATE TABLE IF NOT EXISTS drafts (" " key TEXT UNIQUE PRIMARY KEY NOT NULL," " text TEXT NOT NULL" ");" "CREATE TABLE IF NOT EXISTS messages (" " id TEXT UNIQUE PRIMARY KEY NOT NULL," " local_id TEXT," " thread TEXT NOT NULL," " user TEXT NOT NULL," " type INTEGER NOT NULL," " future_type INTEGER," " content TEXT," " time INTEGER NOT NULL" ");" "CREATE TABLE IF NOT EXISTS olm_persist_account (" " id INTEGER UNIQUE PRIMARY KEY NOT NULL," " account_data TEXT NOT NULL" ");" "CREATE TABLE IF NOT EXISTS olm_persist_sessions (" " target_user_id TEXT UNIQUE PRIMARY KEY NOT NULL," " session_data TEXT NOT NULL" ");" "CREATE TABLE IF NOT EXISTS media (" " id TEXT UNIQUE PRIMARY KEY NOT NULL," " container TEXT NOT NULL," " thread TEXT NOT NULL," " uri TEXT NOT NULL," " type TEXT NOT NULL," " extras TEXT NOT NULL" ");" "CREATE TABLE IF NOT EXISTS threads (" " id TEXT UNIQUE PRIMARY KEY NOT NULL," " type INTEGER NOT NULL," " name TEXT," " description TEXT," " color TEXT NOT NULL," " creation_time BIGINT NOT NULL," " parent_thread_id TEXT," " containing_thread_id TEXT," " community TEXT," " members TEXT NOT NULL," " roles TEXT NOT NULL," " current_user TEXT NOT NULL," " source_message_id TEXT," " replies_count INTEGER NOT NULL," " avatar TEXT," " pinned_count INTEGER NOT NULL DEFAULT 0" ");" "CREATE TABLE IF NOT EXISTS metadata (" " name TEXT UNIQUE PRIMARY KEY NOT NULL," " data TEXT NOT NULL" ");" "CREATE TABLE IF NOT EXISTS message_store_threads (" " id TEXT UNIQUE PRIMARY KEY NOT NULL," " start_reached INTEGER NOT NULL" ");" "CREATE TABLE IF NOT EXISTS reports (" " id TEXT UNIQUE PRIMARY KEY NOT NULL," " report TEXT NOT NULL" ");" "CREATE TABLE IF NOT EXISTS persist_storage (" " key TEXT UNIQUE PRIMARY KEY NOT NULL," " item TEXT NOT NULL" ");" "CREATE TABLE IF NOT EXISTS users (" " id TEXT UNIQUE PRIMARY KEY NOT NULL," " user_info TEXT NOT NULL" ");" "CREATE TABLE IF NOT EXISTS keyservers (" " id TEXT UNIQUE PRIMARY KEY NOT NULL," " keyserver_info TEXT NOT NULL" ");" "CREATE INDEX IF NOT EXISTS media_idx_container" " ON media (container);" "CREATE INDEX IF NOT EXISTS messages_idx_thread_time" " ON messages (thread, time);", nullptr, nullptr, &error); if (!error) { return true; } std::ostringstream stringStream; stringStream << "Error creating tables: " << error; Logger::log(stringStream.str()); sqlite3_free(error); return false; } void set_encryption_key( sqlite3 *db, const std::string &encryptionKey = SQLiteQueryExecutor::encryptionKey) { std::string set_encryption_key_query = "PRAGMA key = \"x'" + encryptionKey + "'\";"; char *error_set_key; sqlite3_exec( db, set_encryption_key_query.c_str(), nullptr, nullptr, &error_set_key); if (error_set_key) { std::ostringstream error_message; error_message << "Failed to set encryption key: " << error_set_key; throw std::system_error( ECANCELED, std::generic_category(), error_message.str()); } } int get_database_version(sqlite3 *db) { sqlite3_stmt *user_version_stmt; sqlite3_prepare_v2( db, "PRAGMA user_version;", -1, &user_version_stmt, nullptr); sqlite3_step(user_version_stmt); int current_user_version = sqlite3_column_int(user_version_stmt, 0); sqlite3_finalize(user_version_stmt); return current_user_version; } bool set_database_version(sqlite3 *db, int db_version) { std::stringstream update_version; update_version << "PRAGMA user_version=" << db_version << ";"; auto update_version_str = update_version.str(); char *error; sqlite3_exec(db, update_version_str.c_str(), nullptr, nullptr, &error); if (!error) { return true; } std::ostringstream errorStream; errorStream << "Error setting database version to " << db_version << ": " << error; Logger::log(errorStream.str()); sqlite3_free(error); return false; } -void trace_queries(sqlite3 *db) { - int error_code = sqlite3_trace_v2( - db, - SQLITE_TRACE_PROFILE, - [](unsigned, void *, void *preparedStatement, void *) { - sqlite3_stmt *statement = (sqlite3_stmt *)preparedStatement; - char *sql = sqlite3_expanded_sql(statement); - if (sql != nullptr) { - std::string sqlStr(sql); - // TODO: send logs to backup here - } - return 0; - }, - NULL); - if (error_code != SQLITE_OK) { - std::ostringstream error_message; - error_message << "Failed to set trace callback, error code: " << error_code; - throw std::system_error( - ECANCELED, std::generic_category(), error_message.str()); - } -} - // We don't want to run `PRAGMA key = ...;` // on main web database. The context is here: // https://linear.app/comm/issue/ENG-6398/issues-with-sqlcipher-on-web void default_on_db_open_callback(sqlite3 *db) { #ifndef EMSCRIPTEN set_encryption_key(db); #endif - trace_queries(db); } // This is a temporary solution. In future we want to keep // a separate table for blob hashes. Tracked on Linear: // https://linear.app/comm/issue/ENG-6261/introduce-blob-hash-table std::string blob_hash_from_blob_service_uri(const std::string &media_uri) { static const std::string blob_service_prefix = "comm-blob-service://"; return media_uri.substr(blob_service_prefix.size()); } bool file_exists(const std::string &file_path) { std::ifstream file(file_path.c_str()); return file.good(); } void attempt_delete_file( const std::string &file_path, const char *error_message) { if (std::remove(file_path.c_str())) { throw std::system_error(errno, std::generic_category(), error_message); } } void attempt_rename_file( const std::string &old_path, const std::string &new_path, const char *error_message) { if (std::rename(old_path.c_str(), new_path.c_str())) { throw std::system_error(errno, std::generic_category(), error_message); } } bool is_database_queryable( sqlite3 *db, bool use_encryption_key, const std::string &path = SQLiteQueryExecutor::sqliteFilePath, const std::string &encryptionKey = SQLiteQueryExecutor::encryptionKey) { char *err_msg; sqlite3_open(path.c_str(), &db); // According to SQLCipher documentation running some SELECT is the only way to // check for key validity if (use_encryption_key) { set_encryption_key(db, encryptionKey); } sqlite3_exec( db, "SELECT COUNT(*) FROM sqlite_master;", nullptr, nullptr, &err_msg); sqlite3_close(db); return !err_msg; } void validate_encryption() { std::string temp_encrypted_db_path = SQLiteQueryExecutor::sqliteFilePath + "_temp_encrypted"; bool temp_encrypted_exists = file_exists(temp_encrypted_db_path); bool default_location_exists = file_exists(SQLiteQueryExecutor::sqliteFilePath); if (temp_encrypted_exists && default_location_exists) { Logger::log( "Previous encryption attempt failed. Repeating encryption process from " "the beginning."); attempt_delete_file( temp_encrypted_db_path, "Failed to delete corrupted encrypted database."); } else if (temp_encrypted_exists && !default_location_exists) { Logger::log( "Moving temporary encrypted database to default location failed in " "previous encryption attempt. Repeating rename step."); attempt_rename_file( temp_encrypted_db_path, SQLiteQueryExecutor::sqliteFilePath, "Failed to move encrypted database to default location."); return; } else if (!default_location_exists) { Logger::log( "Database not present yet. It will be created encrypted under default " "path."); return; } sqlite3 *db; if (is_database_queryable(db, true)) { Logger::log( "Database exists under default path and it is correctly encrypted."); return; } if (!is_database_queryable(db, false)) { Logger::log( "Database exists but it is encrypted with key that was lost. " "Attempting database deletion. New encrypted one will be created."); attempt_delete_file( SQLiteQueryExecutor::sqliteFilePath.c_str(), "Failed to delete database encrypted with lost key."); return; } else { Logger::log( "Database exists but it is not encrypted. Attempting encryption " "process."); } sqlite3_open(SQLiteQueryExecutor::sqliteFilePath.c_str(), &db); std::string createEncryptedCopySQL = "ATTACH DATABASE '" + temp_encrypted_db_path + "' AS encrypted_comm " "KEY \"x'" + SQLiteQueryExecutor::encryptionKey + "'\";" "SELECT sqlcipher_export('encrypted_comm');" "DETACH DATABASE encrypted_comm;"; char *encryption_error; sqlite3_exec( db, createEncryptedCopySQL.c_str(), nullptr, nullptr, &encryption_error); if (encryption_error) { throw std::system_error( ECANCELED, std::generic_category(), "Failed to create encrypted copy of the original database."); } sqlite3_close(db); attempt_delete_file( SQLiteQueryExecutor::sqliteFilePath, "Failed to delete unencrypted database."); attempt_rename_file( temp_encrypted_db_path, SQLiteQueryExecutor::sqliteFilePath, "Failed to move encrypted database to default location."); Logger::log("Encryption completed successfully."); } typedef bool ShouldBeInTransaction; typedef std::function MigrateFunction; typedef std::pair SQLiteMigration; std::vector> migrations{ {{1, {create_drafts_table, true}}, {2, {rename_threadID_to_key, true}}, {4, {create_persist_account_table, true}}, {5, {create_persist_sessions_table, true}}, {15, {create_media_table, true}}, {16, {drop_messages_table, true}}, {17, {recreate_messages_table, true}}, {18, {create_messages_idx_thread_time, true}}, {19, {create_media_idx_container, true}}, {20, {create_threads_table, true}}, {21, {update_threadID_for_pending_threads_in_drafts, true}}, {22, {enable_write_ahead_logging_mode, false}}, {23, {create_metadata_table, true}}, {24, {add_not_null_constraint_to_drafts, true}}, {25, {add_not_null_constraint_to_metadata, true}}, {26, {add_avatar_column_to_threads_table, true}}, {27, {add_pinned_count_column_to_threads, true}}, {28, {create_message_store_threads_table, true}}, {29, {create_reports_table, true}}, {30, {create_persist_storage_table, true}}, {31, {recreate_message_store_threads_table, true}}, {32, {create_users_table, true}}, {33, {create_keyservers_table, true}}, {34, {enable_rollback_journal_mode, false}}}}; enum class MigrationResult { SUCCESS, FAILURE, NOT_APPLIED }; MigrationResult applyMigrationWithTransaction( sqlite3 *db, const MigrateFunction &migrate, int index) { sqlite3_exec(db, "BEGIN TRANSACTION;", nullptr, nullptr, nullptr); auto db_version = get_database_version(db); if (index <= db_version) { sqlite3_exec(db, "ROLLBACK;", nullptr, nullptr, nullptr); return MigrationResult::NOT_APPLIED; } auto rc = migrate(db); if (!rc) { sqlite3_exec(db, "ROLLBACK;", nullptr, nullptr, nullptr); return MigrationResult::FAILURE; } auto database_version_set = set_database_version(db, index); if (!database_version_set) { sqlite3_exec(db, "ROLLBACK;", nullptr, nullptr, nullptr); return MigrationResult::FAILURE; } sqlite3_exec(db, "END TRANSACTION;", nullptr, nullptr, nullptr); return MigrationResult::SUCCESS; } MigrationResult applyMigrationWithoutTransaction( sqlite3 *db, const MigrateFunction &migrate, int index) { auto db_version = get_database_version(db); if (index <= db_version) { return MigrationResult::NOT_APPLIED; } auto rc = migrate(db); if (!rc) { return MigrationResult::FAILURE; } sqlite3_exec(db, "BEGIN TRANSACTION;", nullptr, nullptr, nullptr); auto inner_db_version = get_database_version(db); if (index <= inner_db_version) { sqlite3_exec(db, "ROLLBACK;", nullptr, nullptr, nullptr); return MigrationResult::NOT_APPLIED; } auto database_version_set = set_database_version(db, index); if (!database_version_set) { sqlite3_exec(db, "ROLLBACK;", nullptr, nullptr, nullptr); return MigrationResult::FAILURE; } sqlite3_exec(db, "END TRANSACTION;", nullptr, nullptr, nullptr); return MigrationResult::SUCCESS; } bool set_up_database(sqlite3 *db) { sqlite3_exec(db, "BEGIN TRANSACTION;", nullptr, nullptr, nullptr); auto db_version = get_database_version(db); auto latest_version = migrations.back().first; if (db_version == latest_version) { sqlite3_exec(db, "ROLLBACK;", nullptr, nullptr, nullptr); return true; } if (db_version != 0 || !create_schema(db) || !set_database_version(db, latest_version)) { sqlite3_exec(db, "ROLLBACK;", nullptr, nullptr, nullptr); return false; } sqlite3_exec(db, "END TRANSACTION;", nullptr, nullptr, nullptr); return true; } void SQLiteQueryExecutor::migrate() { // We don't want to run `PRAGMA key = ...;` // on main web database. The context is here: // https://linear.app/comm/issue/ENG-6398/issues-with-sqlcipher-on-web #ifndef EMSCRIPTEN validate_encryption(); #endif sqlite3 *db; sqlite3_open(SQLiteQueryExecutor::sqliteFilePath.c_str(), &db); default_on_db_open_callback(db); std::stringstream db_path; db_path << "db path: " << SQLiteQueryExecutor::sqliteFilePath.c_str() << std::endl; Logger::log(db_path.str()); auto db_version = get_database_version(db); std::stringstream version_msg; version_msg << "db version: " << db_version << std::endl; Logger::log(version_msg.str()); if (db_version == 0) { auto db_created = set_up_database(db); if (!db_created) { sqlite3_close(db); Logger::log("Database structure creation error."); throw std::runtime_error("Database structure creation error"); } Logger::log("Database structure created."); sqlite3_close(db); return; } for (const auto &[idx, migration] : migrations) { const auto &[applyMigration, shouldBeInTransaction] = migration; MigrationResult migrationResult; if (shouldBeInTransaction) { migrationResult = applyMigrationWithTransaction(db, applyMigration, idx); } else { migrationResult = applyMigrationWithoutTransaction(db, applyMigration, idx); } if (migrationResult == MigrationResult::NOT_APPLIED) { continue; } std::stringstream migration_msg; if (migrationResult == MigrationResult::FAILURE) { migration_msg << "migration " << idx << " failed." << std::endl; Logger::log(migration_msg.str()); sqlite3_close(db); throw std::runtime_error(migration_msg.str()); } if (migrationResult == MigrationResult::SUCCESS) { migration_msg << "migration " << idx << " succeeded." << std::endl; Logger::log(migration_msg.str()); } } sqlite3_close(db); } SQLiteQueryExecutor::SQLiteQueryExecutor() { SQLiteQueryExecutor::migrate(); +#ifndef EMSCRIPTEN + std::string currentBackupID = this->getMetadata("backupID"); + if (!StaffUtils::isStaffRelease() || !currentBackupID.size()) { + return; + } + SQLiteQueryExecutor::connectionManager.setLogsMonitoring(true); +#endif } SQLiteQueryExecutor::SQLiteQueryExecutor(std::string sqliteFilePath) { SQLiteQueryExecutor::sqliteFilePath = sqliteFilePath; SQLiteQueryExecutor::migrate(); } sqlite3 *SQLiteQueryExecutor::getConnection() { - if (SQLiteQueryExecutor::dbConnection) { - return SQLiteQueryExecutor::dbConnection; - } - - int connectResult = sqlite3_open( - SQLiteQueryExecutor::sqliteFilePath.c_str(), - &SQLiteQueryExecutor::dbConnection); - - if (connectResult != SQLITE_OK) { - std::stringstream error_message; - error_message << "Failed to open database connection. Details: " - << sqlite3_errstr(connectResult) << std::endl; - throw std::runtime_error(error_message.str()); + if (SQLiteQueryExecutor::connectionManager.getConnection()) { + return SQLiteQueryExecutor::connectionManager.getConnection(); } - - default_on_db_open_callback(SQLiteQueryExecutor::dbConnection); - return SQLiteQueryExecutor::dbConnection; + SQLiteQueryExecutor::connectionManager.initializeConnection( + SQLiteQueryExecutor::sqliteFilePath, default_on_db_open_callback); + return SQLiteQueryExecutor::connectionManager.getConnection(); } void SQLiteQueryExecutor::closeConnection() { - if (!SQLiteQueryExecutor::dbConnection) { - return; - } - sqlite3_close(SQLiteQueryExecutor::dbConnection); - SQLiteQueryExecutor::dbConnection = nullptr; + SQLiteQueryExecutor::connectionManager.closeConnection(); } SQLiteQueryExecutor::~SQLiteQueryExecutor() { SQLiteQueryExecutor::closeConnection(); } std::string SQLiteQueryExecutor::getDraft(std::string key) const { static std::string getDraftByPrimaryKeySQL = "SELECT * " "FROM drafts " "WHERE key = ?;"; std::unique_ptr draft = getEntityByPrimaryKey( SQLiteQueryExecutor::getConnection(), getDraftByPrimaryKeySQL, key); return (draft == nullptr) ? "" : draft->text; } std::unique_ptr SQLiteQueryExecutor::getThread(std::string threadID) const { static std::string getThreadByPrimaryKeySQL = "SELECT * " "FROM threads " "WHERE id = ?;"; return getEntityByPrimaryKey( SQLiteQueryExecutor::getConnection(), getThreadByPrimaryKeySQL, threadID); } void SQLiteQueryExecutor::updateDraft(std::string key, std::string text) const { static std::string replaceDraftSQL = "REPLACE INTO drafts (key, text) " "VALUES (?, ?);"; Draft draft = {key, text}; replaceEntity( SQLiteQueryExecutor::getConnection(), replaceDraftSQL, draft); } bool SQLiteQueryExecutor::moveDraft(std::string oldKey, std::string newKey) const { std::string draftText = this->getDraft(oldKey); if (!draftText.size()) { return false; } static std::string rekeyDraftSQL = "UPDATE OR REPLACE drafts " "SET key = ? " "WHERE key = ?;"; rekeyAllEntities( SQLiteQueryExecutor::getConnection(), rekeyDraftSQL, oldKey, newKey); return true; } std::vector SQLiteQueryExecutor::getAllDrafts() const { static std::string getAllDraftsSQL = "SELECT * " "FROM drafts;"; return getAllEntities( SQLiteQueryExecutor::getConnection(), getAllDraftsSQL); } void SQLiteQueryExecutor::removeAllDrafts() const { static std::string removeAllDraftsSQL = "DELETE FROM drafts;"; removeAllEntities(SQLiteQueryExecutor::getConnection(), removeAllDraftsSQL); } void SQLiteQueryExecutor::removeDrafts( const std::vector &ids) const { if (!ids.size()) { return; } std::stringstream removeDraftsByKeysSQLStream; removeDraftsByKeysSQLStream << "DELETE FROM drafts " "WHERE key IN " << getSQLStatementArray(ids.size()) << ";"; removeEntitiesByKeys( SQLiteQueryExecutor::getConnection(), removeDraftsByKeysSQLStream.str(), ids); } void SQLiteQueryExecutor::removeAllMessages() const { static std::string removeAllMessagesSQL = "DELETE FROM messages;"; removeAllEntities(SQLiteQueryExecutor::getConnection(), removeAllMessagesSQL); } std::vector>> SQLiteQueryExecutor::getAllMessages() const { static std::string getAllMessagesSQL = "SELECT * " "FROM messages " "LEFT JOIN media " " ON messages.id = media.container " "ORDER BY messages.id;"; SQLiteStatementWrapper preparedSQL( SQLiteQueryExecutor::getConnection(), getAllMessagesSQL, "Failed to retrieve all messages."); std::string prevMsgIdx{}; std::vector>> allMessages; for (int stepResult = sqlite3_step(preparedSQL); stepResult == SQLITE_ROW; stepResult = sqlite3_step(preparedSQL)) { Message message = Message::fromSQLResult(preparedSQL, 0); if (message.id == prevMsgIdx) { allMessages.back().second.push_back(Media::fromSQLResult(preparedSQL, 8)); } else { prevMsgIdx = message.id; std::vector mediaForMsg; if (sqlite3_column_type(preparedSQL, 8) != SQLITE_NULL) { mediaForMsg.push_back(Media::fromSQLResult(preparedSQL, 8)); } allMessages.push_back(std::make_pair(std::move(message), mediaForMsg)); } } return allMessages; } void SQLiteQueryExecutor::removeMessages( const std::vector &ids) const { if (!ids.size()) { return; } std::stringstream removeMessagesByKeysSQLStream; removeMessagesByKeysSQLStream << "DELETE FROM messages " "WHERE id IN " << getSQLStatementArray(ids.size()) << ";"; removeEntitiesByKeys( SQLiteQueryExecutor::getConnection(), removeMessagesByKeysSQLStream.str(), ids); } void SQLiteQueryExecutor::removeMessagesForThreads( const std::vector &threadIDs) const { if (!threadIDs.size()) { return; } std::stringstream removeMessagesByKeysSQLStream; removeMessagesByKeysSQLStream << "DELETE FROM messages " "WHERE thread IN " << getSQLStatementArray(threadIDs.size()) << ";"; removeEntitiesByKeys( SQLiteQueryExecutor::getConnection(), removeMessagesByKeysSQLStream.str(), threadIDs); } void SQLiteQueryExecutor::replaceMessage(const Message &message) const { static std::string replaceMessageSQL = "REPLACE INTO messages " "(id, local_id, thread, user, type, future_type, content, time) " "VALUES (?, ?, ?, ?, ?, ?, ?, ?);"; replaceEntity( SQLiteQueryExecutor::getConnection(), replaceMessageSQL, message); } void SQLiteQueryExecutor::rekeyMessage(std::string from, std::string to) const { static std::string rekeyMessageSQL = "UPDATE OR REPLACE messages " "SET id = ? " "WHERE id = ?"; rekeyAllEntities( SQLiteQueryExecutor::getConnection(), rekeyMessageSQL, from, to); } void SQLiteQueryExecutor::removeAllMedia() const { static std::string removeAllMediaSQL = "DELETE FROM media;"; removeAllEntities(SQLiteQueryExecutor::getConnection(), removeAllMediaSQL); } void SQLiteQueryExecutor::removeMediaForMessages( const std::vector &msg_ids) const { if (!msg_ids.size()) { return; } std::stringstream removeMediaByKeysSQLStream; removeMediaByKeysSQLStream << "DELETE FROM media " "WHERE container IN " << getSQLStatementArray(msg_ids.size()) << ";"; removeEntitiesByKeys( SQLiteQueryExecutor::getConnection(), removeMediaByKeysSQLStream.str(), msg_ids); } void SQLiteQueryExecutor::removeMediaForMessage(std::string msg_id) const { static std::string removeMediaByKeySQL = "DELETE FROM media " "WHERE container IN (?);"; std::vector keys = {msg_id}; removeEntitiesByKeys( SQLiteQueryExecutor::getConnection(), removeMediaByKeySQL, keys); } void SQLiteQueryExecutor::removeMediaForThreads( const std::vector &thread_ids) const { if (!thread_ids.size()) { return; } std::stringstream removeMediaByKeysSQLStream; removeMediaByKeysSQLStream << "DELETE FROM media " "WHERE thread IN " << getSQLStatementArray(thread_ids.size()) << ";"; removeEntitiesByKeys( SQLiteQueryExecutor::getConnection(), removeMediaByKeysSQLStream.str(), thread_ids); } void SQLiteQueryExecutor::replaceMedia(const Media &media) const { static std::string replaceMediaSQL = "REPLACE INTO media " "(id, container, thread, uri, type, extras) " "VALUES (?, ?, ?, ?, ?, ?)"; replaceEntity( SQLiteQueryExecutor::getConnection(), replaceMediaSQL, media); } void SQLiteQueryExecutor::rekeyMediaContainers(std::string from, std::string to) const { static std::string rekeyMediaContainersSQL = "UPDATE media SET container = ? WHERE container = ?;"; rekeyAllEntities( SQLiteQueryExecutor::getConnection(), rekeyMediaContainersSQL, from, to); } void SQLiteQueryExecutor::replaceMessageStoreThreads( const std::vector &threads) const { static std::string replaceMessageStoreThreadSQL = "REPLACE INTO message_store_threads " "(id, start_reached) " "VALUES (?, ?);"; for (auto &thread : threads) { replaceEntity( SQLiteQueryExecutor::getConnection(), replaceMessageStoreThreadSQL, thread); } } void SQLiteQueryExecutor::removeAllMessageStoreThreads() const { static std::string removeAllMessageStoreThreadsSQL = "DELETE FROM message_store_threads;"; removeAllEntities( SQLiteQueryExecutor::getConnection(), removeAllMessageStoreThreadsSQL); } void SQLiteQueryExecutor::removeMessageStoreThreads( const std::vector &ids) const { if (!ids.size()) { return; } std::stringstream removeMessageStoreThreadsByKeysSQLStream; removeMessageStoreThreadsByKeysSQLStream << "DELETE FROM message_store_threads " "WHERE id IN " << getSQLStatementArray(ids.size()) << ";"; removeEntitiesByKeys( SQLiteQueryExecutor::getConnection(), removeMessageStoreThreadsByKeysSQLStream.str(), ids); } std::vector SQLiteQueryExecutor::getAllMessageStoreThreads() const { static std::string getAllMessageStoreThreadsSQL = "SELECT * " "FROM message_store_threads;"; return getAllEntities( SQLiteQueryExecutor::getConnection(), getAllMessageStoreThreadsSQL); } std::vector SQLiteQueryExecutor::getAllThreads() const { static std::string getAllThreadsSQL = "SELECT * " "FROM threads;"; return getAllEntities( SQLiteQueryExecutor::getConnection(), getAllThreadsSQL); }; void SQLiteQueryExecutor::removeThreads(std::vector ids) const { if (!ids.size()) { return; } std::stringstream removeThreadsByKeysSQLStream; removeThreadsByKeysSQLStream << "DELETE FROM threads " "WHERE id IN " << getSQLStatementArray(ids.size()) << ";"; removeEntitiesByKeys( SQLiteQueryExecutor::getConnection(), removeThreadsByKeysSQLStream.str(), ids); }; void SQLiteQueryExecutor::replaceThread(const Thread &thread) const { static std::string replaceThreadSQL = "REPLACE INTO threads (" " id, type, name, description, color, creation_time, parent_thread_id," " containing_thread_id, community, members, roles, current_user," " source_message_id, replies_count, avatar, pinned_count) " "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"; replaceEntity( SQLiteQueryExecutor::getConnection(), replaceThreadSQL, thread); }; void SQLiteQueryExecutor::removeAllThreads() const { static std::string removeAllThreadsSQL = "DELETE FROM threads;"; removeAllEntities(SQLiteQueryExecutor::getConnection(), removeAllThreadsSQL); }; void SQLiteQueryExecutor::replaceReport(const Report &report) const { static std::string replaceReportSQL = "REPLACE INTO reports (id, report) " "VALUES (?, ?);"; replaceEntity( SQLiteQueryExecutor::getConnection(), replaceReportSQL, report); } void SQLiteQueryExecutor::removeAllReports() const { static std::string removeAllReportsSQL = "DELETE FROM reports;"; removeAllEntities(SQLiteQueryExecutor::getConnection(), removeAllReportsSQL); } void SQLiteQueryExecutor::removeReports( const std::vector &ids) const { if (!ids.size()) { return; } std::stringstream removeReportsByKeysSQLStream; removeReportsByKeysSQLStream << "DELETE FROM reports " "WHERE id IN " << getSQLStatementArray(ids.size()) << ";"; removeEntitiesByKeys( SQLiteQueryExecutor::getConnection(), removeReportsByKeysSQLStream.str(), ids); } std::vector SQLiteQueryExecutor::getAllReports() const { static std::string getAllReportsSQL = "SELECT * " "FROM reports;"; return getAllEntities( SQLiteQueryExecutor::getConnection(), getAllReportsSQL); } void SQLiteQueryExecutor::setPersistStorageItem( std::string key, std::string item) const { static std::string replacePersistStorageItemSQL = "REPLACE INTO persist_storage (key, item) " "VALUES (?, ?);"; PersistItem entry{ key, item, }; replaceEntity( SQLiteQueryExecutor::getConnection(), replacePersistStorageItemSQL, entry); } void SQLiteQueryExecutor::removePersistStorageItem(std::string key) const { static std::string removePersistStorageItemByKeySQL = "DELETE FROM persist_storage " "WHERE key IN (?);"; std::vector keys = {key}; removeEntitiesByKeys( SQLiteQueryExecutor::getConnection(), removePersistStorageItemByKeySQL, keys); } std::string SQLiteQueryExecutor::getPersistStorageItem(std::string key) const { static std::string getPersistStorageItemByPrimaryKeySQL = "SELECT * " "FROM persist_storage " "WHERE key = ?;"; std::unique_ptr entry = getEntityByPrimaryKey( SQLiteQueryExecutor::getConnection(), getPersistStorageItemByPrimaryKeySQL, key); return (entry == nullptr) ? "" : entry->item; } void SQLiteQueryExecutor::replaceUser(const UserInfo &user_info) const { static std::string replaceUserSQL = "REPLACE INTO users (id, user_info) " "VALUES (?, ?);"; replaceEntity( SQLiteQueryExecutor::getConnection(), replaceUserSQL, user_info); } void SQLiteQueryExecutor::removeAllUsers() const { static std::string removeAllUsersSQL = "DELETE FROM users;"; removeAllEntities(SQLiteQueryExecutor::getConnection(), removeAllUsersSQL); } void SQLiteQueryExecutor::removeUsers( const std::vector &ids) const { if (!ids.size()) { return; } std::stringstream removeUsersByKeysSQLStream; removeUsersByKeysSQLStream << "DELETE FROM users " "WHERE id IN " << getSQLStatementArray(ids.size()) << ";"; removeEntitiesByKeys( SQLiteQueryExecutor::getConnection(), removeUsersByKeysSQLStream.str(), ids); } void SQLiteQueryExecutor::replaceKeyserver( const KeyserverInfo &keyserver_info) const { static std::string replaceKeyserverSQL = "REPLACE INTO keyservers (id, keyserver_info) " "VALUES (?, ?);"; replaceEntity( SQLiteQueryExecutor::getConnection(), replaceKeyserverSQL, keyserver_info); } void SQLiteQueryExecutor::removeAllKeyservers() const { static std::string removeAllKeyserversSQL = "DELETE FROM keyservers;"; removeAllEntities( SQLiteQueryExecutor::getConnection(), removeAllKeyserversSQL); } void SQLiteQueryExecutor::removeKeyservers( const std::vector &ids) const { if (!ids.size()) { return; } std::stringstream removeKeyserversByKeysSQLStream; removeKeyserversByKeysSQLStream << "DELETE FROM keyservers " "WHERE id IN " << getSQLStatementArray(ids.size()) << ";"; removeEntitiesByKeys( SQLiteQueryExecutor::getConnection(), removeKeyserversByKeysSQLStream.str(), ids); } std::vector SQLiteQueryExecutor::getAllKeyservers() const { static std::string getAllKeyserversSQL = "SELECT * " "FROM keyservers;"; return getAllEntities( SQLiteQueryExecutor::getConnection(), getAllKeyserversSQL); } std::vector SQLiteQueryExecutor::getAllUsers() const { static std::string getAllUsersSQL = "SELECT * " "FROM users;"; return getAllEntities( SQLiteQueryExecutor::getConnection(), getAllUsersSQL); } void SQLiteQueryExecutor::beginTransaction() const { executeQuery(SQLiteQueryExecutor::getConnection(), "BEGIN TRANSACTION;"); } void SQLiteQueryExecutor::commitTransaction() const { executeQuery(SQLiteQueryExecutor::getConnection(), "COMMIT;"); } void SQLiteQueryExecutor::rollbackTransaction() const { executeQuery(SQLiteQueryExecutor::getConnection(), "ROLLBACK;"); } std::vector SQLiteQueryExecutor::getOlmPersistSessionsData() const { static std::string getAllOlmPersistSessionsSQL = "SELECT * " "FROM olm_persist_sessions;"; return getAllEntities( SQLiteQueryExecutor::getConnection(), getAllOlmPersistSessionsSQL); } std::optional SQLiteQueryExecutor::getOlmPersistAccountData() const { static std::string getAllOlmPersistAccountSQL = "SELECT * " "FROM olm_persist_account;"; std::vector result = getAllEntities( SQLiteQueryExecutor::getConnection(), getAllOlmPersistAccountSQL); if (result.size() > 1) { throw std::system_error( ECANCELED, std::generic_category(), "Multiple records found for the olm_persist_account table"); } return (result.size() == 0) ? std::nullopt : std::optional(result[0].account_data); } void SQLiteQueryExecutor::storeOlmPersistAccount( const std::string &accountData) const { static std::string replaceOlmPersistAccountSQL = "REPLACE INTO olm_persist_account (id, account_data) " "VALUES (?, ?);"; OlmPersistAccount persistAccount = {ACCOUNT_ID, accountData}; replaceEntity( SQLiteQueryExecutor::getConnection(), replaceOlmPersistAccountSQL, persistAccount); } void SQLiteQueryExecutor::storeOlmPersistSession( const OlmPersistSession &session) const { static std::string replaceOlmPersistSessionSQL = "REPLACE INTO olm_persist_sessions (target_user_id, session_data) " "VALUES (?, ?);"; replaceEntity( SQLiteQueryExecutor::getConnection(), replaceOlmPersistSessionSQL, session); } void SQLiteQueryExecutor::storeOlmPersistData(crypto::Persist persist) const { std::string accountData = std::string(persist.account.begin(), persist.account.end()); for (auto it = persist.sessions.begin(); it != persist.sessions.end(); it++) { OlmPersistSession persistSession = { it->first, std::string(it->second.begin(), it->second.end())}; this->storeOlmPersistSession(persistSession); } } void SQLiteQueryExecutor::setNotifyToken(std::string token) const { this->setMetadata("notify_token", token); } void SQLiteQueryExecutor::clearNotifyToken() const { this->clearMetadata("notify_token"); } void SQLiteQueryExecutor::setCurrentUserID(std::string userID) const { this->setMetadata("current_user_id", userID); } std::string SQLiteQueryExecutor::getCurrentUserID() const { return this->getMetadata("current_user_id"); } void SQLiteQueryExecutor::setMetadata(std::string entry_name, std::string data) const { std::string replaceMetadataSQL = "REPLACE INTO metadata (name, data) " "VALUES (?, ?);"; Metadata entry{ entry_name, data, }; replaceEntity( SQLiteQueryExecutor::getConnection(), replaceMetadataSQL, entry); } void SQLiteQueryExecutor::clearMetadata(std::string entry_name) const { static std::string removeMetadataByKeySQL = "DELETE FROM metadata " "WHERE name IN (?);"; std::vector keys = {entry_name}; removeEntitiesByKeys( SQLiteQueryExecutor::getConnection(), removeMetadataByKeySQL, keys); } std::string SQLiteQueryExecutor::getMetadata(std::string entry_name) const { std::string getMetadataByPrimaryKeySQL = "SELECT * " "FROM metadata " "WHERE name = ?;"; std::unique_ptr entry = getEntityByPrimaryKey( SQLiteQueryExecutor::getConnection(), getMetadataByPrimaryKeySQL, entry_name); return (entry == nullptr) ? "" : entry->data; } #ifdef EMSCRIPTEN std::vector SQLiteQueryExecutor::getAllThreadsWeb() const { auto threads = this->getAllThreads(); std::vector webThreads; webThreads.reserve(threads.size()); for (const auto &thread : threads) { webThreads.emplace_back(thread); } return webThreads; }; void SQLiteQueryExecutor::replaceThreadWeb(const WebThread &thread) const { this->replaceThread(thread.toThread()); }; std::vector SQLiteQueryExecutor::getAllMessagesWeb() const { auto allMessages = this->getAllMessages(); std::vector allMessageWithMedias; for (auto &messageWitMedia : allMessages) { allMessageWithMedias.push_back( {std::move(messageWitMedia.first), messageWitMedia.second}); } return allMessageWithMedias; } void SQLiteQueryExecutor::replaceMessageWeb(const WebMessage &message) const { this->replaceMessage(message.toMessage()); }; NullableString SQLiteQueryExecutor::getOlmPersistAccountDataWeb() const { std::optional accountData = this->getOlmPersistAccountData(); if (!accountData.has_value()) { return NullableString(); } return std::make_unique(accountData.value()); } #else void SQLiteQueryExecutor::clearSensitiveData() { SQLiteQueryExecutor::closeConnection(); if (file_exists(SQLiteQueryExecutor::sqliteFilePath) && std::remove(SQLiteQueryExecutor::sqliteFilePath.c_str())) { std::ostringstream errorStream; errorStream << "Failed to delete database file. Details: " << strerror(errno); throw std::system_error(errno, std::generic_category(), errorStream.str()); } SQLiteQueryExecutor::assign_encryption_key(); SQLiteQueryExecutor::migrate(); } void SQLiteQueryExecutor::initialize(std::string &databasePath) { std::call_once(SQLiteQueryExecutor::initialized, [&databasePath]() { SQLiteQueryExecutor::sqliteFilePath = databasePath; folly::Optional maybeEncryptionKey = CommSecureStore::get(SQLiteQueryExecutor::secureStoreEncryptionKeyID); if (file_exists(databasePath) && maybeEncryptionKey) { SQLiteQueryExecutor::encryptionKey = maybeEncryptionKey.value(); return; } SQLiteQueryExecutor::assign_encryption_key(); }); } void SQLiteQueryExecutor::createMainCompaction(std::string backupID) const { std::string finalBackupPath = PlatformSpecificTools::getBackupFilePath(backupID, false); std::string finalAttachmentsPath = PlatformSpecificTools::getBackupFilePath(backupID, true); std::string tempBackupPath = finalBackupPath + "_tmp"; std::string tempAttachmentsPath = finalAttachmentsPath + "_tmp"; if (file_exists(tempBackupPath)) { Logger::log( "Attempting to delete temporary backup file from previous backup " "attempt."); attempt_delete_file( tempBackupPath, "Failed to delete temporary backup file from previous backup attempt."); } if (file_exists(tempAttachmentsPath)) { Logger::log( "Attempting to delete temporary attachments file from previous backup " "attempt."); attempt_delete_file( tempAttachmentsPath, "Failed to delete temporary attachments file from previous backup " "attempt."); } sqlite3 *backupDB; sqlite3_open(tempBackupPath.c_str(), &backupDB); set_encryption_key(backupDB); sqlite3_backup *backupObj = sqlite3_backup_init( backupDB, "main", SQLiteQueryExecutor::getConnection(), "main"); if (!backupObj) { std::stringstream error_message; error_message << "Failed to init backup for main compaction. Details: " << sqlite3_errmsg(backupDB) << std::endl; sqlite3_close(backupDB); throw std::runtime_error(error_message.str()); } int backupResult = sqlite3_backup_step(backupObj, -1); sqlite3_backup_finish(backupObj); if (backupResult == SQLITE_BUSY || backupResult == SQLITE_LOCKED) { sqlite3_close(backupDB); throw std::runtime_error( "Programmer error. Database in transaction during backup attempt."); } else if (backupResult != SQLITE_DONE) { sqlite3_close(backupDB); std::stringstream error_message; error_message << "Failed to create database backup. Details: " << sqlite3_errstr(backupResult); throw std::runtime_error(error_message.str()); } executeQuery(backupDB, "VACUUM;"); sqlite3_close(backupDB); attempt_rename_file( tempBackupPath, finalBackupPath, "Failed to rename complete temporary backup file to final backup file."); std::ofstream tempAttachmentsFile(tempAttachmentsPath); if (!tempAttachmentsFile.is_open()) { throw std::runtime_error( "Unable to create attachments file for backup id: " + backupID); } std::string getAllBlobServiceMediaSQL = "SELECT * FROM media WHERE uri LIKE 'comm-blob-service://%';"; std::vector blobServiceMedia = getAllEntities( SQLiteQueryExecutor::getConnection(), getAllBlobServiceMediaSQL); for (const auto &media : blobServiceMedia) { std::string blobServiceURI = media.uri; std::string blobHash = blob_hash_from_blob_service_uri(blobServiceURI); tempAttachmentsFile << blobHash << "\n"; } tempAttachmentsFile.close(); attempt_rename_file( tempAttachmentsPath, finalAttachmentsPath, "Failed to rename complete temporary attachments file to final " "attachments file."); + + this->setMetadata("backupID", backupID); + this->clearMetadata("logID"); + if (StaffUtils::isStaffRelease()) { + SQLiteQueryExecutor::connectionManager.setLogsMonitoring(true); + } } void SQLiteQueryExecutor::assign_encryption_key() { std::string encryptionKey = comm::crypto::Tools::generateRandomHexString( SQLiteQueryExecutor::sqlcipherEncryptionKeySize); CommSecureStore::set( SQLiteQueryExecutor::secureStoreEncryptionKeyID, encryptionKey); SQLiteQueryExecutor::encryptionKey = encryptionKey; } + +void SQLiteQueryExecutor::captureBackupLogs() const { + std::string backupID = this->getMetadata("backupID"); + if (!backupID.size()) { + return; + } + + std::string logID = this->getMetadata("logID"); + if (!logID.size()) { + logID = "0"; + } + + bool newLogCreated = + SQLiteQueryExecutor::connectionManager.captureLogs(backupID, logID); + if (!newLogCreated) { + return; + } + this->setMetadata("logID", std::to_string(std::stoi(logID) + 1)); +} #endif void SQLiteQueryExecutor::restoreFromMainCompaction( std::string mainCompactionPath, std::string mainCompactionEncryptionKey) const { if (!file_exists(mainCompactionPath)) { throw std::runtime_error("Restore attempt but backup file does not exist."); } sqlite3 *backupDB; if (!is_database_queryable( backupDB, true, mainCompactionPath, mainCompactionEncryptionKey)) { throw std::runtime_error("Backup file or encryption key corrupted."); } // We don't want to run `PRAGMA key = ...;` // on main web database. The context is here: // https://linear.app/comm/issue/ENG-6398/issues-with-sqlcipher-on-web #ifdef EMSCRIPTEN std::string plaintextBackupPath = mainCompactionPath + "_plaintext"; if (file_exists(plaintextBackupPath)) { attempt_delete_file( plaintextBackupPath, "Failed to delete plaintext backup file from previous backup attempt."); } std::string plaintextMigrationDBQuery = "PRAGMA key = \"x'" + mainCompactionEncryptionKey + "'\";" "ATTACH DATABASE '" + plaintextBackupPath + "' AS plaintext KEY '';" "SELECT sqlcipher_export('plaintext');" "DETACH DATABASE plaintext;"; sqlite3_open(mainCompactionPath.c_str(), &backupDB); char *plaintextMigrationErr; sqlite3_exec( backupDB, plaintextMigrationDBQuery.c_str(), nullptr, nullptr, &plaintextMigrationErr); sqlite3_close(backupDB); if (plaintextMigrationErr) { std::stringstream error_message; error_message << "Failed to migrate backup SQLCipher file to plaintext " "SQLite file. Details" << plaintextMigrationErr << std::endl; std::string error_message_str = error_message.str(); sqlite3_free(plaintextMigrationErr); throw std::runtime_error(error_message_str); } sqlite3_open(plaintextBackupPath.c_str(), &backupDB); #else sqlite3_open(mainCompactionPath.c_str(), &backupDB); set_encryption_key(backupDB, mainCompactionEncryptionKey); #endif sqlite3_backup *backupObj = sqlite3_backup_init( SQLiteQueryExecutor::getConnection(), "main", backupDB, "main"); if (!backupObj) { std::stringstream error_message; error_message << "Failed to init backup for main compaction. Details: " << sqlite3_errmsg(SQLiteQueryExecutor::getConnection()) << std::endl; sqlite3_close(backupDB); throw std::runtime_error(error_message.str()); } int backupResult = sqlite3_backup_step(backupObj, -1); sqlite3_backup_finish(backupObj); sqlite3_close(backupDB); if (backupResult == SQLITE_BUSY || backupResult == SQLITE_LOCKED) { throw std::runtime_error( "Programmer error. Database in transaction during restore attempt."); } else if (backupResult != SQLITE_DONE) { std::stringstream error_message; error_message << "Failed to restore database from backup. Details: " << sqlite3_errstr(backupResult); throw std::runtime_error(error_message.str()); } #ifdef EMSCRIPTEN attempt_delete_file( plaintextBackupPath, "Failed to delete plaintext compaction file after successful restore."); #endif attempt_delete_file( mainCompactionPath, "Failed to delete main compaction file after successful restore."); } } // namespace comm diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h index d24440a38..743cbad0f 100644 --- a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h +++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h @@ -1,115 +1,119 @@ #pragma once #include "../CryptoTools/Persist.h" #include "DatabaseQueryExecutor.h" +#include "NativeSQLiteConnectionManager.h" #include "entities/Draft.h" #include "entities/KeyserverInfo.h" #include "entities/UserInfo.h" #include #include namespace comm { class SQLiteQueryExecutor : public DatabaseQueryExecutor { static void migrate(); static sqlite3 *getConnection(); static void closeConnection(); static std::once_flag initialized; static int sqlcipherEncryptionKeySize; static std::string secureStoreEncryptionKeyID; - static sqlite3 *dbConnection; #ifndef EMSCRIPTEN + static NativeSQLiteConnectionManager connectionManager; static void assign_encryption_key(); +#else + static SQLiteConnectionManager connectionManager; #endif public: static std::string sqliteFilePath; static std::string encryptionKey; SQLiteQueryExecutor(); ~SQLiteQueryExecutor(); SQLiteQueryExecutor(std::string sqliteFilePath); std::unique_ptr getThread(std::string threadID) const override; std::string getDraft(std::string key) const override; void updateDraft(std::string key, std::string text) const override; bool moveDraft(std::string oldKey, std::string newKey) const override; std::vector getAllDrafts() const override; void removeAllDrafts() const override; void removeDrafts(const std::vector &ids) const override; void removeAllMessages() const override; std::vector>> getAllMessages() const override; void removeMessages(const std::vector &ids) const override; void removeMessagesForThreads( const std::vector &threadIDs) const override; void replaceMessage(const Message &message) const override; void rekeyMessage(std::string from, std::string to) const override; void replaceMessageStoreThreads( const std::vector &threads) const override; void removeMessageStoreThreads(const std::vector &ids) const override; void removeAllMessageStoreThreads() const override; std::vector getAllMessageStoreThreads() const override; void removeAllMedia() const override; void removeMediaForMessages( const std::vector &msg_ids) const override; void removeMediaForMessage(std::string msg_id) const override; void removeMediaForThreads( const std::vector &thread_ids) const override; void replaceMedia(const Media &media) const override; void rekeyMediaContainers(std::string from, std::string to) const override; std::vector getAllThreads() const override; void removeThreads(std::vector ids) const override; void replaceThread(const Thread &thread) const override; void removeAllThreads() const override; void replaceReport(const Report &report) const override; void removeReports(const std::vector &ids) const override; void removeAllReports() const override; std::vector getAllReports() const override; void setPersistStorageItem(std::string key, std::string item) const override; void removePersistStorageItem(std::string key) const override; std::string getPersistStorageItem(std::string key) const override; void replaceUser(const UserInfo &user_info) const override; void removeUsers(const std::vector &ids) const override; void removeAllUsers() const override; std::vector getAllUsers() const override; void replaceKeyserver(const KeyserverInfo &keyserver_info) const override; void removeKeyservers(const std::vector &ids) const override; void removeAllKeyservers() const override; std::vector getAllKeyservers() const override; void beginTransaction() const override; void commitTransaction() const override; void rollbackTransaction() const override; std::vector getOlmPersistSessionsData() const override; std::optional getOlmPersistAccountData() const override; void storeOlmPersistSession(const OlmPersistSession &session) const override; void storeOlmPersistAccount(const std::string &accountData) const override; void storeOlmPersistData(crypto::Persist persist) const override; void setNotifyToken(std::string token) const override; void clearNotifyToken() const override; void setCurrentUserID(std::string userID) const override; std::string getCurrentUserID() const override; void setMetadata(std::string entry_name, std::string data) const override; void clearMetadata(std::string entry_name) const override; std::string getMetadata(std::string entry_name) const override; void restoreFromMainCompaction( std::string mainCompactionPath, std::string mainCompactionEncryptionKey) const override; #ifdef EMSCRIPTEN std::vector getAllThreadsWeb() const override; void replaceThreadWeb(const WebThread &thread) const override; std::vector getAllMessagesWeb() const override; void replaceMessageWeb(const WebMessage &message) const override; NullableString getOlmPersistAccountDataWeb() const override; #else static void clearSensitiveData(); static void initialize(std::string &databasePath); void createMainCompaction(std::string backupID) const override; + void captureBackupLogs() const override; #endif }; } // namespace comm diff --git a/native/ios/Comm.xcodeproj/project.pbxproj b/native/ios/Comm.xcodeproj/project.pbxproj index bea30b9d3..87515c60b 100644 --- a/native/ios/Comm.xcodeproj/project.pbxproj +++ b/native/ios/Comm.xcodeproj/project.pbxproj @@ -1,1852 +1,1864 @@ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 54; objects = { /* Begin PBXBuildFile section */ 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 1F537ACC7B60DC049C0ECFA7 /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 769A87FB41BCE3FEF97FD59A /* ExpoModulesProvider.swift */; }; 71142A7726C2650B0039DCBD /* CommSecureStoreIOSWrapper.mm in Sources */ = {isa = PBXBuildFile; fileRef = 71142A7626C2650A0039DCBD /* CommSecureStoreIOSWrapper.mm */; }; 711B408425DA97F9005F8F06 /* dummy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F26E81B24440D87004049C6 /* dummy.swift */; }; 71762A75270D8AAE00F565ED /* PlatformSpecificTools.mm in Sources */ = {isa = PBXBuildFile; fileRef = 71762A74270D8AAE00F565ED /* PlatformSpecificTools.mm */; }; 718DE99E2653D41C00365824 /* WorkerThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 718DE99C2653D41C00365824 /* WorkerThread.cpp */; }; 71BE844A2636A944002849D2 /* CommCoreModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 71BE843C2636A944002849D2 /* CommCoreModule.cpp */; }; 71BE844B2636A944002849D2 /* SQLiteQueryExecutor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 71BE84412636A944002849D2 /* SQLiteQueryExecutor.cpp */; }; 71BF5B7126B3FF0900EDE27D /* Session.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 71BF5B6F26B3FF0900EDE27D /* Session.cpp */; }; 71BF5B7526B401D300EDE27D /* Tools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 71BF5B7326B401D300EDE27D /* Tools.cpp */; }; 71BF5B7F26BBDD7400EDE27D /* CryptoModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 71BF5B7B26BBDA6100EDE27D /* CryptoModule.cpp */; }; 71CA4A64262DA8E500835C89 /* Logger.mm in Sources */ = {isa = PBXBuildFile; fileRef = 71CA4A63262DA8E500835C89 /* Logger.mm */; }; 71CA4AEC262F236100835C89 /* Tools.mm in Sources */ = {isa = PBXBuildFile; fileRef = 71CA4AEB262F236100835C89 /* Tools.mm */; }; 71D4D7CC26C50B1000FCDBCD /* CommSecureStore.mm in Sources */ = {isa = PBXBuildFile; fileRef = 71D4D7CB26C50B1000FCDBCD /* CommSecureStore.mm */; }; 724995D527B4103A00323FCE /* NotificationService.mm in Sources */ = {isa = PBXBuildFile; fileRef = 724995D427B4103A00323FCE /* NotificationService.mm */; }; 724995D927B4103A00323FCE /* NotificationService.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 724995D127B4103A00323FCE /* NotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 724995FB27BA9E8D00323FCE /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 724995FA27BA9E8C00323FCE /* UserNotifications.framework */; }; 7F0C6E31291C4468002AA2D9 /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EEB3E70587B0ADAD05237B0 /* ExpoModulesProvider.swift */; }; 7F761E602201141E001B6FB7 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F761E292201141E001B6FB7 /* JavaScriptCore.framework */; }; 7F788C2C248AA2140098F071 /* SplashScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7F788C2B248AA2130098F071 /* SplashScreen.storyboard */; }; 7F8D602126535E060053CB29 /* OpenSans-Semibold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7F8D601E26535E060053CB29 /* OpenSans-Semibold.ttf */; }; 7F8D602226535E060053CB29 /* Anaheim-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7F8D601F26535E060053CB29 /* Anaheim-Regular.ttf */; }; 7F8D602326535E060053CB29 /* OpenSans-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7F8D602026535E060053CB29 /* OpenSans-Regular.ttf */; }; 7F8D602826535F240053CB29 /* IBMPlexSans-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7F8D602726535EEE0053CB29 /* IBMPlexSans-Bold.ttf */; }; 7F8D602926535F2A0053CB29 /* IBMPlexSans-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7F8D602626535EEE0053CB29 /* IBMPlexSans-Regular.ttf */; }; 7FA2DCDE293E62F500991BA4 /* CommIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7FA2DCDC293E62F500991BA4 /* CommIcons.ttf */; }; 7FA2DCDF293E62F500991BA4 /* SWMansionIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7FA2DCDD293E62F500991BA4 /* SWMansionIcons.ttf */; }; 7FBB2A7629E94539002C6493 /* utilsJSI-generated.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7FBB2A7529E94539002C6493 /* utilsJSI-generated.cpp */; }; 7FBB2A7829E945C2002C6493 /* CommUtilsModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7FBB2A7329E944FD002C6493 /* CommUtilsModule.cpp */; }; 7FBB2A7B29EEA2A4002C6493 /* Base64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7FBB2A7A29EEA2A4002C6493 /* Base64.cpp */; }; 7FE4D9F5291DFE9300667BF6 /* commJSI-generated.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7FE4D9F4291DFE9300667BF6 /* commJSI-generated.cpp */; }; 8B38121629CE5742000C52E9 /* RustPromiseManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8B38121529CE5742000C52E9 /* RustPromiseManager.cpp */; }; 8B652FA6295EAA5B009F8163 /* RustCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8B652FA5295EAA5B009F8163 /* RustCallback.cpp */; }; 8B99BAAC28D50F3000EB5ADB /* libnative_rust_library.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B99BAAB28D50F3000EB5ADB /* libnative_rust_library.a */; }; 8B99BAAE28D511FF00EB5ADB /* lib.rs.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B99BAAD28D511FF00EB5ADB /* lib.rs.cc */; }; 8BC9568529FC49B00060AE4A /* JSIRust.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8BC9568429FC49B00060AE4A /* JSIRust.cpp */; }; 8E2CC2592B5C99B0000C94D6 /* KeyserverStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E2CC2582B5C99B0000C94D6 /* KeyserverStore.cpp */; }; 8E3994552B039A7C00D5E950 /* UserStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E3994532B039A7C00D5E950 /* UserStore.cpp */; }; 8E43C32C291E5B4A009378F5 /* TerminateApp.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8E43C32B291E5B4A009378F5 /* TerminateApp.mm */; }; 8E86A6D329537EBB000BBE7D /* DatabaseManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E86A6D229537EBB000BBE7D /* DatabaseManager.cpp */; }; 8EA59BD62A6E8E0400EB4F53 /* DraftStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8EA59BD42A6E8E0400EB4F53 /* DraftStore.cpp */; }; 8EA59BD92A73DAB000EB4F53 /* rustJSI-generated.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8EA59BD72A73DAB000EB4F53 /* rustJSI-generated.cpp */; }; 8EF775682A74032C0046A385 /* CommRustModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8EF775672A74032C0046A385 /* CommRustModule.cpp */; }; 8EF7756B2A7433630046A385 /* ThreadStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8EF775692A7433630046A385 /* ThreadStore.cpp */; }; 8EF7756E2A7513F40046A385 /* MessageStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8EF7756D2A7513F40046A385 /* MessageStore.cpp */; }; 8EF775712A751B780046A385 /* ReportStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8EF7756F2A751B780046A385 /* ReportStore.cpp */; }; B71AFF1F265EDD8600B22352 /* IBMPlexSans-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = B71AFF1E265EDD8600B22352 /* IBMPlexSans-Medium.ttf */; }; CB01F0C22B67EF5A0089E1F9 /* SQLiteDataConverters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB01F0C12B67EF470089E1F9 /* SQLiteDataConverters.cpp */; }; CB01F0C42B67F3A10089E1F9 /* SQLiteStatementWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB01F0C32B67F3970089E1F9 /* SQLiteStatementWrapper.cpp */; }; CB1648AF27CFBE6A00394D9D /* CryptoModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 71BF5B7B26BBDA6100EDE27D /* CryptoModule.cpp */; }; CB24361829A39A2500FEC4E1 /* NotificationsCryptoModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB24361729A39A2500FEC4E1 /* NotificationsCryptoModule.cpp */; }; CB2689002A2DF58000EC7300 /* CommConstants.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB2688FF2A2DF56000EC7300 /* CommConstants.cpp */; }; CB38B48228771C7A00171182 /* NonBlockingLock.mm in Sources */ = {isa = PBXBuildFile; fileRef = CB38B47B287718A200171182 /* NonBlockingLock.mm */; }; CB38B48328771C8300171182 /* NonBlockingLock.mm in Sources */ = {isa = PBXBuildFile; fileRef = CB38B47B287718A200171182 /* NonBlockingLock.mm */; }; CB38B48428771CAF00171182 /* EncryptedFileUtils.mm in Sources */ = {isa = PBXBuildFile; fileRef = CB38B47D2877194100171182 /* EncryptedFileUtils.mm */; }; CB38B48528771CB800171182 /* EncryptedFileUtils.mm in Sources */ = {isa = PBXBuildFile; fileRef = CB38B47D2877194100171182 /* EncryptedFileUtils.mm */; }; CB38B48628771CDD00171182 /* TemporaryMessageStorage.mm in Sources */ = {isa = PBXBuildFile; fileRef = CB38B47F28771A3B00171182 /* TemporaryMessageStorage.mm */; }; CB38B48728771CE500171182 /* TemporaryMessageStorage.mm in Sources */ = {isa = PBXBuildFile; fileRef = CB38B47F28771A3B00171182 /* TemporaryMessageStorage.mm */; }; CB38F2B1286C6C870010535C /* MessageOperationsUtilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB38F2AF286C6C870010535C /* MessageOperationsUtilities.cpp */; }; CB3C0A3B2A125C8F009BD4DA /* NotificationsCryptoModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB24361729A39A2500FEC4E1 /* NotificationsCryptoModule.cpp */; }; CB3C621127CE4A320054F24C /* Logger.mm in Sources */ = {isa = PBXBuildFile; fileRef = 71CA4A63262DA8E500835C89 /* Logger.mm */; }; CB3C621227CE65030054F24C /* CommSecureStoreIOSWrapper.mm in Sources */ = {isa = PBXBuildFile; fileRef = 71142A7626C2650A0039DCBD /* CommSecureStoreIOSWrapper.mm */; }; + CB3CCB012B72470700793640 /* NativeSQLiteConnectionManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB3CCB002B7246F400793640 /* NativeSQLiteConnectionManager.cpp */; }; CB4821A927CFB153001AB7E1 /* WorkerThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 718DE99C2653D41C00365824 /* WorkerThread.cpp */; }; CB4821AA27CFB153001AB7E1 /* Tools.mm in Sources */ = {isa = PBXBuildFile; fileRef = 71CA4AEB262F236100835C89 /* Tools.mm */; }; CB4821AC27CFB17C001AB7E1 /* Session.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 71BF5B6F26B3FF0900EDE27D /* Session.cpp */; }; CB4821AE27CFB187001AB7E1 /* Tools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 71BF5B7326B401D300EDE27D /* Tools.cpp */; }; CB4821AF27CFB19D001AB7E1 /* PlatformSpecificTools.mm in Sources */ = {isa = PBXBuildFile; fileRef = 71762A74270D8AAE00F565ED /* PlatformSpecificTools.mm */; }; CB74AB1C2B2AFF6E00CBB494 /* CommServicesAuthMetadataEmitter.mm in Sources */ = {isa = PBXBuildFile; fileRef = CB74AB1B2B2AFF6E00CBB494 /* CommServicesAuthMetadataEmitter.mm */; }; CB74AB202B2B0C0A00CBB494 /* RustCSAMetadataEmitter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB74AB1E2B2B0C0900CBB494 /* RustCSAMetadataEmitter.cpp */; }; CB7EF17E295C674300B17035 /* CommIOSNotifications.mm in Sources */ = {isa = PBXBuildFile; fileRef = CB7EF17D295C5D1800B17035 /* CommIOSNotifications.mm */; }; CB7EF180295C674300B17035 /* CommIOSNotificationsBridgeQueue.mm in Sources */ = {isa = PBXBuildFile; fileRef = CB7EF17B295C580500B17035 /* CommIOSNotificationsBridgeQueue.mm */; }; CB90951F29534B32002F2A7F /* CommSecureStore.mm in Sources */ = {isa = PBXBuildFile; fileRef = 71D4D7CB26C50B1000FCDBCD /* CommSecureStore.mm */; }; + CBA5F8852B6979F7005BE700 /* SQLiteConnectionManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CBA5F8842B6979ED005BE700 /* SQLiteConnectionManager.cpp */; }; CBAAA4702B459181007599DA /* BackupOperationsExecutor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CBAAA46E2B459181007599DA /* BackupOperationsExecutor.cpp */; }; 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 */; }; DFD5E77E2B05264000C32B6A /* AESCrypto.mm in Sources */ = {isa = PBXBuildFile; fileRef = DFD5E77D2B05264000C32B6A /* AESCrypto.mm */; }; DFD5E7862B052B1400C32B6A /* RustAESCrypto.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFD5E7842B052B1400C32B6A /* RustAESCrypto.cpp */; }; F02C296C528B51ADAB5AA19D /* libPods-NotificationService.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3EE4DCB430B05EC9DE7D7B01 /* libPods-NotificationService.a */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 713EE40B26C6676B003D7C48 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; proxyType = 1; remoteGlobalIDString = 13B07F861A680F5B00A75B9A; remoteInfo = Comm; }; 724995D727B4103A00323FCE /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; proxyType = 1; remoteGlobalIDString = 724995D027B4103A00323FCE; remoteInfo = NotificationService; }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ 724995DA27B4103A00323FCE /* Embed App Extensions */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 13; files = ( 724995D927B4103A00323FCE /* NotificationService.appex in Embed App Extensions */, ); name = "Embed App Extensions"; runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 13B07F961A680F5B00A75B9A /* Comm.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Comm.app; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Comm/AppDelegate.h; sourceTree = ""; }; 13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = Comm/AppDelegate.mm; sourceTree = ""; }; 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Comm/Images.xcassets; sourceTree = ""; }; 13B07FB61A68108700A75B9A /* Info.release.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.release.plist; path = Comm/Info.release.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Comm/main.m; sourceTree = ""; }; 2DDA0A22FECC9DAA5C19C35D /* Metadata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Metadata.h; sourceTree = ""; }; 3EE4DCB430B05EC9DE7D7B01 /* libPods-NotificationService.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-NotificationService.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 3EEB3E70587B0ADAD05237B0 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-Comm/ExpoModulesProvider.swift"; sourceTree = ""; }; 71142A7526C2650A0039DCBD /* CommSecureStoreIOSWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommSecureStoreIOSWrapper.h; path = Comm/CommSecureStoreIOSWrapper.h; sourceTree = ""; }; 71142A7626C2650A0039DCBD /* CommSecureStoreIOSWrapper.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = CommSecureStoreIOSWrapper.mm; path = Comm/CommSecureStoreIOSWrapper.mm; sourceTree = ""; }; 711CF80E25DC096000A00FBD /* libFolly.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libFolly.a; sourceTree = BUILT_PRODUCTS_DIR; }; 713EE40626C6676B003D7C48 /* CommTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CommTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 713EE40A26C6676B003D7C48 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 71762A74270D8AAE00F565ED /* PlatformSpecificTools.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PlatformSpecificTools.mm; path = Comm/PlatformSpecificTools.mm; sourceTree = ""; }; 718DE99C2653D41C00365824 /* WorkerThread.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WorkerThread.cpp; sourceTree = ""; }; 718DE99D2653D41C00365824 /* WorkerThread.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WorkerThread.h; sourceTree = ""; }; 71B8CCBD26BD4DEB0040C0A2 /* CommSecureStore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CommSecureStore.h; sourceTree = ""; }; 71BE84392636A944002849D2 /* Logger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Logger.h; sourceTree = ""; }; 71BE843C2636A944002849D2 /* CommCoreModule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CommCoreModule.cpp; sourceTree = ""; }; 71BE843E2636A944002849D2 /* CommCoreModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommCoreModule.h; sourceTree = ""; }; 71BE84402636A944002849D2 /* DatabaseQueryExecutor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DatabaseQueryExecutor.h; sourceTree = ""; }; 71BE84412636A944002849D2 /* SQLiteQueryExecutor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SQLiteQueryExecutor.cpp; sourceTree = ""; }; 71BE84422636A944002849D2 /* SQLiteQueryExecutor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SQLiteQueryExecutor.h; sourceTree = ""; }; 71BE84432636A944002849D2 /* DatabaseManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DatabaseManager.h; sourceTree = ""; }; 71BE84452636A944002849D2 /* Draft.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Draft.h; sourceTree = ""; }; 71BF5B6F26B3FF0900EDE27D /* Session.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Session.cpp; sourceTree = ""; }; 71BF5B7026B3FF0900EDE27D /* Session.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Session.h; sourceTree = ""; }; 71BF5B7226B3FFBC00EDE27D /* Persist.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Persist.h; sourceTree = ""; }; 71BF5B7326B401D300EDE27D /* Tools.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Tools.cpp; sourceTree = ""; }; 71BF5B7426B401D300EDE27D /* Tools.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Tools.h; sourceTree = ""; }; 71BF5B7A26BBDA6000EDE27D /* CryptoModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CryptoModule.h; sourceTree = ""; }; 71BF5B7B26BBDA6100EDE27D /* CryptoModule.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CryptoModule.cpp; sourceTree = ""; }; 71CA4A63262DA8E500835C89 /* Logger.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = Logger.mm; path = Comm/Logger.mm; sourceTree = ""; }; 71CA4AEA262F230A00835C89 /* Tools.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Tools.h; path = Comm/Tools.h; sourceTree = ""; }; 71CA4AEB262F236100835C89 /* Tools.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = Tools.mm; path = Comm/Tools.mm; sourceTree = ""; }; 71D4D7CB26C50B1000FCDBCD /* CommSecureStore.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = CommSecureStore.mm; path = Comm/CommSecureStore.mm; sourceTree = ""; }; 71DC160C270C43D300822863 /* PlatformSpecificTools.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PlatformSpecificTools.h; sourceTree = ""; }; 724995D127B4103A00323FCE /* NotificationService.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = NotificationService.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 724995D327B4103A00323FCE /* NotificationService.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NotificationService.h; sourceTree = ""; }; 724995D427B4103A00323FCE /* NotificationService.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = NotificationService.mm; sourceTree = ""; }; 724995D627B4103A00323FCE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 724995FA27BA9E8C00323FCE /* UserNotifications.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotifications.framework; path = System/Library/Frameworks/UserNotifications.framework; sourceTree = SDKROOT; }; 75291F0228F9A09E00F4C80E /* DeviceID.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DeviceID.h; sourceTree = ""; }; 75291F0328F9A0AE00F4C80E /* DeviceID.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DeviceID.cpp; sourceTree = ""; }; 769A87FB41BCE3FEF97FD59A /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-NotificationService/ExpoModulesProvider.swift"; sourceTree = ""; }; 7F26E81B24440D87004049C6 /* dummy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dummy.swift; sourceTree = ""; }; 7F446E2229C3AF3800670288 /* ReactionMessageSpec.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ReactionMessageSpec.h; path = PersistentStorageUtilities/MessageOperationsUtilities/MessageSpecs/ReactionMessageSpec.h; sourceTree = ""; }; 7F446E2329C3B2BE00670288 /* SidebarSourceMessageSpec.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SidebarSourceMessageSpec.h; path = PersistentStorageUtilities/MessageOperationsUtilities/MessageSpecs/SidebarSourceMessageSpec.h; sourceTree = ""; }; 7F554F822332D58B007CB9F7 /* Info.debug.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.debug.plist; path = Comm/Info.debug.plist; sourceTree = ""; }; 7F761E292201141E001B6FB7 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; 7F788C2B248AA2130098F071 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = SplashScreen.storyboard; sourceTree = ""; }; 7F8D601E26535E060053CB29 /* OpenSans-Semibold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "OpenSans-Semibold.ttf"; path = "Resources/OpenSans-Semibold.ttf"; sourceTree = ""; }; 7F8D601F26535E060053CB29 /* Anaheim-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Anaheim-Regular.ttf"; path = "Resources/Anaheim-Regular.ttf"; sourceTree = ""; }; 7F8D602026535E060053CB29 /* OpenSans-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "OpenSans-Regular.ttf"; path = "Resources/OpenSans-Regular.ttf"; sourceTree = ""; }; 7F8D602626535EEE0053CB29 /* IBMPlexSans-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "IBMPlexSans-Regular.ttf"; path = "Resources/IBMPlexSans-Regular.ttf"; sourceTree = ""; }; 7F8D602726535EEE0053CB29 /* IBMPlexSans-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "IBMPlexSans-Bold.ttf"; path = "Resources/IBMPlexSans-Bold.ttf"; sourceTree = ""; }; 7FA2DCDC293E62F500991BA4 /* CommIcons.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = CommIcons.ttf; path = ../fonts/CommIcons.ttf; sourceTree = ""; }; 7FA2DCDD293E62F500991BA4 /* SWMansionIcons.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = SWMansionIcons.ttf; path = ../fonts/SWMansionIcons.ttf; sourceTree = ""; }; 7FBB2A7329E944FD002C6493 /* CommUtilsModule.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CommUtilsModule.cpp; sourceTree = ""; }; 7FBB2A7429E9450E002C6493 /* CommUtilsModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CommUtilsModule.h; sourceTree = ""; }; 7FBB2A7529E94539002C6493 /* utilsJSI-generated.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "utilsJSI-generated.cpp"; sourceTree = ""; }; 7FBB2A7729E94541002C6493 /* utilsJSI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utilsJSI.h; sourceTree = ""; }; 7FBB2A7929EA752D002C6493 /* Base64.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Base64.h; sourceTree = ""; }; 7FBB2A7A29EEA2A4002C6493 /* Base64.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Base64.cpp; sourceTree = ""; }; 7FCEA2DC2444010B004017B1 /* Comm-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Comm-Bridging-Header.h"; sourceTree = ""; }; 7FCFD8BD1E81B8DF00629B0E /* Comm.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = Comm.entitlements; path = Comm/Comm.entitlements; sourceTree = ""; }; 7FE4D9F3291DFE9300667BF6 /* commJSI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = commJSI.h; sourceTree = ""; }; 7FE4D9F4291DFE9300667BF6 /* commJSI-generated.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "commJSI-generated.cpp"; sourceTree = ""; }; 891D1495EE1F375F3AF6C7ED /* Pods-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.debug.xcconfig"; sourceTree = ""; }; 8B38121529CE5742000C52E9 /* RustPromiseManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RustPromiseManager.cpp; sourceTree = ""; }; 8B652FA1295EA6B8009F8163 /* RustPromiseManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RustPromiseManager.h; sourceTree = ""; }; 8B652FA4295EA9F1009F8163 /* RustCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RustCallback.h; sourceTree = ""; }; 8B652FA5295EAA5B009F8163 /* RustCallback.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RustCallback.cpp; sourceTree = ""; }; 8B99AF6D28D50D4800EB5ADB /* lib.rs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lib.rs.h; sourceTree = ""; }; 8B99B59928D50D4900EB5ADB /* cxx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cxx.h; sourceTree = ""; }; 8B99BAAB28D50F3000EB5ADB /* libnative_rust_library.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libnative_rust_library.a; path = ../native_rust_library/target/universal/release/libnative_rust_library.a; sourceTree = ""; }; 8B99BAAD28D511FF00EB5ADB /* lib.rs.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lib.rs.cc; sourceTree = ""; }; 8BC9568329FC49920060AE4A /* JSIRust.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSIRust.h; sourceTree = ""; }; 8BC9568429FC49B00060AE4A /* JSIRust.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSIRust.cpp; sourceTree = ""; }; 8E2CC2562B5C999A000C94D6 /* KeyserverStoreOperations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeyserverStoreOperations.h; sourceTree = ""; }; 8E2CC2572B5C99B0000C94D6 /* KeyserverStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KeyserverStore.h; path = PersistentStorageUtilities/DataStores/KeyserverStore.h; sourceTree = ""; }; 8E2CC2582B5C99B0000C94D6 /* KeyserverStore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = KeyserverStore.cpp; path = PersistentStorageUtilities/DataStores/KeyserverStore.cpp; sourceTree = ""; }; 8E3994532B039A7C00D5E950 /* UserStore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UserStore.cpp; path = PersistentStorageUtilities/DataStores/UserStore.cpp; sourceTree = ""; }; 8E3994542B039A7C00D5E950 /* UserStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UserStore.h; path = PersistentStorageUtilities/DataStores/UserStore.h; sourceTree = ""; }; 8E3994562B039A9300D5E950 /* UserStoreOperations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserStoreOperations.h; sourceTree = ""; }; 8E43C32B291E5B4A009378F5 /* TerminateApp.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = TerminateApp.mm; path = Comm/TerminateApp.mm; sourceTree = ""; }; 8E43C32E291E5B9D009378F5 /* TerminateApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TerminateApp.h; path = ../cpp/CommonCpp/Tools/TerminateApp.h; sourceTree = ""; }; 8E86A6D229537EBB000BBE7D /* DatabaseManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DatabaseManager.cpp; sourceTree = ""; }; 8EA59BD22A6E800100EB4F53 /* NativeModuleUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeModuleUtils.h; sourceTree = ""; }; 8EA59BD32A6E8CB700EB4F53 /* BaseDataStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BaseDataStore.h; path = PersistentStorageUtilities/DataStores/BaseDataStore.h; sourceTree = ""; }; 8EA59BD42A6E8E0400EB4F53 /* DraftStore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DraftStore.cpp; path = PersistentStorageUtilities/DataStores/DraftStore.cpp; sourceTree = ""; }; 8EA59BD52A6E8E0400EB4F53 /* DraftStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DraftStore.h; path = PersistentStorageUtilities/DataStores/DraftStore.h; sourceTree = ""; }; 8EA59BD72A73DAB000EB4F53 /* rustJSI-generated.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "rustJSI-generated.cpp"; sourceTree = ""; }; 8EA59BD82A73DAB000EB4F53 /* rustJSI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rustJSI.h; sourceTree = ""; }; 8EE6E49F2A39CCAB00AE6BCD /* ReportStoreOperations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReportStoreOperations.h; sourceTree = ""; }; 8EE6E4A02A39CCAB00AE6BCD /* DraftStoreOperations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DraftStoreOperations.h; sourceTree = ""; }; 8EF775662A74032C0046A385 /* CommRustModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommRustModule.h; sourceTree = ""; }; 8EF775672A74032C0046A385 /* CommRustModule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CommRustModule.cpp; sourceTree = ""; }; 8EF775692A7433630046A385 /* ThreadStore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadStore.cpp; path = PersistentStorageUtilities/DataStores/ThreadStore.cpp; sourceTree = ""; }; 8EF7756A2A7433630046A385 /* ThreadStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadStore.h; path = PersistentStorageUtilities/DataStores/ThreadStore.h; sourceTree = ""; }; 8EF7756C2A7513F40046A385 /* MessageStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MessageStore.h; path = PersistentStorageUtilities/DataStores/MessageStore.h; sourceTree = ""; }; 8EF7756D2A7513F40046A385 /* MessageStore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MessageStore.cpp; path = PersistentStorageUtilities/DataStores/MessageStore.cpp; sourceTree = ""; }; 8EF7756F2A751B780046A385 /* ReportStore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ReportStore.cpp; path = PersistentStorageUtilities/DataStores/ReportStore.cpp; sourceTree = ""; }; 8EF775702A751B780046A385 /* ReportStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ReportStore.h; path = PersistentStorageUtilities/DataStores/ReportStore.h; sourceTree = ""; }; 913E5A7BDECB327E3DE11053 /* Pods-NotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.release.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.release.xcconfig"; sourceTree = ""; }; 994BEBDD4E4959F69CEA0BC3 /* libPods-Comm.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Comm.a"; sourceTree = BUILT_PRODUCTS_DIR; }; B7055C6B26E477CF00BE0548 /* MessageStoreOperations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MessageStoreOperations.h; sourceTree = ""; }; B70FBC1226B047050040F480 /* Message.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Message.h; sourceTree = ""; }; B71AFF1E265EDD8600B22352 /* IBMPlexSans-Medium.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "IBMPlexSans-Medium.ttf"; path = "Resources/IBMPlexSans-Medium.ttf"; sourceTree = ""; }; B7906F692720905A009BBBF5 /* ThreadStoreOperations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ThreadStoreOperations.h; sourceTree = ""; }; B7906F6A27209091009BBBF5 /* OlmPersistAccount.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OlmPersistAccount.h; sourceTree = ""; }; B7906F6B27209091009BBBF5 /* OlmPersistSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OlmPersistSession.h; sourceTree = ""; }; B7906F6C27209091009BBBF5 /* Thread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Thread.h; sourceTree = ""; }; B7E937CA26F448E700022A7C /* Media.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Media.h; sourceTree = ""; }; C562A7004903539402D988CE /* Pods-Comm.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Comm.release.xcconfig"; path = "Target Support Files/Pods-Comm/Pods-Comm.release.xcconfig"; sourceTree = ""; }; CB01F0BF2B67CDC20089E1F9 /* SQLiteStatementWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQLiteStatementWrapper.h; sourceTree = ""; }; CB01F0C02B67CDC20089E1F9 /* SQLiteDataConverters.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQLiteDataConverters.h; sourceTree = ""; }; CB01F0C12B67EF470089E1F9 /* SQLiteDataConverters.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SQLiteDataConverters.cpp; sourceTree = ""; }; CB01F0C32B67F3970089E1F9 /* SQLiteStatementWrapper.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SQLiteStatementWrapper.cpp; sourceTree = ""; }; CB24361629A397AB00FEC4E1 /* NotificationsCryptoModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NotificationsCryptoModule.h; path = Notifications/BackgroundDataStorage/NotificationsCryptoModule.h; sourceTree = ""; }; CB24361729A39A2500FEC4E1 /* NotificationsCryptoModule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NotificationsCryptoModule.cpp; path = Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp; sourceTree = ""; }; CB2688FE2A2DF55F00EC7300 /* CommConstants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CommConstants.h; sourceTree = ""; }; CB2688FF2A2DF56000EC7300 /* CommConstants.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CommConstants.cpp; sourceTree = ""; }; CB30C12327D0ACF700FBE8DE /* NotificationService.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NotificationService.entitlements; sourceTree = ""; }; CB38B4792877179A00171182 /* NonBlockingLock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NonBlockingLock.h; path = Comm/TemporaryMessageStorage/NonBlockingLock.h; sourceTree = ""; }; CB38B47B287718A200171182 /* NonBlockingLock.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = NonBlockingLock.mm; path = Comm/TemporaryMessageStorage/NonBlockingLock.mm; sourceTree = ""; }; CB38B47C2877190100171182 /* EncryptedFileUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = EncryptedFileUtils.h; path = Comm/TemporaryMessageStorage/EncryptedFileUtils.h; sourceTree = ""; }; CB38B47D2877194100171182 /* EncryptedFileUtils.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = EncryptedFileUtils.mm; path = Comm/TemporaryMessageStorage/EncryptedFileUtils.mm; sourceTree = ""; }; CB38B47E287719C500171182 /* TemporaryMessageStorage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TemporaryMessageStorage.h; path = Comm/TemporaryMessageStorage/TemporaryMessageStorage.h; sourceTree = ""; }; CB38B47F28771A3B00171182 /* TemporaryMessageStorage.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = TemporaryMessageStorage.mm; path = Comm/TemporaryMessageStorage/TemporaryMessageStorage.mm; sourceTree = ""; }; CB38F2AE286C6C870010535C /* MessageSpecs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MessageSpecs.h; path = PersistentStorageUtilities/MessageOperationsUtilities/MessageSpecs.h; sourceTree = ""; }; CB38F2AF286C6C870010535C /* MessageOperationsUtilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MessageOperationsUtilities.cpp; path = PersistentStorageUtilities/MessageOperationsUtilities/MessageOperationsUtilities.cpp; sourceTree = ""; }; CB38F2B0286C6C870010535C /* MessageOperationsUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MessageOperationsUtilities.h; path = PersistentStorageUtilities/MessageOperationsUtilities/MessageOperationsUtilities.h; sourceTree = ""; }; CB38F2B2286C6C970010535C /* CreateThreadMessageSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CreateThreadMessageSpec.h; path = PersistentStorageUtilities/MessageOperationsUtilities/MessageSpecs/CreateThreadMessageSpec.h; sourceTree = ""; }; CB38F2B3286C6C970010535C /* TextMessageSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TextMessageSpec.h; path = PersistentStorageUtilities/MessageOperationsUtilities/MessageSpecs/TextMessageSpec.h; sourceTree = ""; }; CB38F2B4286C6C970010535C /* CreateSidebarMessageSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CreateSidebarMessageSpec.h; path = PersistentStorageUtilities/MessageOperationsUtilities/MessageSpecs/CreateSidebarMessageSpec.h; sourceTree = ""; }; CB38F2B5286C6C970010535C /* ChangeRoleMessageSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ChangeRoleMessageSpec.h; path = PersistentStorageUtilities/MessageOperationsUtilities/MessageSpecs/ChangeRoleMessageSpec.h; sourceTree = ""; }; CB38F2B6286C6C970010535C /* RestoreEntryMessageSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RestoreEntryMessageSpec.h; path = PersistentStorageUtilities/MessageOperationsUtilities/MessageSpecs/RestoreEntryMessageSpec.h; sourceTree = ""; }; CB38F2B7286C6C970010535C /* MessageSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MessageSpec.h; path = PersistentStorageUtilities/MessageOperationsUtilities/MessageSpecs/MessageSpec.h; sourceTree = ""; }; CB38F2B8286C6C970010535C /* ChangeSettingsMessageSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ChangeSettingsMessageSpec.h; path = PersistentStorageUtilities/MessageOperationsUtilities/MessageSpecs/ChangeSettingsMessageSpec.h; sourceTree = ""; }; CB38F2B9286C6C970010535C /* UnsupportedMessageSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UnsupportedMessageSpec.h; path = PersistentStorageUtilities/MessageOperationsUtilities/MessageSpecs/UnsupportedMessageSpec.h; sourceTree = ""; }; CB38F2BA286C6C970010535C /* CreateEntryMessageSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CreateEntryMessageSpec.h; path = PersistentStorageUtilities/MessageOperationsUtilities/MessageSpecs/CreateEntryMessageSpec.h; sourceTree = ""; }; CB38F2BB286C6C970010535C /* EditEntryMessageSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EditEntryMessageSpec.h; path = PersistentStorageUtilities/MessageOperationsUtilities/MessageSpecs/EditEntryMessageSpec.h; sourceTree = ""; }; CB38F2BC286C6C970010535C /* CreateSubThreadMessageSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CreateSubThreadMessageSpec.h; path = PersistentStorageUtilities/MessageOperationsUtilities/MessageSpecs/CreateSubThreadMessageSpec.h; sourceTree = ""; }; CB38F2BD286C6C970010535C /* MultimediaMessageSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MultimediaMessageSpec.h; path = PersistentStorageUtilities/MessageOperationsUtilities/MessageSpecs/MultimediaMessageSpec.h; sourceTree = ""; }; CB38F2BE286C6C980010535C /* DeleteEntryMessageSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DeleteEntryMessageSpec.h; path = PersistentStorageUtilities/MessageOperationsUtilities/MessageSpecs/DeleteEntryMessageSpec.h; sourceTree = ""; }; CB38F2BF286C6C980010535C /* UpdateRelationshipMessageSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UpdateRelationshipMessageSpec.h; path = PersistentStorageUtilities/MessageOperationsUtilities/MessageSpecs/UpdateRelationshipMessageSpec.h; sourceTree = ""; }; CB3C621327CE66540054F24C /* libEXSecureStore.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libEXSecureStore.a; sourceTree = BUILT_PRODUCTS_DIR; }; + CB3CCAFF2B7246F400793640 /* NativeSQLiteConnectionManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NativeSQLiteConnectionManager.h; sourceTree = ""; }; + CB3CCB002B7246F400793640 /* NativeSQLiteConnectionManager.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = NativeSQLiteConnectionManager.cpp; sourceTree = ""; }; CB74AB1B2B2AFF6E00CBB494 /* CommServicesAuthMetadataEmitter.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = CommServicesAuthMetadataEmitter.mm; path = Comm/CommServicesAuthMetadataEmitter.mm; sourceTree = ""; }; CB74AB1E2B2B0C0900CBB494 /* RustCSAMetadataEmitter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RustCSAMetadataEmitter.cpp; sourceTree = ""; }; CB74AB1F2B2B0C0900CBB494 /* RustCSAMetadataEmitter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RustCSAMetadataEmitter.h; sourceTree = ""; }; CB7EF17B295C580500B17035 /* CommIOSNotificationsBridgeQueue.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = CommIOSNotificationsBridgeQueue.mm; path = Comm/CommIOSNotifications/CommIOSNotificationsBridgeQueue.mm; sourceTree = ""; }; CB7EF17C295C580500B17035 /* CommIOSNotificationsBridgeQueue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CommIOSNotificationsBridgeQueue.h; path = Comm/CommIOSNotifications/CommIOSNotificationsBridgeQueue.h; sourceTree = ""; }; CB7EF17D295C5D1800B17035 /* CommIOSNotifications.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = CommIOSNotifications.mm; path = Comm/CommIOSNotifications/CommIOSNotifications.mm; sourceTree = ""; }; CB90951929531663002F2A7F /* CommIOSNotifications.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommIOSNotifications.h; path = Comm/CommIOSNotifications/CommIOSNotifications.h; sourceTree = ""; }; + CBA5F8832B6979ED005BE700 /* SQLiteConnectionManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQLiteConnectionManager.h; sourceTree = ""; }; + CBA5F8842B6979ED005BE700 /* SQLiteConnectionManager.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SQLiteConnectionManager.cpp; sourceTree = ""; }; CBA784382B28AC4300E9F419 /* CommServicesAuthMetadataEmitter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CommServicesAuthMetadataEmitter.h; sourceTree = ""; }; CBAAA46E2B459181007599DA /* BackupOperationsExecutor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BackupOperationsExecutor.cpp; path = PersistentStorageUtilities/BackupOperationsUtilities/BackupOperationsExecutor.cpp; sourceTree = ""; }; CBAAA46F2B459181007599DA /* BackupOperationsExecutor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BackupOperationsExecutor.h; path = PersistentStorageUtilities/BackupOperationsUtilities/BackupOperationsExecutor.h; sourceTree = ""; }; CBCA09042A8E0E6B00F75B3E /* StaffUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StaffUtils.h; sourceTree = ""; }; CBCA09052A8E0E6B00F75B3E /* StaffUtils.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = StaffUtils.cpp; sourceTree = ""; }; CBCF57AB2B05096F00EC4BC0 /* AESCryptoModuleObjCCompat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AESCryptoModuleObjCCompat.h; path = Comm/CommAESCryptoUtils/AESCryptoModuleObjCCompat.h; sourceTree = ""; }; CBDEC69928ED859600C17588 /* GlobalDBSingleton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GlobalDBSingleton.h; sourceTree = ""; }; CBDEC69A28ED867000C17588 /* GlobalDBSingleton.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = GlobalDBSingleton.mm; path = Comm/GlobalDBSingleton.mm; sourceTree = ""; }; CBF9DAE22B595934000EE771 /* EntityQueryHelpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EntityQueryHelpers.h; sourceTree = ""; }; CBFBEEB82B4ED90600729F1D /* RustBackupExecutor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RustBackupExecutor.cpp; sourceTree = ""; }; CBFBEEB92B4ED90600729F1D /* RustBackupExecutor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RustBackupExecutor.h; sourceTree = ""; }; CBFE58272885852B003B94C9 /* ThreadOperations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadOperations.h; path = PersistentStorageUtilities/ThreadOperationsUtilities/ThreadOperations.h; sourceTree = ""; }; CBFE58282885852B003B94C9 /* ThreadOperations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadOperations.cpp; path = PersistentStorageUtilities/ThreadOperationsUtilities/ThreadOperations.cpp; sourceTree = ""; }; DFD5E77A2B05181400C32B6A /* RustSecureStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RustSecureStore.h; sourceTree = ""; }; DFD5E77B2B05181400C32B6A /* RustSecureStore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RustSecureStore.cpp; sourceTree = ""; }; DFD5E77D2B05264000C32B6A /* AESCrypto.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AESCrypto.mm; path = Comm/AESCrypto.mm; sourceTree = ""; }; DFD5E7802B05264F00C32B6A /* AESCrypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AESCrypto.h; sourceTree = ""; }; DFD5E7842B052B1400C32B6A /* RustAESCrypto.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RustAESCrypto.cpp; sourceTree = ""; }; DFD5E7852B052B1400C32B6A /* RustAESCrypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RustAESCrypto.h; sourceTree = ""; }; F53DA7B3F26C2798DCE74A94 /* Pods-Comm.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Comm.debug.xcconfig"; path = "Target Support Files/Pods-Comm/Pods-Comm.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 8B99BAAC28D50F3000EB5ADB /* libnative_rust_library.a in Frameworks */, 7F761E602201141E001B6FB7 /* JavaScriptCore.framework in Frameworks */, D7DB6E0F85B2DBE15B01EC21 /* libPods-Comm.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 713EE40326C6676B003D7C48 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 724995CE27B4103A00323FCE /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 724995FB27BA9E8D00323FCE /* UserNotifications.framework in Frameworks */, F02C296C528B51ADAB5AA19D /* libPods-NotificationService.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 13B07FAE1A68108700A75B9A /* Comm */ = { isa = PBXGroup; children = ( 71B8CCB626BD30EC0040C0A2 /* CommCoreImplementations */, 7F788C2B248AA2130098F071 /* SplashScreen.storyboard */, 7FCFD8BD1E81B8DF00629B0E /* Comm.entitlements */, 13B07FAF1A68108700A75B9A /* AppDelegate.h */, 13B07FB01A68108700A75B9A /* AppDelegate.mm */, 13B07FB51A68108700A75B9A /* Images.xcassets */, 7F554F822332D58B007CB9F7 /* Info.debug.plist */, 13B07FB61A68108700A75B9A /* Info.release.plist */, 13B07FB71A68108700A75B9A /* main.m */, 7FCEA2DC2444010B004017B1 /* Comm-Bridging-Header.h */, 7F26E81B24440D87004049C6 /* dummy.swift */, ); name = Comm; sourceTree = ""; }; 5F5A6FB2C6AD630620BBF58C /* NotificationService */ = { isa = PBXGroup; children = ( 769A87FB41BCE3FEF97FD59A /* ExpoModulesProvider.swift */, ); name = NotificationService; sourceTree = ""; }; 6534411766BE4CA4B0AB0A78 /* Resources */ = { isa = PBXGroup; children = ( 7FA2DCDC293E62F500991BA4 /* CommIcons.ttf */, 7FA2DCDD293E62F500991BA4 /* SWMansionIcons.ttf */, 7F8D601F26535E060053CB29 /* Anaheim-Regular.ttf */, 7F8D602026535E060053CB29 /* OpenSans-Regular.ttf */, B71AFF1E265EDD8600B22352 /* IBMPlexSans-Medium.ttf */, 7F8D601E26535E060053CB29 /* OpenSans-Semibold.ttf */, 7F8D602726535EEE0053CB29 /* IBMPlexSans-Bold.ttf */, 7F8D602626535EEE0053CB29 /* IBMPlexSans-Regular.ttf */, ); name = Resources; sourceTree = ""; }; 713EE40726C6676B003D7C48 /* CommTests */ = { isa = PBXGroup; children = ( 713EE40A26C6676B003D7C48 /* Info.plist */, ); path = CommTests; sourceTree = ""; }; 71B8CCB626BD30EC0040C0A2 /* CommCoreImplementations */ = { isa = PBXGroup; children = ( CB74AB1B2B2AFF6E00CBB494 /* CommServicesAuthMetadataEmitter.mm */, DFD5E77D2B05264000C32B6A /* AESCrypto.mm */, CBCF57A92B05091D00EC4BC0 /* CommAESCryptoUtils */, CB90951729531647002F2A7F /* CommIOSNotifications */, 8E43C32E291E5B9D009378F5 /* TerminateApp.h */, 8E43C32B291E5B4A009378F5 /* TerminateApp.mm */, CBDEC69A28ED867000C17588 /* GlobalDBSingleton.mm */, CB38B4782877177B00171182 /* TemporaryMessageStorage */, 71762A74270D8AAE00F565ED /* PlatformSpecificTools.mm */, 71D4D7CB26C50B1000FCDBCD /* CommSecureStore.mm */, 71142A7526C2650A0039DCBD /* CommSecureStoreIOSWrapper.h */, 71142A7626C2650A0039DCBD /* CommSecureStoreIOSWrapper.mm */, 71CA4AEA262F230A00835C89 /* Tools.h */, 71CA4AEB262F236100835C89 /* Tools.mm */, 71CA4A63262DA8E500835C89 /* Logger.mm */, ); name = CommCoreImplementations; sourceTree = ""; }; 71BE84362636A944002849D2 /* cpp */ = { isa = PBXGroup; children = ( 71BE84372636A944002849D2 /* CommonCpp */, ); name = cpp; path = ../cpp; sourceTree = ""; }; 71BE84372636A944002849D2 /* CommonCpp */ = { isa = PBXGroup; children = ( CB24361429A3978800FEC4E1 /* Notifications */, 71F971B4270726C000DDC5BF /* _generated */, 71BF5B6A26B3FCFF00EDE27D /* CryptoTools */, 71BE84382636A944002849D2 /* Tools */, 71BE843A2636A944002849D2 /* NativeModules */, 71BE843F2636A944002849D2 /* DatabaseManagers */, ); path = CommonCpp; sourceTree = ""; }; 71BE84382636A944002849D2 /* Tools */ = { isa = PBXGroup; children = ( DFD5E7802B05264F00C32B6A /* AESCrypto.h */, CBCA09052A8E0E6B00F75B3E /* StaffUtils.cpp */, CBCA09042A8E0E6B00F75B3E /* StaffUtils.h */, 7FBB2A7A29EEA2A4002C6493 /* Base64.cpp */, 7FBB2A7929EA752D002C6493 /* Base64.h */, 71B8CCBD26BD4DEB0040C0A2 /* CommSecureStore.h */, 718DE99C2653D41C00365824 /* WorkerThread.cpp */, 718DE99D2653D41C00365824 /* WorkerThread.h */, 71BE84392636A944002849D2 /* Logger.h */, 71DC160C270C43D300822863 /* PlatformSpecificTools.h */, ); path = Tools; sourceTree = ""; }; 71BE843A2636A944002849D2 /* NativeModules */ = { isa = PBXGroup; children = ( 8E2CC2562B5C999A000C94D6 /* KeyserverStoreOperations.h */, CBA784382B28AC4300E9F419 /* CommServicesAuthMetadataEmitter.h */, 8E3994562B039A9300D5E950 /* UserStoreOperations.h */, 8EA59BD22A6E800100EB4F53 /* NativeModuleUtils.h */, 8EF775672A74032C0046A385 /* CommRustModule.cpp */, 8EF775662A74032C0046A385 /* CommRustModule.h */, 8EE6E4A02A39CCAB00AE6BCD /* DraftStoreOperations.h */, 8EE6E49F2A39CCAB00AE6BCD /* ReportStoreOperations.h */, CB2688FF2A2DF56000EC7300 /* CommConstants.cpp */, CB2688FE2A2DF55F00EC7300 /* CommConstants.h */, CBED0E2C284E086100CD3863 /* PersistentStorageUtilities */, 726E5D722731A4240032361D /* InternalModules */, 71BE843C2636A944002849D2 /* CommCoreModule.cpp */, 8BC9568429FC49B00060AE4A /* JSIRust.cpp */, 8BC9568329FC49920060AE4A /* JSIRust.h */, 71BE843E2636A944002849D2 /* CommCoreModule.h */, 7FBB2A7329E944FD002C6493 /* CommUtilsModule.cpp */, 7FBB2A7429E9450E002C6493 /* CommUtilsModule.h */, B7055C6B26E477CF00BE0548 /* MessageStoreOperations.h */, B7906F692720905A009BBBF5 /* ThreadStoreOperations.h */, ); path = NativeModules; sourceTree = ""; }; 71BE843F2636A944002849D2 /* DatabaseManagers */ = { isa = PBXGroup; children = ( + CB3CCB002B7246F400793640 /* NativeSQLiteConnectionManager.cpp */, + CB3CCAFF2B7246F400793640 /* NativeSQLiteConnectionManager.h */, + CBA5F8842B6979ED005BE700 /* SQLiteConnectionManager.cpp */, + CBA5F8832B6979ED005BE700 /* SQLiteConnectionManager.h */, 8E86A6D229537EBB000BBE7D /* DatabaseManager.cpp */, 71BE84402636A944002849D2 /* DatabaseQueryExecutor.h */, 71BE84412636A944002849D2 /* SQLiteQueryExecutor.cpp */, 71BE84422636A944002849D2 /* SQLiteQueryExecutor.h */, 71BE84432636A944002849D2 /* DatabaseManager.h */, 71BE84442636A944002849D2 /* entities */, ); path = DatabaseManagers; sourceTree = ""; }; 71BE84442636A944002849D2 /* entities */ = { isa = PBXGroup; children = ( CB01F0C32B67F3970089E1F9 /* SQLiteStatementWrapper.cpp */, CB01F0C12B67EF470089E1F9 /* SQLiteDataConverters.cpp */, CB01F0C02B67CDC20089E1F9 /* SQLiteDataConverters.h */, CB01F0BF2B67CDC20089E1F9 /* SQLiteStatementWrapper.h */, CBF9DAE22B595934000EE771 /* EntityQueryHelpers.h */, B7906F6A27209091009BBBF5 /* OlmPersistAccount.h */, B7906F6B27209091009BBBF5 /* OlmPersistSession.h */, B7906F6C27209091009BBBF5 /* Thread.h */, 71BE84452636A944002849D2 /* Draft.h */, B70FBC1226B047050040F480 /* Message.h */, B7E937CA26F448E700022A7C /* Media.h */, 2DDA0A22FECC9DAA5C19C35D /* Metadata.h */, ); path = entities; sourceTree = ""; }; 71BF5B6A26B3FCFF00EDE27D /* CryptoTools */ = { isa = PBXGroup; children = ( 75291F0328F9A0AE00F4C80E /* DeviceID.cpp */, 75291F0228F9A09E00F4C80E /* DeviceID.h */, 71BF5B7B26BBDA6100EDE27D /* CryptoModule.cpp */, 71BF5B7A26BBDA6000EDE27D /* CryptoModule.h */, 71BF5B6F26B3FF0900EDE27D /* Session.cpp */, 71BF5B7026B3FF0900EDE27D /* Session.h */, 71BF5B7226B3FFBC00EDE27D /* Persist.h */, 71BF5B7326B401D300EDE27D /* Tools.cpp */, 71BF5B7426B401D300EDE27D /* Tools.h */, ); path = CryptoTools; sourceTree = ""; }; 71F971B4270726C000DDC5BF /* _generated */ = { isa = PBXGroup; children = ( 8EA59BD72A73DAB000EB4F53 /* rustJSI-generated.cpp */, 8EA59BD82A73DAB000EB4F53 /* rustJSI.h */, 7FE4D9F4291DFE9300667BF6 /* commJSI-generated.cpp */, 7FE4D9F3291DFE9300667BF6 /* commJSI.h */, 7FBB2A7529E94539002C6493 /* utilsJSI-generated.cpp */, 7FBB2A7729E94541002C6493 /* utilsJSI.h */, ); path = _generated; sourceTree = ""; }; 724995D227B4103A00323FCE /* NotificationService */ = { isa = PBXGroup; children = ( CB30C12327D0ACF700FBE8DE /* NotificationService.entitlements */, 724995D327B4103A00323FCE /* NotificationService.h */, 724995D427B4103A00323FCE /* NotificationService.mm */, 724995D627B4103A00323FCE /* Info.plist */, ); path = NotificationService; sourceTree = ""; }; 726E5D722731A4240032361D /* InternalModules */ = { isa = PBXGroup; children = ( 8B38121529CE5742000C52E9 /* RustPromiseManager.cpp */, 8B652FA1295EA6B8009F8163 /* RustPromiseManager.h */, CBDEC69928ED859600C17588 /* GlobalDBSingleton.h */, ); path = InternalModules; sourceTree = ""; }; 7FF0870B1E833C3F000A1ACF /* Frameworks */ = { isa = PBXGroup; children = ( 8B99BAAB28D50F3000EB5ADB /* libnative_rust_library.a */, CB3C621327CE66540054F24C /* libEXSecureStore.a */, 724995FA27BA9E8C00323FCE /* UserNotifications.framework */, 711CF80E25DC096000A00FBD /* libFolly.a */, 7F761E292201141E001B6FB7 /* JavaScriptCore.framework */, 994BEBDD4E4959F69CEA0BC3 /* libPods-Comm.a */, 3EE4DCB430B05EC9DE7D7B01 /* libPods-NotificationService.a */, ); name = Frameworks; sourceTree = ""; }; 83CBB9F61A601CBA00E9B192 = { isa = PBXGroup; children = ( 8B99AF6B28D50D4800EB5ADB /* native_rust_library */, 71BE84362636A944002849D2 /* cpp */, 13B07FAE1A68108700A75B9A /* Comm */, 713EE40726C6676B003D7C48 /* CommTests */, 724995D227B4103A00323FCE /* NotificationService */, 83CBBA001A601CBA00E9B192 /* Products */, 6534411766BE4CA4B0AB0A78 /* Resources */, 7FF0870B1E833C3F000A1ACF /* Frameworks */, D533B93718E3B9684B508006 /* Pods */, AFF3F1F76178B42122C79BDE /* ExpoModulesProviders */, ); indentWidth = 2; sourceTree = ""; tabWidth = 2; }; 83CBBA001A601CBA00E9B192 /* Products */ = { isa = PBXGroup; children = ( 13B07F961A680F5B00A75B9A /* Comm.app */, 713EE40626C6676B003D7C48 /* CommTests.xctest */, 724995D127B4103A00323FCE /* NotificationService.appex */, ); name = Products; sourceTree = ""; }; 8B99AF6B28D50D4800EB5ADB /* native_rust_library */ = { isa = PBXGroup; children = ( CBFBEEB82B4ED90600729F1D /* RustBackupExecutor.cpp */, CBFBEEB92B4ED90600729F1D /* RustBackupExecutor.h */, CB74AB1E2B2B0C0900CBB494 /* RustCSAMetadataEmitter.cpp */, CB74AB1F2B2B0C0900CBB494 /* RustCSAMetadataEmitter.h */, DFD5E7842B052B1400C32B6A /* RustAESCrypto.cpp */, DFD5E7852B052B1400C32B6A /* RustAESCrypto.h */, DFD5E77B2B05181400C32B6A /* RustSecureStore.cpp */, DFD5E77A2B05181400C32B6A /* RustSecureStore.h */, 8B652FA4295EA9F1009F8163 /* RustCallback.h */, 8B99BAAD28D511FF00EB5ADB /* lib.rs.cc */, 8B99AF6D28D50D4800EB5ADB /* lib.rs.h */, 8B99B59928D50D4900EB5ADB /* cxx.h */, 8B652FA5295EAA5B009F8163 /* RustCallback.cpp */, ); name = native_rust_library; path = ../native_rust_library; sourceTree = ""; }; 8EA59BD02A6E786200EB4F53 /* DataStores */ = { isa = PBXGroup; children = ( 8E2CC2582B5C99B0000C94D6 /* KeyserverStore.cpp */, 8E2CC2572B5C99B0000C94D6 /* KeyserverStore.h */, 8E3994532B039A7C00D5E950 /* UserStore.cpp */, 8E3994542B039A7C00D5E950 /* UserStore.h */, 8EF7756F2A751B780046A385 /* ReportStore.cpp */, 8EF775702A751B780046A385 /* ReportStore.h */, 8EF7756D2A7513F40046A385 /* MessageStore.cpp */, 8EF7756C2A7513F40046A385 /* MessageStore.h */, 8EF775692A7433630046A385 /* ThreadStore.cpp */, 8EF7756A2A7433630046A385 /* ThreadStore.h */, 8EA59BD42A6E8E0400EB4F53 /* DraftStore.cpp */, 8EA59BD52A6E8E0400EB4F53 /* DraftStore.h */, 8EA59BD32A6E8CB700EB4F53 /* BaseDataStore.h */, ); name = DataStores; sourceTree = ""; }; AFF3F1F76178B42122C79BDE /* ExpoModulesProviders */ = { isa = PBXGroup; children = ( E75E6E4967CE9A8BBA89ED86 /* Comm */, 5F5A6FB2C6AD630620BBF58C /* NotificationService */, ); name = ExpoModulesProviders; sourceTree = ""; }; CB24361429A3978800FEC4E1 /* Notifications */ = { isa = PBXGroup; children = ( CB24361529A3979500FEC4E1 /* BackgroundDataStorage */, ); name = Notifications; sourceTree = ""; }; CB24361529A3979500FEC4E1 /* BackgroundDataStorage */ = { isa = PBXGroup; children = ( CB24361729A39A2500FEC4E1 /* NotificationsCryptoModule.cpp */, CB24361629A397AB00FEC4E1 /* NotificationsCryptoModule.h */, ); name = BackgroundDataStorage; sourceTree = ""; }; CB38B4782877177B00171182 /* TemporaryMessageStorage */ = { isa = PBXGroup; children = ( CB38B47F28771A3B00171182 /* TemporaryMessageStorage.mm */, CB38B47E287719C500171182 /* TemporaryMessageStorage.h */, CB38B47D2877194100171182 /* EncryptedFileUtils.mm */, CB38B47C2877190100171182 /* EncryptedFileUtils.h */, CB38B47B287718A200171182 /* NonBlockingLock.mm */, CB38B4792877179A00171182 /* NonBlockingLock.h */, ); name = TemporaryMessageStorage; sourceTree = ""; }; CB38F2AC286C6C010010535C /* MessageOperationsUtilities */ = { isa = PBXGroup; children = ( CB38F2AF286C6C870010535C /* MessageOperationsUtilities.cpp */, CB38F2B0286C6C870010535C /* MessageOperationsUtilities.h */, CB38F2AE286C6C870010535C /* MessageSpecs.h */, CB38F2AD286C6C4B0010535C /* MessageSpecs */, ); name = MessageOperationsUtilities; sourceTree = ""; }; CB38F2AD286C6C4B0010535C /* MessageSpecs */ = { isa = PBXGroup; children = ( 7F446E2329C3B2BE00670288 /* SidebarSourceMessageSpec.h */, CB38F2B5286C6C970010535C /* ChangeRoleMessageSpec.h */, CB38F2B8286C6C970010535C /* ChangeSettingsMessageSpec.h */, CB38F2BA286C6C970010535C /* CreateEntryMessageSpec.h */, CB38F2B4286C6C970010535C /* CreateSidebarMessageSpec.h */, CB38F2BC286C6C970010535C /* CreateSubThreadMessageSpec.h */, CB38F2B2286C6C970010535C /* CreateThreadMessageSpec.h */, CB38F2BE286C6C980010535C /* DeleteEntryMessageSpec.h */, CB38F2BB286C6C970010535C /* EditEntryMessageSpec.h */, CB38F2B7286C6C970010535C /* MessageSpec.h */, CB38F2BD286C6C970010535C /* MultimediaMessageSpec.h */, 7F446E2229C3AF3800670288 /* ReactionMessageSpec.h */, CB38F2B6286C6C970010535C /* RestoreEntryMessageSpec.h */, CB38F2B3286C6C970010535C /* TextMessageSpec.h */, CB38F2B9286C6C970010535C /* UnsupportedMessageSpec.h */, CB38F2BF286C6C980010535C /* UpdateRelationshipMessageSpec.h */, ); name = MessageSpecs; sourceTree = ""; }; CB90951729531647002F2A7F /* CommIOSNotifications */ = { isa = PBXGroup; children = ( CB7EF17D295C5D1800B17035 /* CommIOSNotifications.mm */, CB7EF17C295C580500B17035 /* CommIOSNotificationsBridgeQueue.h */, CB7EF17B295C580500B17035 /* CommIOSNotificationsBridgeQueue.mm */, CB90951929531663002F2A7F /* CommIOSNotifications.h */, ); name = CommIOSNotifications; sourceTree = ""; }; CBAAA46D2B45915F007599DA /* BackupOperationsUtilities */ = { isa = PBXGroup; children = ( CBAAA46E2B459181007599DA /* BackupOperationsExecutor.cpp */, CBAAA46F2B459181007599DA /* BackupOperationsExecutor.h */, ); name = BackupOperationsUtilities; sourceTree = ""; }; CBCF57A92B05091D00EC4BC0 /* CommAESCryptoUtils */ = { isa = PBXGroup; children = ( CBCF57AB2B05096F00EC4BC0 /* AESCryptoModuleObjCCompat.h */, ); name = CommAESCryptoUtils; sourceTree = ""; }; CBED0E2C284E086100CD3863 /* PersistentStorageUtilities */ = { isa = PBXGroup; children = ( CBAAA46D2B45915F007599DA /* BackupOperationsUtilities */, 8EA59BD02A6E786200EB4F53 /* DataStores */, CBFE582628858512003B94C9 /* ThreadOperationsUtilities */, CB38F2AC286C6C010010535C /* MessageOperationsUtilities */, ); name = PersistentStorageUtilities; sourceTree = ""; }; CBFE582628858512003B94C9 /* ThreadOperationsUtilities */ = { isa = PBXGroup; children = ( CBFE58282885852B003B94C9 /* ThreadOperations.cpp */, CBFE58272885852B003B94C9 /* ThreadOperations.h */, ); name = ThreadOperationsUtilities; sourceTree = ""; }; D533B93718E3B9684B508006 /* Pods */ = { isa = PBXGroup; children = ( F53DA7B3F26C2798DCE74A94 /* Pods-Comm.debug.xcconfig */, C562A7004903539402D988CE /* Pods-Comm.release.xcconfig */, 891D1495EE1F375F3AF6C7ED /* Pods-NotificationService.debug.xcconfig */, 913E5A7BDECB327E3DE11053 /* Pods-NotificationService.release.xcconfig */, ); path = Pods; sourceTree = ""; }; E75E6E4967CE9A8BBA89ED86 /* Comm */ = { isa = PBXGroup; children = ( 3EEB3E70587B0ADAD05237B0 /* ExpoModulesProvider.swift */, ); name = Comm; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 13B07F861A680F5B00A75B9A /* Comm */ = { isa = PBXNativeTarget; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Comm" */; buildPhases = ( 02DE093B3C1DDF10C1FA3E9C /* [CP] Check Pods Manifest.lock */, 8BF9F24E28B795E200E20C13 /* Build Rust library */, 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, DB38BFA0686C805CE44F051F /* [CP] Copy Pods Resources */, EA2E8897D838D7F3E680EACE /* [CP] Embed Pods Frameworks */, 724995DA27B4103A00323FCE /* Embed App Extensions */, ); buildRules = ( ); dependencies = ( 724995D827B4103A00323FCE /* PBXTargetDependency */, ); name = Comm; productName = "Hello World"; productReference = 13B07F961A680F5B00A75B9A /* Comm.app */; productType = "com.apple.product-type.application"; }; 713EE40526C6676B003D7C48 /* CommTests */ = { isa = PBXNativeTarget; buildConfigurationList = 713EE40F26C6676B003D7C48 /* Build configuration list for PBXNativeTarget "CommTests" */; buildPhases = ( 713EE40226C6676B003D7C48 /* Sources */, 713EE40326C6676B003D7C48 /* Frameworks */, 713EE40426C6676B003D7C48 /* Resources */, ); buildRules = ( ); dependencies = ( 713EE40C26C6676B003D7C48 /* PBXTargetDependency */, ); name = CommTests; productName = CommTests; productReference = 713EE40626C6676B003D7C48 /* CommTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; 724995D027B4103A00323FCE /* NotificationService */ = { isa = PBXNativeTarget; buildConfigurationList = 724995DD27B4103A00323FCE /* Build configuration list for PBXNativeTarget "NotificationService" */; buildPhases = ( 6735FA74B2C82E3B27E18258 /* [CP] Check Pods Manifest.lock */, 724995CD27B4103A00323FCE /* Sources */, 724995CE27B4103A00323FCE /* Frameworks */, 724995CF27B4103A00323FCE /* Resources */, E6221695BEF4548AF41DD8EB /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( ); name = NotificationService; productName = NotificationService; productReference = 724995D127B4103A00323FCE /* NotificationService.appex */; productType = "com.apple.product-type.app-extension"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 83CBB9F71A601CBA00E9B192 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 1150; ORGANIZATIONNAME = "Comm Technologies, Inc."; TargetAttributes = { 13B07F861A680F5B00A75B9A = { DevelopmentTeam = H98Y8MH53M; LastSwiftMigration = 1140; ProvisioningStyle = Automatic; SystemCapabilities = { com.apple.BackgroundModes = { enabled = 1; }; com.apple.GameCenter = { enabled = 0; }; com.apple.InAppPurchase = { enabled = 0; }; com.apple.Keychain = { enabled = 1; }; com.apple.Push = { enabled = 1; }; com.apple.SafariKeychain = { enabled = 1; }; }; }; 713EE40526C6676B003D7C48 = { CreatedOnToolsVersion = 12.5.1; ProvisioningStyle = Automatic; TestTargetID = 13B07F861A680F5B00A75B9A; }; 724995D027B4103A00323FCE = { CreatedOnToolsVersion = 13.0; DevelopmentTeam = H98Y8MH53M; ProvisioningStyle = Automatic; }; }; }; buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Comm" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( English, en, Base, ); mainGroup = 83CBB9F61A601CBA00E9B192; productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 13B07F861A680F5B00A75B9A /* Comm */, 713EE40526C6676B003D7C48 /* CommTests */, 724995D027B4103A00323FCE /* NotificationService */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 13B07F8E1A680F5B00A75B9A /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 7F8D602926535F2A0053CB29 /* IBMPlexSans-Regular.ttf in Resources */, 7F8D602826535F240053CB29 /* IBMPlexSans-Bold.ttf in Resources */, 7F8D602126535E060053CB29 /* OpenSans-Semibold.ttf in Resources */, 7FA2DCDE293E62F500991BA4 /* CommIcons.ttf in Resources */, 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, 7F788C2C248AA2140098F071 /* SplashScreen.storyboard in Resources */, 7F8D602226535E060053CB29 /* Anaheim-Regular.ttf in Resources */, 7FA2DCDF293E62F500991BA4 /* SWMansionIcons.ttf in Resources */, B71AFF1F265EDD8600B22352 /* IBMPlexSans-Medium.ttf in Resources */, 7F8D602326535E060053CB29 /* OpenSans-Regular.ttf in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; 713EE40426C6676B003D7C48 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 724995CF27B4103A00323FCE /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "$(SRCROOT)/.xcode.env.local", "$(SRCROOT)/.xcode.env", ); name = "Bundle React Native code and images"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "set -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n"; }; 02DE093B3C1DDF10C1FA3E9C /* [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-Comm-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; }; 6735FA74B2C82E3B27E18258 /* [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-NotificationService-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; }; 8BF9F24E28B795E200E20C13 /* Build Rust library */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( ); inputPaths = ( ); name = "Build Rust library"; outputFileListPaths = ( ); outputPaths = ( "${SRCROOT}/../native_rust_library/lib.rs.cc", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "${SRCROOT}/../../scripts/build-rust-native-library.sh\n"; }; DB38BFA0686C805CE44F051F /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Comm/Pods-Comm-resources.sh", "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/expo-dev-launcher/EXDevLauncher.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/expo-dev-menu/EXDevMenu.bundle", ); name = "[CP] Copy Pods Resources"; outputPaths = ( "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXDevLauncher.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXDevMenu.bundle", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Comm/Pods-Comm-resources.sh\"\n"; showEnvVarsInLog = 0; }; E6221695BEF4548AF41DD8EB /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-NotificationService/Pods-NotificationService-resources.sh", "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/expo-dev-launcher/EXDevLauncher.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/expo-dev-menu/EXDevMenu.bundle", ); name = "[CP] Copy Pods Resources"; outputPaths = ( "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXDevLauncher.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXDevMenu.bundle", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NotificationService/Pods-NotificationService-resources.sh\"\n"; showEnvVarsInLog = 0; }; EA2E8897D838D7F3E680EACE /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Comm/Pods-Comm-frameworks.sh", "${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL-Universal/OpenSSL.framework/OpenSSL", "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/hermes.framework/hermes", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OpenSSL.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Comm/Pods-Comm-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 13B07F871A680F5B00A75B9A /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + CB3CCB012B72470700793640 /* NativeSQLiteConnectionManager.cpp in Sources */, + CBA5F8852B6979F7005BE700 /* SQLiteConnectionManager.cpp in Sources */, CB01F0C42B67F3A10089E1F9 /* SQLiteStatementWrapper.cpp in Sources */, CB01F0C22B67EF5A0089E1F9 /* SQLiteDataConverters.cpp in Sources */, CBAAA4702B459181007599DA /* BackupOperationsExecutor.cpp in Sources */, CBCA09062A8E0E7400F75B3E /* StaffUtils.cpp in Sources */, 8EF7756B2A7433630046A385 /* ThreadStore.cpp in Sources */, CB2689002A2DF58000EC7300 /* CommConstants.cpp in Sources */, CB7EF17E295C674300B17035 /* CommIOSNotifications.mm in Sources */, CB7EF180295C674300B17035 /* CommIOSNotificationsBridgeQueue.mm in Sources */, 7F0C6E31291C4468002AA2D9 /* ExpoModulesProvider.swift in Sources */, 8EF775682A74032C0046A385 /* CommRustModule.cpp in Sources */, 8E43C32C291E5B4A009378F5 /* TerminateApp.mm in Sources */, 8BC9568529FC49B00060AE4A /* JSIRust.cpp in Sources */, 8EA59BD92A73DAB000EB4F53 /* rustJSI-generated.cpp in Sources */, CB38B48628771CDD00171182 /* TemporaryMessageStorage.mm in Sources */, CB74AB202B2B0C0A00CBB494 /* RustCSAMetadataEmitter.cpp in Sources */, CB38B48428771CAF00171182 /* EncryptedFileUtils.mm in Sources */, 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 */, 8B99BAAE28D511FF00EB5ADB /* lib.rs.cc in Sources */, 71CA4AEC262F236100835C89 /* Tools.mm in Sources */, 71762A75270D8AAE00F565ED /* PlatformSpecificTools.mm in Sources */, 71BF5B7126B3FF0900EDE27D /* Session.cpp in Sources */, 8EF7756E2A7513F40046A385 /* MessageStore.cpp in Sources */, 8E2CC2592B5C99B0000C94D6 /* KeyserverStore.cpp in Sources */, DFD5E77C2B05181400C32B6A /* RustSecureStore.cpp in Sources */, 71BF5B7526B401D300EDE27D /* Tools.cpp in Sources */, 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */, 7FE4D9F5291DFE9300667BF6 /* commJSI-generated.cpp in Sources */, 8B652FA6295EAA5B009F8163 /* RustCallback.cpp in Sources */, 71142A7726C2650B0039DCBD /* CommSecureStoreIOSWrapper.mm in Sources */, 7FBB2A7B29EEA2A4002C6493 /* Base64.cpp in Sources */, CB38F2B1286C6C870010535C /* MessageOperationsUtilities.cpp in Sources */, DFD5E7862B052B1400C32B6A /* RustAESCrypto.cpp in Sources */, 8EF775712A751B780046A385 /* ReportStore.cpp in Sources */, 71CA4A64262DA8E500835C89 /* Logger.mm in Sources */, 71BF5B7F26BBDD7400EDE27D /* CryptoModule.cpp in Sources */, CB24361829A39A2500FEC4E1 /* NotificationsCryptoModule.cpp in Sources */, 71BE844A2636A944002849D2 /* CommCoreModule.cpp in Sources */, 71D4D7CC26C50B1000FCDBCD /* CommSecureStore.mm in Sources */, 8B38121629CE5742000C52E9 /* RustPromiseManager.cpp in Sources */, 7FBB2A7629E94539002C6493 /* utilsJSI-generated.cpp in Sources */, 711B408425DA97F9005F8F06 /* dummy.swift in Sources */, 8E86A6D329537EBB000BBE7D /* DatabaseManager.cpp in Sources */, CBDEC69B28ED867000C17588 /* GlobalDBSingleton.mm in Sources */, DFD5E77E2B05264000C32B6A /* AESCrypto.mm in Sources */, 8EA59BD62A6E8E0400EB4F53 /* DraftStore.cpp in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, 71BE844B2636A944002849D2 /* SQLiteQueryExecutor.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 713EE40226C6676B003D7C48 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 724995CD27B4103A00323FCE /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( CBCA09072A8E0E7D00F75B3E /* StaffUtils.cpp in Sources */, CB3C0A3B2A125C8F009BD4DA /* NotificationsCryptoModule.cpp in Sources */, CB90951F29534B32002F2A7F /* CommSecureStore.mm in Sources */, CB38B48728771CE500171182 /* TemporaryMessageStorage.mm in Sources */, CB38B48528771CB800171182 /* EncryptedFileUtils.mm in Sources */, CB38B48328771C8300171182 /* NonBlockingLock.mm in Sources */, CB1648AF27CFBE6A00394D9D /* CryptoModule.cpp in Sources */, CB4821AE27CFB187001AB7E1 /* Tools.cpp in Sources */, CB4821AC27CFB17C001AB7E1 /* Session.cpp in Sources */, CB4821A927CFB153001AB7E1 /* WorkerThread.cpp in Sources */, CB4821AA27CFB153001AB7E1 /* Tools.mm in Sources */, CB3C621227CE65030054F24C /* CommSecureStoreIOSWrapper.mm in Sources */, CB3C621127CE4A320054F24C /* Logger.mm in Sources */, 724995D527B4103A00323FCE /* NotificationService.mm in Sources */, CB4821AF27CFB19D001AB7E1 /* PlatformSpecificTools.mm in Sources */, 1F537ACC7B60DC049C0ECFA7 /* ExpoModulesProvider.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 713EE40C26C6676B003D7C48 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 13B07F861A680F5B00A75B9A /* Comm */; targetProxy = 713EE40B26C6676B003D7C48 /* PBXContainerItemProxy */; }; 724995D827B4103A00323FCE /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 724995D027B4103A00323FCE /* NotificationService */; targetProxy = 724995D727B4103A00323FCE /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ 13B07F941A680F5B00A75B9A /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = F53DA7B3F26C2798DCE74A94 /* Pods-Comm.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_CXX_LANGUAGE_STANDARD = "c++17"; CLANG_ENABLE_MODULES = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES; CODE_SIGN_ENTITLEMENTS = Comm/Comm.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = H98Y8MH53M; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "COCOAPODS=1", "FB_SONARKIT_ENABLED=1", "SD_WEBP=1", ); HEADER_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)/../node_modules/react-native/Libraries/LinkingIOS", "$(PODS_ROOT)/boost-for-react-native", "$(SRCROOT)/../native_rust_library", "$(PODS_ROOT)/Headers/Private/React-bridging/react/bridging", ); INFOPLIST_FILE = Comm/Info.debug.plist; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); LIBRARY_SEARCH_PATHS = ( "$(SDKROOT)/usr/lib/swift", "$(inherited)", "\"${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/CocoaAsyncSocket\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/DVAssetLoaderDelegate\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/DoubleConversion\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/EXApplication\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/EXFont\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/EXHaptics\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/EXImageLoader\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/EXImageManipulator\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/EXKeepAwake\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/EXSecureStore\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/ExpoModulesCore\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/FBReactNativeSpec\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/OLMKit\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/Protobuf-C++\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RCT-Folly\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RCTTypeSafety\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RNCAsyncStorage\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RNCClipboard\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RNCMaskedView\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RNDeviceInfo\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RNFS\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RNFastImage\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RNGestureHandler\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RNKeychain\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RNReanimated\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RNSVG\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RNScreens\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RNVectorIcons\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Core\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-CoreModules\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTAnimation\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTBlob\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTImage\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTLinking\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTNetwork\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTSettings\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTText\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTVibration\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-hermes\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-jsi\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-jsiexecutor\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-jsinspector\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-logger\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-perflogger\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/ReactNativeART\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/ReactNativeDarkMode\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/ReactNativeKeyboardInput\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/ReactNativeKeyboardTrackingView\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/SDWebImageWebPCoder\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/SPTPersistentCache\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/SQLCipher-Amalgamation\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/Yoga\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/YogaKit\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/abseil\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/fmt\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/gRPC-C++\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/gRPC-Core\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/glog\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/libevent\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/libwebp\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/lottie-react-native\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-camera\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-ffmpeg\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-in-app-message\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-netinfo\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-notifications\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-orientation-locker\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-safe-area-context\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-video\"", /usr/lib/swift, ); "LIBRARY_SEARCH_PATHS[sdk=iphoneos*]" = ( "$(inherited)", "$(SRCROOT)/../native_rust_library/target/aarch64-apple-ios/debug", ); "LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*]" = ( "$(inherited)", "$(SRCROOT)/../native_rust_library/target/x86_64-apple-ios/debug", ); OTHER_CPLUSPLUSFLAGS = ( "-DFOLLY_MOBILE=1", "-DFOLLY_NO_CONFIG", "-DFOLLY_USE_LIBCPP=1", "-DREACT_NATIVE_MINOR_VERSION=70", "-fcxx-modules", "-fmodules", ); OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", "-lc++", ); OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; PRODUCT_BUNDLE_IDENTIFIER = app.comm; PRODUCT_NAME = Comm; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "Comm-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 1; USE_HEADERMAP = YES; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; }; 13B07F951A680F5B00A75B9A /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = C562A7004903539402D988CE /* Pods-Comm.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_CXX_LANGUAGE_STANDARD = "c++17"; CLANG_ENABLE_MODULES = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES; CODE_SIGN_ENTITLEMENTS = Comm/Comm.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = H98Y8MH53M; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; HEADER_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)/../node_modules/react-native/Libraries/LinkingIOS", "$(PODS_ROOT)/boost-for-react-native", "$(SRCROOT)/../native_rust_library", "$(PODS_ROOT)/Headers/Private/React-bridging/react/bridging", ); INFOPLIST_FILE = Comm/Info.release.plist; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); LIBRARY_SEARCH_PATHS = ( "$(SDKROOT)/usr/lib/swift", "$(inherited)", "\"${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/CocoaAsyncSocket\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/DVAssetLoaderDelegate\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/DoubleConversion\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/EXApplication\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/EXFont\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/EXHaptics\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/EXImageLoader\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/EXImageManipulator\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/EXKeepAwake\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/EXSecureStore\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/ExpoModulesCore\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/FBReactNativeSpec\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/OLMKit\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/Protobuf-C++\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RCT-Folly\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RCTTypeSafety\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RNCAsyncStorage\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RNCClipboard\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RNCMaskedView\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RNDeviceInfo\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RNFS\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RNFastImage\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RNGestureHandler\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RNKeychain\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RNReanimated\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RNSVG\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RNScreens\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/RNVectorIcons\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Core\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-CoreModules\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTAnimation\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTBlob\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTImage\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTLinking\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTNetwork\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTSettings\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTText\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTVibration\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-hermes\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-jsi\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-jsiexecutor\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-jsinspector\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-logger\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/React-perflogger\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/ReactNativeART\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/ReactNativeDarkMode\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/ReactNativeKeyboardInput\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/ReactNativeKeyboardTrackingView\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/SDWebImageWebPCoder\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/SPTPersistentCache\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/SQLCipher-Amalgamation\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/Yoga\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/YogaKit\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/abseil\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/fmt\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/gRPC-C++\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/gRPC-Core\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/glog\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/libevent\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/libwebp\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/lottie-react-native\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-camera\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-ffmpeg\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-in-app-message\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-netinfo\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-notifications\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-orientation-locker\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-safe-area-context\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-video\"", /usr/lib/swift, ); "LIBRARY_SEARCH_PATHS[sdk=iphoneos*]" = ( "$(inherited)", "$(SRCROOT)/../native_rust_library/target/aarch64-apple-ios/release", ); "LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*]" = ( "$(inherited)", "$(SRCROOT)/../native_rust_library/target/x86_64-apple-ios/release", ); ONLY_ACTIVE_ARCH = YES; OTHER_CPLUSPLUSFLAGS = ( "-DFOLLY_MOBILE=1", "-DFOLLY_NO_CONFIG", "-DFOLLY_USE_LIBCPP=1", "-DREACT_NATIVE_MINOR_VERSION=70", "-fcxx-modules", "-fmodules", ); OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", "-lc++", ); OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = app.comm; PRODUCT_NAME = Comm; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "Comm-Bridging-Header.h"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 1; USE_HEADERMAP = YES; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; }; 713EE40D26C6676B003D7C48 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "c++17"; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; DEBUG_INFORMATION_FORMAT = dwarf; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "i386 arm64"; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); INFOPLIST_FILE = CommTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 14.5; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@loader_path/Frameworks", ); MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; PRODUCT_BUNDLE_IDENTIFIER = swm.CommTests; PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = "1,2"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Comm.app/Comm"; USER_HEADER_SEARCH_PATHS = ( ../../node_modules/olm/include, ../../node_modules/olm/lib, "${PODS_ROOT}/OLMKit/include", "${PODS_ROOT}/OLMKit/lib", ); }; name = Debug; }; 713EE40E26C6676B003D7C48 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "c++17"; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "i386 arm64"; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = CommTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 14.5; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@loader_path/Frameworks", ); MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = swm.CommTests; PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = "1,2"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Comm.app/Comm"; USER_HEADER_SEARCH_PATHS = ( ../../node_modules/olm/include, ../../node_modules/olm/lib, "${PODS_ROOT}/OLMKit/include", "${PODS_ROOT}/OLMKit/lib", ); }; name = Release; }; 724995DB27B4103A00323FCE /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 891D1495EE1F375F3AF6C7ED /* Pods-NotificationService.debug.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "c++17"; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 314; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = H98Y8MH53M; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = NotificationService/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = NotificationService; INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 Comm Technologies, Inc. All rights reserved."; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); MARKETING_VERSION = 1.0.314; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_CFLAGS = ( "$(inherited)", "-DSQLITE_HAS_CODEC", "-DFOLLY_MOBILE=1", "-DFOLLY_NO_CONFIG", "-DFOLLY_USE_LIBCPP=1", "-DSQLITE_TEMP_STORE=2", "-DSQLCIPHER_CRYPTO_OPENSSL", ); OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; PRODUCT_BUNDLE_IDENTIFIER = app.comm.NotificationService; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = NO; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 1; }; name = Debug; }; 724995DC27B4103A00323FCE /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 913E5A7BDECB327E3DE11053 /* Pods-NotificationService.release.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "c++17"; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 314; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = H98Y8MH53M; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = NotificationService/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = NotificationService; INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 Comm Technologies, Inc. All rights reserved."; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); MARKETING_VERSION = 1.0.314; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ( "$(inherited)", "-DSQLITE_HAS_CODEC", "-DFOLLY_MOBILE=1", "-DFOLLY_NO_CONFIG", "-DFOLLY_USE_LIBCPP=1", "-DSQLITE_TEMP_STORE=2", "-DSQLCIPHER_CRYPTO_OPENSSL", ); OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = app.comm.NotificationService; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = NO; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 1; }; name = Release; }; 83CBBA201A601CBA00E9B192 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "c++17"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "FB_SONARKIT_ENABLED=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; OTHER_CPLUSPLUSFLAGS = ( "$(OTHER_CFLAGS)", "-DFOLLY_MOBILE=1", "-DFOLLY_NO_CONFIG", "-DFOLLY_USE_LIBCPP=1", "-fcxx-modules", "-fmodules", ); REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; }; name = Debug; }; 83CBBA211A601CBA00E9B192 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "c++17"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = YES; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; OTHER_CPLUSPLUSFLAGS = ( "$(OTHER_CFLAGS)", "-DFOLLY_MOBILE=1", "-DFOLLY_NO_CONFIG", "-DFOLLY_USE_LIBCPP=1", "-fcxx-modules", "-fmodules", ); REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; VALIDATE_PRODUCT = YES; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Comm" */ = { isa = XCConfigurationList; buildConfigurations = ( 13B07F941A680F5B00A75B9A /* Debug */, 13B07F951A680F5B00A75B9A /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 713EE40F26C6676B003D7C48 /* Build configuration list for PBXNativeTarget "CommTests" */ = { isa = XCConfigurationList; buildConfigurations = ( 713EE40D26C6676B003D7C48 /* Debug */, 713EE40E26C6676B003D7C48 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 724995DD27B4103A00323FCE /* Build configuration list for PBXNativeTarget "NotificationService" */ = { isa = XCConfigurationList; buildConfigurations = ( 724995DB27B4103A00323FCE /* Debug */, 724995DC27B4103A00323FCE /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Comm" */ = { isa = XCConfigurationList; buildConfigurations = ( 83CBBA201A601CBA00E9B192 /* Debug */, 83CBBA211A601CBA00E9B192 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; } diff --git a/web/database/_generated/comm_query_executor.wasm b/web/database/_generated/comm_query_executor.wasm index 01797b912..2918d4f92 100755 Binary files a/web/database/_generated/comm_query_executor.wasm and b/web/database/_generated/comm_query_executor.wasm differ diff --git a/web/scripts/run_emscripten.sh b/web/scripts/run_emscripten.sh index cc073758f..461971b60 100755 --- a/web/scripts/run_emscripten.sh +++ b/web/scripts/run_emscripten.sh @@ -1,168 +1,169 @@ #!/usr/bin/env bash set -Eeuo pipefail if ! command -v emcc > /dev/null; then echo "Please install emscripten or run 'nix develop'" >&2 exit 1 fi # directories SCRIPT_DIR=$(cd "$(dirname "$0")"; pwd -P) NATIVE_CPP_DIR="${SCRIPT_DIR}/../../native/cpp/" INPUT_DIR="${NATIVE_CPP_DIR}CommonCpp/DatabaseManagers/" ENTITIES_DIR="${NATIVE_CPP_DIR}CommonCpp/DatabaseManagers/entities/" SQLITE_DIR="${SCRIPT_DIR}/../database/sqlite/" WEB_CPP_DIR="${SCRIPT_DIR}/../cpp/" OUTPUT_DIR="${SCRIPT_DIR}/../database/_generated/" # files SQLITE_SOURCE="${SQLITE_DIR}sqlite3.c" SQLITE_BITCODE_FILE="${SQLITE_DIR}sqlite3.bc" OUTPUT_FILE_NAME="comm-query-executor" OUTPUT_FILE="${OUTPUT_DIR}${OUTPUT_FILE_NAME}.js" # OpenSSL resources OPENSSL_VERSION="3.2.0" OPENSSL_URL="https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz" OPENSSL_FILE="${SQLITE_DIR}openssl-file" OPENSSL_DIR="${SQLITE_DIR}openssl-${OPENSSL_VERSION}" OPENSSL_HEADERS="${OPENSSL_DIR}/include" OPENSSL_LIBCRYPTO="${OPENSSL_DIR}/libcrypto.a" # SQLCipher resources SQLCIPHER_AMALGAMATION_VERSION="4.5.5b" SQLCIPHER_AMALGAMATION="sqlcipher-amalgamation-${SQLCIPHER_AMALGAMATION_VERSION}" SQLCIPHER_AMALGAMATION_URL="https://codeload.github.com/CommE2E/sqlcipher-amalgamation/zip/refs/tags/${SQLCIPHER_AMALGAMATION_VERSION}" SQLCIPHER_AMALGAMATION_FILE="${SQLITE_DIR}${SQLCIPHER_AMALGAMATION}" SQLITE_COMPILATION_FLAGS=( -Oz -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_DISABLE_LFS -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_THREADSAFE=0 -DSQLITE_ENABLE_NORMALIZE -DSQLITE_HAS_CODEC -DSQLITE_TEMP_STORE=2 -DSQLCIPHER_CRYPTO_OPENSSL ) download_openssl() { mkdir -p "$SQLITE_DIR" curl "${OPENSSL_URL}" --output "${OPENSSL_FILE}" tar -xf "${OPENSSL_FILE}" -C "${SQLITE_DIR}" rm -f "${OPENSSL_FILE}" } build_openssl() { pushd "${OPENSSL_DIR}" ./Configure \ no-asm \ no-async \ no-egd \ no-ktls \ no-module \ no-posix-io \ no-secure-memory \ no-dso \ no-shared \ no-sock \ no-stdio \ no-ui-console \ no-weak-ssl-ciphers \ no-engine \ linux-generic32 make CC="emcc" AR="emar" RANLIB="emranlib" popd } if [ ! -d "$OPENSSL_DIR" ]; then echo "OpenSSL sources not found. Downloading." download_openssl fi if [ ! -f "$OPENSSL_LIBCRYPTO" ]; then echo "OpenSSL binary not found. Building." build_openssl fi download_sqlite() { mkdir -p "$SQLITE_DIR" curl "${SQLCIPHER_AMALGAMATION_URL}" --output "${SQLCIPHER_AMALGAMATION_FILE}" unzip -jo "${SQLCIPHER_AMALGAMATION_FILE}" -d "${SQLITE_DIR}" rm -f "${SQLCIPHER_AMALGAMATION_FILE}" } if [ ! -f "$SQLITE_BITCODE_FILE" ]; then echo "SQLite engine not found. Downloading." download_sqlite emcc "${SQLITE_COMPILATION_FLAGS[@]}" \ -I "${OPENSSL_HEADERS}" \ -c "$SQLITE_SOURCE" \ -o "$SQLITE_BITCODE_FILE" fi EMCC_FLAGS=( # WASM files and bindings --memory-init-file 0 -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s ALLOW_TABLE_GROWTH=1 -s FORCE_FILESYSTEM=1 -s SINGLE_FILE=0 -s EXPORTED_RUNTIME_METHODS=["FS"] # node/babel/webpack helpers -s NODEJS_CATCH_EXIT=0 -s NODEJS_CATCH_REJECTION=0 -s WASM_ASYNC_COMPILATION=0 -s EXPORT_ES6=1 -s USE_ES6_IMPORT_META=0 -s MODULARIZE=1 # optimization -Oz -flto --closure 1 ) CFLAGS=( -I "$INPUT_DIR" -I "$SQLITE_DIR" -I "${NATIVE_CPP_DIR}CommonCpp/Tools/" ) INPUT_FILES=( + "${INPUT_DIR}SQLiteConnectionManager.cpp" "${WEB_CPP_DIR}SQLiteQueryExecutorBindings.cpp" "${WEB_CPP_DIR}Logger.cpp" "${ENTITIES_DIR}SQLiteDataConverters.cpp" "${ENTITIES_DIR}SQLiteStatementWrapper.cpp" "$SQLITE_BITCODE_FILE" ) mkdir -p "$OUTPUT_DIR" emcc -lembind \ "${EMCC_FLAGS[@]}" \ "${CFLAGS[@]}" \ "${INPUT_FILES[@]}" \ "${OPENSSL_LIBCRYPTO}" \ -o "${OUTPUT_FILE}" \ -std=c++17 GENERATED_TAG="generated" sed -i.bak -e "1i\/\/ \@${GENERATED_TAG}" "${OUTPUT_FILE}" mv -f "${OUTPUT_DIR}${OUTPUT_FILE_NAME}.wasm" "${OUTPUT_DIR}comm_query_executor.wasm" rm -f "${OUTPUT_FILE}.bak"