mirror of
https://github.com/sqlitebrowser/sqlitebrowser.git
synced 2026-01-20 11:00:44 -06:00
Add automatic crypted databases open via dotenvs (#1404)
* Rename confusing variables
* Fix some project warnings
* Fix code style
* Add constant for the default page size
* Move KeyFormats enum to CipherSettings
* Fix code style
* Fix memory leak
* Stop relying on CipherDialog for encryption settings management
* Fix code style
* Add .env format for QSettings
* Add automatic crypted databases open via dotenvs
This adds support for `.env` files next to the crypted databases that
are to be opened that contains the needed cipher settings.
The only required one is the plain-text password as a value for the key
with the name of the database like this:
myCryptedDatabase.sqlite = MyPassword
This way, databases with a different extension are supported too:
myCryptedDatabase.db = MyPassword
You can also specify a custom page size adding a different line
(anywhere in the file) like this:
myCryptedDatabase.db_pageSize = 2048
If not specified, `1024` is used.
You can also specify the format of the specified key using the
associated integer id:
anotherCryptedDatabase.sqlite = 0xCAFEBABE
anotherCryptedDatabase.sqlite_keyFormat = 1
where `1` means a Raw key. If not specified, `0` is used, which means a
simple text Passphrase.
Dotenv files (`.env`) are already used on other platforms and by
different tools to manage environment variables, and it's recommended
to be ignored from version control systems, so they won't leak.
* Add new files to CMakeLists
* Move DotenvFormat include to the implementation
* Fix build error
* Remove superfluous method
(related to ac51c23)
* Remove superfluous checks
* Fix memory leaks
(introduced by 94bbb46)
* Fix code style
* Make dotenv related variable and comment clearer
* Remove duplicated code
* Remove unused forward declaration
(introduced by e5a0293)
This commit is contained in:
committed by
Martin Kleusberg
parent
c861f1b9d9
commit
3cdc65a63f
@@ -49,34 +49,33 @@ CipherDialog::~CipherDialog()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
CipherDialog::KeyFormats CipherDialog::keyFormat() const
|
||||
CipherSettings CipherDialog::getCipherSettings() const
|
||||
{
|
||||
return static_cast<CipherDialog::KeyFormats>(ui->comboKeyFormat->currentIndex());
|
||||
}
|
||||
CipherSettings::KeyFormats keyFormat = CipherSettings::getKeyFormat(ui->comboKeyFormat->currentIndex());
|
||||
QString password = ui->editPassword->text();
|
||||
int pageSize = ui->comboPageSize->itemData(ui->comboPageSize->currentIndex()).toInt();
|
||||
|
||||
QString CipherDialog::password() const
|
||||
{
|
||||
if(keyFormat() == KeyFormats::Passphrase)
|
||||
return QString("'%1'").arg(ui->editPassword->text().replace("'", "''"));
|
||||
else
|
||||
return QString("\"x'%1'\"").arg(ui->editPassword->text().mid(2)); // Remove the '0x' part at the beginning
|
||||
}
|
||||
CipherSettings cipherSettings;
|
||||
|
||||
int CipherDialog::pageSize() const
|
||||
{
|
||||
return ui->comboPageSize->itemData(ui->comboPageSize->currentIndex()).toInt();
|
||||
cipherSettings.setKeyFormat(keyFormat);
|
||||
cipherSettings.setPassword(password);
|
||||
cipherSettings.setPageSize(pageSize);
|
||||
|
||||
return cipherSettings;
|
||||
}
|
||||
|
||||
void CipherDialog::checkInputFields()
|
||||
{
|
||||
if(sender() == ui->comboKeyFormat)
|
||||
{
|
||||
if(keyFormat() == KeyFormats::Passphrase)
|
||||
CipherSettings::KeyFormats keyFormat = CipherSettings::getKeyFormat(ui->comboKeyFormat->currentIndex());
|
||||
|
||||
if(keyFormat == CipherSettings::KeyFormats::Passphrase)
|
||||
{
|
||||
ui->editPassword->setValidator(nullptr);
|
||||
ui->editPassword2->setValidator(nullptr);
|
||||
ui->editPassword->setPlaceholderText("");
|
||||
} else if(keyFormat() == KeyFormats::RawKey) {
|
||||
} else if(keyFormat == CipherSettings::KeyFormats::RawKey) {
|
||||
ui->editPassword->setValidator(rawKeyValidator);
|
||||
ui->editPassword2->setValidator(rawKeyValidator);
|
||||
ui->editPassword->setPlaceholderText("0x...");
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "CipherSettings.h"
|
||||
|
||||
class QRegExpValidator;
|
||||
|
||||
namespace Ui {
|
||||
@@ -14,21 +16,12 @@ class CipherDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum KeyFormats
|
||||
{
|
||||
Passphrase,
|
||||
RawKey
|
||||
};
|
||||
|
||||
// Set the encrypt parameter to true when the dialog is used to encrypt a database;
|
||||
// set it to false if the dialog is used to ask the user for the key to decrypt a file.
|
||||
explicit CipherDialog(QWidget* parent, bool encrypt);
|
||||
~CipherDialog();
|
||||
|
||||
// Allow read access to the input fields
|
||||
KeyFormats keyFormat() const;
|
||||
QString password() const;
|
||||
int pageSize() const;
|
||||
CipherSettings getCipherSettings() const;
|
||||
|
||||
private:
|
||||
Ui::CipherDialog* ui;
|
||||
|
||||
49
src/CipherSettings.cpp
Normal file
49
src/CipherSettings.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "CipherSettings.h"
|
||||
|
||||
CipherSettings::KeyFormats CipherSettings::getKeyFormat() const
|
||||
{
|
||||
return keyFormat;
|
||||
}
|
||||
|
||||
void CipherSettings::setKeyFormat(const KeyFormats &value)
|
||||
{
|
||||
keyFormat = value;
|
||||
}
|
||||
|
||||
QString CipherSettings::getPassword() const
|
||||
{
|
||||
if(keyFormat == Passphrase)
|
||||
{
|
||||
QString tempPassword = password;
|
||||
|
||||
tempPassword.replace("'", "''");
|
||||
|
||||
return QString("'%1'").arg(tempPassword);
|
||||
} else {
|
||||
// Remove the '0x' part at the beginning
|
||||
return QString("\"x'%1'\"").arg(password.mid(2));
|
||||
}
|
||||
}
|
||||
|
||||
void CipherSettings::setPassword(const QString &value)
|
||||
{
|
||||
password = value;
|
||||
}
|
||||
|
||||
int CipherSettings::getPageSize() const
|
||||
{
|
||||
if (pageSize == 0)
|
||||
return defaultPageSize;
|
||||
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
void CipherSettings::setPageSize(int value)
|
||||
{
|
||||
pageSize = value;
|
||||
}
|
||||
|
||||
CipherSettings::KeyFormats CipherSettings::getKeyFormat(int rawKeyFormat)
|
||||
{
|
||||
return static_cast<CipherSettings::KeyFormats>(rawKeyFormat);
|
||||
}
|
||||
34
src/CipherSettings.h
Normal file
34
src/CipherSettings.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef CIPHERSETTINGS_H
|
||||
#define CIPHERSETTINGS_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
class CipherSettings
|
||||
{
|
||||
public:
|
||||
enum KeyFormats
|
||||
{
|
||||
Passphrase,
|
||||
RawKey
|
||||
};
|
||||
|
||||
static const int defaultPageSize = 1024;
|
||||
|
||||
KeyFormats getKeyFormat() const;
|
||||
void setKeyFormat(const KeyFormats &value);
|
||||
|
||||
QString getPassword() const;
|
||||
void setPassword(const QString &value);
|
||||
|
||||
int getPageSize() const;
|
||||
void setPageSize(int value);
|
||||
|
||||
static KeyFormats getKeyFormat(int rawKeyFormat);
|
||||
|
||||
private:
|
||||
KeyFormats keyFormat;
|
||||
QString password;
|
||||
int pageSize;
|
||||
};
|
||||
|
||||
#endif // CIPHERSETTINGS_H
|
||||
28
src/DotenvFormat.cpp
Normal file
28
src/DotenvFormat.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include "DotenvFormat.h"
|
||||
|
||||
#include <QRegularExpression>
|
||||
#include <QTextStream>
|
||||
|
||||
bool DotenvFormat::readEnvFile(QIODevice &device, QSettings::SettingsMap &map)
|
||||
{
|
||||
QTextStream in(&device);
|
||||
|
||||
QString line;
|
||||
|
||||
QRegularExpression keyValueRegex("^\\s*([\\w\\.\\-]+)\\s*=\\s*(.*)\\s*$");
|
||||
|
||||
while (in.readLineInto(&line)) {
|
||||
QRegularExpressionMatch match = keyValueRegex.match(line);
|
||||
|
||||
if (match.capturedLength() < 3) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QString key = match.captured(1);
|
||||
QString value = match.captured(2);
|
||||
|
||||
map.insert(key, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
13
src/DotenvFormat.h
Normal file
13
src/DotenvFormat.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef DOTENVFORMAT_H
|
||||
#define DOTENVFORMAT_H
|
||||
|
||||
#include <QIODevice>
|
||||
#include <QSettings>
|
||||
|
||||
class DotenvFormat
|
||||
{
|
||||
public:
|
||||
static bool readEnvFile(QIODevice &device, QSettings::SettingsMap &map);
|
||||
};
|
||||
|
||||
#endif // DOTENVFORMAT_H
|
||||
@@ -2530,8 +2530,8 @@ void MainWindow::updateFilter(int column, const QString& value)
|
||||
void MainWindow::editEncryption()
|
||||
{
|
||||
#ifdef ENABLE_SQLCIPHER
|
||||
CipherDialog dialog(this, true);
|
||||
if(dialog.exec())
|
||||
CipherDialog cipherDialog(this, true);
|
||||
if(cipherDialog.exec())
|
||||
{
|
||||
// Show progress dialog even though we can't provide any detailed progress information but this
|
||||
// process might take some time.
|
||||
@@ -2553,14 +2553,16 @@ void MainWindow::editEncryption()
|
||||
file.close();
|
||||
}
|
||||
|
||||
CipherSettings cipherSettings = cipherDialog.getCipherSettings();
|
||||
|
||||
// Attach a new database using the new settings
|
||||
qApp->processEvents();
|
||||
if(ok)
|
||||
ok = db.executeSQL(QString("ATTACH DATABASE '%1' AS sqlitebrowser_edit_encryption KEY %2;").arg(db.currentFile() + ".enctemp").arg(dialog.password()),
|
||||
ok = db.executeSQL(QString("ATTACH DATABASE '%1' AS sqlitebrowser_edit_encryption KEY %2;").arg(db.currentFile() + ".enctemp").arg(cipherSettings.getPassword()),
|
||||
false, false);
|
||||
qApp->processEvents();
|
||||
if(ok)
|
||||
ok = db.executeSQL(QString("PRAGMA sqlitebrowser_edit_encryption.cipher_page_size = %1").arg(dialog.pageSize()), false, false);
|
||||
ok = db.executeSQL(QString("PRAGMA sqlitebrowser_edit_encryption.cipher_page_size = %1").arg(cipherSettings.getPageSize()), false, false);
|
||||
|
||||
// Export the current database to the new one
|
||||
qApp->processEvents();
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#define SETTINGS_H
|
||||
|
||||
#include <QApplication>
|
||||
#include <QVariant>
|
||||
#include <QHash>
|
||||
#include <QVariant>
|
||||
|
||||
class Settings
|
||||
{
|
||||
|
||||
141
src/sqlitedb.cpp
141
src/sqlitedb.cpp
@@ -2,6 +2,8 @@
|
||||
#include "sqlite.h"
|
||||
#include "sqlitetablemodel.h"
|
||||
#include "CipherDialog.h"
|
||||
#include "CipherSettings.h"
|
||||
#include "DotenvFormat.h"
|
||||
#include "Settings.h"
|
||||
|
||||
#include <QFile>
|
||||
@@ -104,8 +106,8 @@ bool DBBrowserDB::open(const QString& db, bool readOnly)
|
||||
dontCheckForStructureUpdates = false;
|
||||
|
||||
// Get encryption settings for database file
|
||||
CipherDialog* cipher = nullptr;
|
||||
if(tryEncryptionSettings(db, &isEncrypted, cipher) == false)
|
||||
CipherSettings* cipherSettings = nullptr;
|
||||
if(tryEncryptionSettings(db, &isEncrypted, cipherSettings) == false)
|
||||
return false;
|
||||
|
||||
// Open database file
|
||||
@@ -117,14 +119,14 @@ bool DBBrowserDB::open(const QString& db, bool readOnly)
|
||||
|
||||
// Set encryption details if database is encrypted
|
||||
#ifdef ENABLE_SQLCIPHER
|
||||
if(isEncrypted && cipher)
|
||||
if(isEncrypted && cipherSettings)
|
||||
{
|
||||
executeSQL(QString("PRAGMA key = %1").arg(cipher->password()), false, false);
|
||||
if(cipher->pageSize() != 1024)
|
||||
executeSQL(QString("PRAGMA cipher_page_size = %1;").arg(cipher->pageSize()), false, false);
|
||||
executeSQL(QString("PRAGMA key = %1").arg(cipherSettings->getPassword()), false, false);
|
||||
if(cipherSettings->getPageSize() != CipherSettings::defaultPageSize)
|
||||
executeSQL(QString("PRAGMA cipher_page_size = %1;").arg(cipherSettings->getPageSize()), false, false);
|
||||
}
|
||||
#endif
|
||||
delete cipher;
|
||||
delete cipherSettings;
|
||||
|
||||
if (_db)
|
||||
{
|
||||
@@ -172,7 +174,7 @@ bool DBBrowserDB::open(const QString& db, bool readOnly)
|
||||
}
|
||||
}
|
||||
|
||||
bool DBBrowserDB::attach(const QString& filename, QString attach_as)
|
||||
bool DBBrowserDB::attach(const QString& filePath, QString attach_as)
|
||||
{
|
||||
if(!_db)
|
||||
return false;
|
||||
@@ -186,7 +188,7 @@ bool DBBrowserDB::attach(const QString& filename, QString attach_as)
|
||||
if(sqlite3_prepare_v2(_db, sql.toUtf8(), sql.toUtf8().length(), &db_vm, nullptr) == SQLITE_OK)
|
||||
{
|
||||
// Loop through all the databases
|
||||
QFileInfo fi(filename);
|
||||
QFileInfo fi(filePath);
|
||||
while(sqlite3_step(db_vm) == SQLITE_ROW)
|
||||
{
|
||||
QFileInfo path(QString::fromUtf8((const char*)sqlite3_column_text(db_vm, 2)));
|
||||
@@ -205,38 +207,39 @@ bool DBBrowserDB::attach(const QString& filename, QString attach_as)
|
||||
qApp->applicationName(),
|
||||
tr("Please specify the database name under which you want to access the attached database"),
|
||||
QLineEdit::Normal,
|
||||
QFileInfo(filename).baseName()
|
||||
QFileInfo(filePath).baseName()
|
||||
).trimmed();
|
||||
if(attach_as.isNull())
|
||||
return false;
|
||||
|
||||
#ifdef ENABLE_SQLCIPHER
|
||||
// Try encryption settings
|
||||
CipherDialog* cipher = nullptr;
|
||||
CipherSettings* cipherSettings = nullptr;
|
||||
bool is_encrypted;
|
||||
if(tryEncryptionSettings(filename, &is_encrypted, cipher) == false)
|
||||
if(tryEncryptionSettings(filePath, &is_encrypted, cipherSettings) == false)
|
||||
return false;
|
||||
|
||||
// Attach database
|
||||
QString key;
|
||||
if(cipher && is_encrypted)
|
||||
key = "KEY " + cipher->password();
|
||||
if(!executeSQL(QString("ATTACH '%1' AS %2 %3").arg(filename).arg(sqlb::escapeIdentifier(attach_as)).arg(key), false))
|
||||
if(cipherSettings && is_encrypted)
|
||||
key = "KEY " + cipherSettings->getPassword();
|
||||
if(!executeSQL(QString("ATTACH '%1' AS %2 %3").arg(filePath).arg(sqlb::escapeIdentifier(attach_as)).arg(key), false))
|
||||
{
|
||||
QMessageBox::warning(nullptr, qApp->applicationName(), lastErrorMessage);
|
||||
return false;
|
||||
}
|
||||
if(cipher && cipher->pageSize() != 1024)
|
||||
if(cipherSettings && cipherSettings->getPageSize() != CipherSettings::defaultPageSize)
|
||||
{
|
||||
if(!executeSQL(QString("PRAGMA %1.cipher_page_size = %2").arg(sqlb::escapeIdentifier(attach_as)).arg(cipher->pageSize()), false))
|
||||
if(!executeSQL(QString("PRAGMA %1.cipher_page_size = %2").arg(sqlb::escapeIdentifier(attach_as)).arg(cipherSettings->getPageSize()), false))
|
||||
{
|
||||
QMessageBox::warning(nullptr, qApp->applicationName(), lastErrorMessage);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
delete cipherSettings;
|
||||
#else
|
||||
// Attach database
|
||||
if(!executeSQL(QString("ATTACH '%1' AS %2").arg(filename).arg(sqlb::escapeIdentifier(attach_as)), false))
|
||||
if(!executeSQL(QString("ATTACH '%1' AS %2").arg(filePath).arg(sqlb::escapeIdentifier(attach_as)), false))
|
||||
{
|
||||
QMessageBox::warning(nullptr, qApp->applicationName(), lastErrorMessage);
|
||||
return false;
|
||||
@@ -249,16 +252,21 @@ bool DBBrowserDB::attach(const QString& filename, QString attach_as)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DBBrowserDB::tryEncryptionSettings(const QString& filename, bool* encrypted, CipherDialog*& cipherSettings)
|
||||
bool DBBrowserDB::tryEncryptionSettings(const QString& filePath, bool* encrypted, CipherSettings*& cipherSettings)
|
||||
{
|
||||
lastErrorMessage = tr("Invalid file format");
|
||||
|
||||
// Open database file
|
||||
sqlite3* dbHandle;
|
||||
if(sqlite3_open_v2(filename.toUtf8(), &dbHandle, SQLITE_OPEN_READONLY, nullptr) != SQLITE_OK)
|
||||
if(sqlite3_open_v2(filePath.toUtf8(), &dbHandle, SQLITE_OPEN_READONLY, nullptr) != SQLITE_OK)
|
||||
return false;
|
||||
|
||||
// Try reading from database
|
||||
|
||||
#ifdef ENABLE_SQLCIPHER
|
||||
bool isDotenvChecked = false;
|
||||
#endif
|
||||
|
||||
*encrypted = false;
|
||||
cipherSettings = nullptr;
|
||||
while(true)
|
||||
@@ -279,32 +287,81 @@ bool DBBrowserDB::tryEncryptionSettings(const QString& filename, bool* encrypted
|
||||
{
|
||||
sqlite3_finalize(vm);
|
||||
#ifdef ENABLE_SQLCIPHER
|
||||
delete cipherSettings;
|
||||
cipherSettings = new CipherDialog(nullptr, false);
|
||||
if(cipherSettings->exec())
|
||||
{
|
||||
// Close and reopen database first to be in a clean state after the failed read attempt from above
|
||||
sqlite3_close(dbHandle);
|
||||
if(sqlite3_open_v2(filename.toUtf8(), &dbHandle, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK)
|
||||
bool foundDotenvPassword = false;
|
||||
|
||||
// Being in a while loop, we don't want to check the same file multiple times
|
||||
if (!isDotenvChecked) {
|
||||
QFile databaseFile(filePath);
|
||||
QFileInfo databaseFileInfo(databaseFile);
|
||||
|
||||
QString databaseDirectoryPath = databaseFileInfo.dir().path();
|
||||
QString databaseFileName(databaseFileInfo.fileName());
|
||||
|
||||
QString dotenvFilePath = databaseDirectoryPath + "/.env";
|
||||
static const QSettings::Format dotenvFormat = QSettings::registerFormat("env", &DotenvFormat::readEnvFile, nullptr);
|
||||
QSettings dotenv(dotenvFilePath, dotenvFormat);
|
||||
|
||||
QVariant passwordValue = dotenv.value(databaseFileName);
|
||||
|
||||
foundDotenvPassword = !passwordValue.isNull();
|
||||
|
||||
isDotenvChecked = true;
|
||||
|
||||
if (foundDotenvPassword)
|
||||
{
|
||||
QString password = passwordValue.toString();
|
||||
|
||||
QVariant keyFormatValue = dotenv.value(databaseFileName + "_keyFormat", QVariant(CipherSettings::KeyFormats::Passphrase));
|
||||
CipherSettings::KeyFormats keyFormat = CipherSettings::getKeyFormat(keyFormatValue.toInt());
|
||||
|
||||
QVariant pageSizeValue = dotenv.value(databaseFileName + "_pageSize", QVariant(CipherSettings::defaultPageSize));
|
||||
int pageSize = pageSizeValue.toInt();
|
||||
|
||||
delete cipherSettings;
|
||||
cipherSettings = nullptr;
|
||||
return false;
|
||||
cipherSettings = new CipherSettings();
|
||||
|
||||
cipherSettings->setKeyFormat(keyFormat);
|
||||
cipherSettings->setPassword(password);
|
||||
cipherSettings->setPageSize(pageSize);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Set key and, if it differs from the default value, the page size
|
||||
sqlite3_exec(dbHandle, QString("PRAGMA key = %1").arg(cipherSettings->password()).toUtf8(), NULL, NULL, NULL);
|
||||
if(cipherSettings->pageSize() != 1024)
|
||||
sqlite3_exec(dbHandle, QString("PRAGMA cipher_page_size = %1;").arg(cipherSettings->pageSize()).toUtf8(), NULL, NULL, NULL);
|
||||
|
||||
*encrypted = true;
|
||||
if(foundDotenvPassword)
|
||||
{
|
||||
// Skip the CipherDialog prompt for now to test if the dotenv password was correct
|
||||
} else {
|
||||
sqlite3_close(dbHandle);
|
||||
*encrypted = false;
|
||||
CipherDialog *cipherDialog = new CipherDialog(nullptr, false);
|
||||
if(cipherDialog->exec())
|
||||
{
|
||||
delete cipherSettings;
|
||||
cipherSettings = new CipherSettings(cipherDialog->getCipherSettings());
|
||||
} else {
|
||||
sqlite3_close(dbHandle);
|
||||
*encrypted = false;
|
||||
delete cipherSettings;
|
||||
cipherSettings = nullptr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Close and reopen database first to be in a clean state after the failed read attempt from above
|
||||
sqlite3_close(dbHandle);
|
||||
if(sqlite3_open_v2(filePath.toUtf8(), &dbHandle, SQLITE_OPEN_READONLY, nullptr) != SQLITE_OK)
|
||||
{
|
||||
delete cipherSettings;
|
||||
cipherSettings = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the key
|
||||
sqlite3_exec(dbHandle, QString("PRAGMA key = %1").arg(cipherSettings->getPassword()).toUtf8(), nullptr, nullptr, nullptr);
|
||||
|
||||
// Set the page size if it differs from the default value
|
||||
if(cipherSettings->getPageSize() != CipherSettings::defaultPageSize)
|
||||
sqlite3_exec(dbHandle, QString("PRAGMA cipher_page_size = %1;").arg(cipherSettings->getPageSize()).toUtf8(), nullptr, nullptr, nullptr);
|
||||
|
||||
*encrypted = true;
|
||||
#else
|
||||
lastErrorMessage = QString::fromUtf8((const char*)sqlite3_errmsg(dbHandle));
|
||||
sqlite3_close(dbHandle);
|
||||
@@ -540,7 +597,7 @@ void DBBrowserDB::waitForDbRelease()
|
||||
}
|
||||
}
|
||||
|
||||
bool DBBrowserDB::dump(const QString& filename,
|
||||
bool DBBrowserDB::dump(const QString& filePath,
|
||||
const QStringList& tablesToDump,
|
||||
bool insertColNames,
|
||||
bool insertNewSyntx,
|
||||
@@ -551,7 +608,7 @@ bool DBBrowserDB::dump(const QString& filename,
|
||||
waitForDbRelease();
|
||||
|
||||
// Open file
|
||||
QFile file(filename);
|
||||
QFile file(filePath);
|
||||
if(file.open(QIODevice::WriteOnly))
|
||||
{
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
@@ -1650,14 +1707,14 @@ bool DBBrowserDB::setPragma(const QString& pragma, int value, int& originalvalue
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DBBrowserDB::loadExtension(const QString& filename)
|
||||
bool DBBrowserDB::loadExtension(const QString& filePath)
|
||||
{
|
||||
waitForDbRelease();
|
||||
if(!_db)
|
||||
return false;
|
||||
|
||||
// Check if file exists
|
||||
if(!QFile::exists(filename))
|
||||
if(!QFile::exists(filePath))
|
||||
{
|
||||
lastErrorMessage = tr("File not found.");
|
||||
return false;
|
||||
@@ -1665,7 +1722,7 @@ bool DBBrowserDB::loadExtension(const QString& filename)
|
||||
|
||||
// Try to load extension
|
||||
char* error;
|
||||
if(sqlite3_load_extension(_db, filename.toUtf8(), nullptr, &error) == SQLITE_OK)
|
||||
if(sqlite3_load_extension(_db, filePath.toUtf8(), nullptr, &error) == SQLITE_OK)
|
||||
{
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <QByteArray>
|
||||
|
||||
struct sqlite3;
|
||||
class CipherDialog;
|
||||
class CipherSettings;
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -205,7 +205,7 @@ private:
|
||||
|
||||
void collationNeeded(void* pData, sqlite3* db, int eTextRep, const char* sCollationName);
|
||||
|
||||
bool tryEncryptionSettings(const QString& filename, bool* encrypted, CipherDialog*& cipherSettings);
|
||||
bool tryEncryptionSettings(const QString& filename, bool* encrypted, CipherSettings*& cipherSettings);
|
||||
|
||||
bool dontCheckForStructureUpdates;
|
||||
|
||||
|
||||
@@ -65,7 +65,9 @@ HEADERS += \
|
||||
FindReplaceDialog.h \
|
||||
ExtendedScintilla.h \
|
||||
FileExtensionManager.h \
|
||||
Data.h
|
||||
Data.h \
|
||||
CipherSettings.h \
|
||||
DotenvFormat.h
|
||||
|
||||
SOURCES += \
|
||||
sqlitedb.cpp \
|
||||
@@ -107,7 +109,9 @@ SOURCES += \
|
||||
FindReplaceDialog.cpp \
|
||||
ExtendedScintilla.cpp \
|
||||
FileExtensionManager.cpp \
|
||||
Data.cpp
|
||||
Data.cpp \
|
||||
CipherSettings.cpp \
|
||||
DotenvFormat.cpp
|
||||
|
||||
RESOURCES += icons/icons.qrc \
|
||||
translations/flags/flags.qrc \
|
||||
|
||||
@@ -17,6 +17,8 @@ set(TESTSQLOBJECTS_SRC
|
||||
../Settings.cpp
|
||||
testsqlobjects.cpp
|
||||
../Data.cpp
|
||||
../CipherSettings.cpp
|
||||
../DotenvFormat.cpp
|
||||
)
|
||||
|
||||
set(TESTSQLOBJECTS_HDR
|
||||
@@ -32,6 +34,8 @@ set(TESTSQLOBJECTS_MOC_HDR
|
||||
../sqlitetablemodel.h
|
||||
../Settings.h
|
||||
testsqlobjects.h
|
||||
../CipherSettings.h
|
||||
../DotenvFormat.h
|
||||
)
|
||||
|
||||
if(sqlcipher)
|
||||
@@ -92,6 +96,8 @@ set(TESTREGEX_SRC
|
||||
../Settings.cpp
|
||||
TestRegex.cpp
|
||||
../Data.cpp
|
||||
../CipherSettings.cpp
|
||||
../DotenvFormat.cpp
|
||||
)
|
||||
|
||||
set(TESTREGEX_HDR
|
||||
@@ -107,6 +113,8 @@ set(TESTREGEX_MOC_HDR
|
||||
../sqlitetablemodel.h
|
||||
../Settings.h
|
||||
TestRegex.h
|
||||
../CipherSettings.h
|
||||
../DotenvFormat.h
|
||||
)
|
||||
|
||||
if(sqlcipher)
|
||||
|
||||
Reference in New Issue
Block a user