diff --git a/.gitignore b/.gitignore
index fc3274f5b..7e9db75e5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,9 @@ docs/
.idea/
vcpkg/
*.tlo
+
+td.binlog
+
+tg_cli.log
+
+tg_cli.log.old
diff --git a/td/telegram/Global.h b/td/telegram/Global.h
index d55f272c6..7aa7c7c49 100644
--- a/td/telegram/Global.h
+++ b/td/telegram/Global.h
@@ -87,6 +87,56 @@ class Global final : public ActorContext {
Status init(const TdParameters ¶meters, ActorId
td, unique_ptr td_db_ptr) TD_WARN_UNUSED_RESULT;
+ static bool get_use_custom_database(const std::string &database_directory) {
+ auto s = get_database_directory_opts(database_directory);
+ size_t qmarkpos;
+ std::string token;
+ size_t find_start_index = 0;
+ while ((qmarkpos = s.find_first_of('&'), find_start_index) != std::string::npos) {
+ token = s.substr(find_start_index, qmarkpos - find_start_index);
+ find_start_index = qmarkpos;
+ if ((qmarkpos = token.find_first_of('=')) != std::string::npos) {
+ std::string propkey = token.substr(0, qmarkpos), propval = token.substr(qmarkpos + 1);
+ if (propkey == "use_custom_database_format" && propval == "true") {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ static std::string get_database_directory_path(const std::string &database_directory) {
+ if (database_directory.empty()) {
+ return database_directory;
+ }
+ size_t qmarkpos;
+ if ((qmarkpos = database_directory.find_first_of('?')) != std::string::npos) {
+ std::string path = database_directory.substr(0, qmarkpos),
+ opts = database_directory.substr(qmarkpos + 1);
+ return path;
+ } else {
+ return database_directory;
+ }
+ }
+
+ static std::string get_database_directory_opts(const std::string &database_directory) {
+ if (database_directory.empty()) {
+ return database_directory;
+ }
+ size_t qmarkpos;
+ if ((qmarkpos = database_directory.find_first_of('?')) != std::string::npos) {
+ std::string path = database_directory.substr(0, qmarkpos),
+ opts = database_directory.substr(qmarkpos + 1);
+ return opts;
+ } else {
+ return "";
+ }
+ }
+
+ bool get_use_custom_database() const {
+ return parameters_.use_custom_db_format;
+ };
+
Slice get_dir() const {
return parameters_.database_directory;
}
diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp
index 6505f3e19..a03220c9a 100644
--- a/td/telegram/Td.cpp
+++ b/td/telegram/Td.cpp
@@ -3007,12 +3007,15 @@ td_api::object_ptr Td::get_fake_authorization_state_
}
}
-DbKey Td::as_db_key(string key) {
+DbKey Td::as_db_key(string key, bool custom_db) {
// Database will still be effectively not encrypted, but
// 1. SQLite database will be protected from corruption, because that's how sqlcipher works
// 2. security through obscurity
// 3. no need for reencryption of SQLite database
if (key.empty()) {
+ if (custom_db) {
+ return DbKey::empty();
+ }
return DbKey::raw_key("cucumber");
}
return DbKey::raw_key(std::move(key));
@@ -3080,11 +3083,11 @@ void Td::request(uint64 id, tl_object_ptr function) {
switch (function_id) {
case td_api::checkDatabaseEncryptionKey::ID: {
auto check_key = move_tl_object_as(function);
- return answer_ok_query(id, init(as_db_key(std::move(check_key->encryption_key_))));
+ return answer_ok_query(id, init(as_db_key(std::move(check_key->encryption_key_), parameters_.use_custom_db_format)));
}
case td_api::setDatabaseEncryptionKey::ID: {
auto set_key = move_tl_object_as(function);
- return answer_ok_query(id, init(as_db_key(std::move(set_key->new_encryption_key_))));
+ return answer_ok_query(id, init(as_db_key(std::move(set_key->new_encryption_key_), parameters_.use_custom_db_format)));
}
case td_api::destroy::ID:
// need to send response synchronously before actual destroying
@@ -4245,7 +4248,8 @@ Status Td::set_parameters(td_api::object_ptr parameters
}
parameters_.use_test_dc = parameters->use_test_dc_;
- parameters_.database_directory = parameters->database_directory_;
+ parameters_.database_directory = Global::get_database_directory_path(parameters->database_directory_);
+ parameters_.use_custom_db_format = Global::get_use_custom_database(parameters->database_directory_);
parameters_.files_directory = parameters->files_directory_;
parameters_.api_id = parameters->api_id_;
parameters_.api_hash = parameters->api_hash_;
@@ -4310,7 +4314,7 @@ void Td::on_request(uint64 id, const td_api::checkDatabaseEncryptionKey &request
void Td::on_request(uint64 id, td_api::setDatabaseEncryptionKey &request) {
CREATE_OK_REQUEST_PROMISE();
- G()->td_db()->get_binlog()->change_key(as_db_key(std::move(request.new_encryption_key_)), std::move(promise));
+ G()->td_db()->get_binlog()->change_key(as_db_key(std::move(request.new_encryption_key_), parameters_.use_custom_db_format), std::move(promise));
}
void Td::on_request(uint64 id, const td_api::getAuthorizationState &request) {
diff --git a/td/telegram/Td.h b/td/telegram/Td.h
index b8505a5ea..56627f595 100644
--- a/td/telegram/Td.h
+++ b/td/telegram/Td.h
@@ -1344,7 +1344,7 @@ class Td final : public Actor {
static td_api::object_ptr do_static_request(const td_api::addLogMessage &request);
static td_api::object_ptr do_static_request(td_api::testReturnError &request);
- static DbKey as_db_key(string key);
+ static DbKey as_db_key(string key, bool custom_db);
Status init(DbKey key) TD_WARN_UNUSED_RESULT;
void init_options_and_network();
void init_connection_creator();
diff --git a/td/telegram/TdDb.cpp b/td/telegram/TdDb.cpp
index 54605c1b4..bcc6535b8 100644
--- a/td/telegram/TdDb.cpp
+++ b/td/telegram/TdDb.cpp
@@ -303,8 +303,16 @@ Status TdDb::init_sqlite(int32 scheduler_id, const TdParameters ¶meters, con
sql_connection_ = std::make_shared(sql_database_path, key, db_instance.get_cipher_version());
sql_connection_->set(std::move(db_instance));
auto &db = sql_connection_->get();
- TRY_STATUS(db.exec("PRAGMA journal_mode=WAL"));
- TRY_STATUS(db.exec("PRAGMA secure_delete=1"));
+ if (parameters.use_custom_db_format) {
+ TRY_STATUS(db.exec("PRAGMA journal_mode=OFF"));
+ TRY_STATUS(db.exec("PRAGMA synchronous=OFF"))
+ TRY_STATUS(db.exec("PRAGMA temp_store=MEMORY"));
+ TRY_STATUS(db.exec("PRAGMA secure_delete=0"));
+ TRY_STATUS(db.exec("PRAGMA mmap_size=30000000000"));
+ } else {
+ TRY_STATUS(db.exec("PRAGMA journal_mode=WAL"));
+ TRY_STATUS(db.exec("PRAGMA secure_delete=1"));
+ }
// Init databases
// Do initialization once and before everything else to avoid "database is locked" error.
diff --git a/td/telegram/TdParameters.h b/td/telegram/TdParameters.h
index da6ee70f9..dd9359d0a 100644
--- a/td/telegram/TdParameters.h
+++ b/td/telegram/TdParameters.h
@@ -23,6 +23,7 @@ struct TdParameters {
bool use_secret_chats = false;
bool use_chat_info_db = false;
bool use_message_db = false;
+ bool use_custom_db_format = false;
};
} // namespace td
|