Add use_custom_database_format option
This commit is contained in:
parent
09b98f6b30
commit
46c0f5877d
6
.gitignore
vendored
6
.gitignore
vendored
@ -9,3 +9,9 @@ docs/
|
||||
.idea/
|
||||
vcpkg/
|
||||
*.tlo
|
||||
|
||||
td.binlog
|
||||
|
||||
tg_cli.log
|
||||
|
||||
tg_cli.log.old
|
||||
|
@ -87,6 +87,56 @@ class Global final : public ActorContext {
|
||||
|
||||
Status init(const TdParameters ¶meters, ActorId<Td> td, unique_ptr<TdDb> 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;
|
||||
}
|
||||
|
@ -3007,12 +3007,15 @@ td_api::object_ptr<td_api::AuthorizationState> 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<td_api::Function> function) {
|
||||
switch (function_id) {
|
||||
case td_api::checkDatabaseEncryptionKey::ID: {
|
||||
auto check_key = move_tl_object_as<td_api::checkDatabaseEncryptionKey>(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<td_api::setDatabaseEncryptionKey>(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<td_api::tdlibParameters> 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) {
|
||||
|
@ -1344,7 +1344,7 @@ class Td final : public Actor {
|
||||
static td_api::object_ptr<td_api::Object> do_static_request(const td_api::addLogMessage &request);
|
||||
static td_api::object_ptr<td_api::Object> 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();
|
||||
|
@ -303,8 +303,16 @@ Status TdDb::init_sqlite(int32 scheduler_id, const TdParameters ¶meters, con
|
||||
sql_connection_ = std::make_shared<SqliteConnectionSafe>(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.
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user