|
1 | 1 | #include "sqlitedb.h" |
2 | 2 | #include "sqlitetablemodel.h" |
| 3 | +#include "sqlite.h" |
3 | 4 |
|
4 | 5 | #include <QFile> |
5 | 6 | #include <QMessageBox> |
6 | 7 | #include <QProgressDialog> |
7 | 8 | #include <QApplication> |
8 | 9 | #include <QSettings> |
9 | 10 | #include <QDebug> |
10 | | -#include <sqlite3.h> |
| 11 | +#include <QInputDialog> |
11 | 12 |
|
12 | 13 | // collation callbacks |
13 | 14 | int collCompare(void* /*pArg*/, int /*eTextRepA*/, const void* sA, int /*eTextRepB*/, const void* sB) |
@@ -43,32 +44,62 @@ bool DBBrowserDB::getDirty() const |
43 | 44 | return !savepointList.empty(); |
44 | 45 | } |
45 | 46 |
|
46 | | -bool DBBrowserDB::open ( const QString & db) |
| 47 | +bool DBBrowserDB::open(const QString& db) |
47 | 48 | { |
48 | 49 | bool ok=false; |
49 | 50 | int err; |
50 | 51 |
|
51 | 52 | if (isOpen()) close(); |
52 | 53 |
|
53 | | - //try to verify the SQLite version 3 file header |
54 | | - QFile dbfile(db); |
55 | | - if ( dbfile.open( QIODevice::ReadOnly ) ) { |
56 | | - char buffer[16+1]; |
57 | | - dbfile.readLine(buffer, 16); |
58 | | - QString contents = QString(buffer); |
59 | | - dbfile.close(); |
60 | | - if (!contents.startsWith("SQLite format 3")) { |
61 | | - lastErrorMessage = QObject::tr("File is not a SQLite 3 database"); |
62 | | - return false; |
63 | | - } |
64 | | - } else { |
65 | | - lastErrorMessage = QObject::tr("File could not be read"); |
| 54 | + lastErrorMessage = QObject::tr("no error"); |
| 55 | + |
| 56 | + // Open database file |
| 57 | + if(sqlite3_open_v2(db.toUtf8(), &_db, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK) |
| 58 | + { |
| 59 | + lastErrorMessage = QString::fromUtf8((const char*)sqlite3_errmsg(_db)); |
66 | 60 | return false; |
67 | 61 | } |
68 | 62 |
|
69 | | - lastErrorMessage = QObject::tr("no error"); |
70 | | - |
71 | | - err = sqlite3_open_v2(db.toUtf8(), &_db, SQLITE_OPEN_READWRITE, NULL); |
| 63 | + // Try reading from database |
| 64 | + bool done = false; |
| 65 | + do |
| 66 | + { |
| 67 | + QString statement = "SELECT COUNT(*) FROM sqlite_master;"; |
| 68 | + QByteArray utf8Statement = statement.toUtf8(); |
| 69 | + sqlite3_stmt* vm; |
| 70 | + const char* tail; |
| 71 | + err = sqlite3_prepare_v2(_db, utf8Statement, utf8Statement.length(), &vm, &tail); |
| 72 | + if(sqlite3_step(vm) != SQLITE_ROW) |
| 73 | + { |
| 74 | +#ifdef SQLCIPHER |
| 75 | + QString pass = QInputDialog::getText(0, qApp->applicationName(), |
| 76 | + QObject::tr("Couldn't read from database file. This means it is either not a valid SQLite3 " |
| 77 | + "database or it is encrypted.\nIn the latter case you can provide a passphrase to open the file. Note" |
| 78 | + "that only databases encrypted using SQLCipher are supported.")); |
| 79 | + if(pass.isEmpty()) |
| 80 | + { |
| 81 | + sqlite3_close(_db); |
| 82 | + _db = 0; |
| 83 | + return false; |
| 84 | + } else { |
| 85 | + int pagesize = QInputDialog::getInt(0, qApp->applicationName(), |
| 86 | + QObject::tr("If the database has been encrypted using a different page size than normally (i.e. 1024 bytes) this " |
| 87 | + "value is required, too."), |
| 88 | + 1024, 0); |
| 89 | + if(pagesize == 0) pagesize = 1024; |
| 90 | + sqlite3_key(_db, pass.toUtf8(), pass.toUtf8().length()); |
| 91 | + sqlite3_exec(_db, QString("PRAGMA cipher_page_size = %1;").arg(pagesize).toUtf8(), NULL, NULL, NULL); |
| 92 | + } |
| 93 | +#else |
| 94 | + sqlite3_close(_db); |
| 95 | + _db = 0; |
| 96 | + return false; |
| 97 | +#endif |
| 98 | + } else { |
| 99 | + done = true; |
| 100 | + } |
| 101 | + sqlite3_finalize(vm); |
| 102 | + } while(!done); |
72 | 103 |
|
73 | 104 | // register collation callback |
74 | 105 | sqlite3_collation_needed(_db, NULL, collation_needed); |
|
0 commit comments