|
|
|
@ -195,10 +195,11 @@ bool dbSchema3to4(RawDatabase& db)
@@ -195,10 +195,11 @@ bool dbSchema3to4(RawDatabase& db)
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Upgrade the db schema |
|
|
|
|
* @return True if the schema upgrade succeded, false otherwise |
|
|
|
|
* @note On future alterations of the database all you have to do is bump the SCHEMA_VERSION |
|
|
|
|
* variable and add another case to the switch statement below. Make sure to fall through on each case. |
|
|
|
|
*/ |
|
|
|
|
void dbSchemaUpgrade(std::shared_ptr<RawDatabase>& db) |
|
|
|
|
bool dbSchemaUpgrade(std::shared_ptr<RawDatabase>& db) |
|
|
|
|
{ |
|
|
|
|
int64_t databaseSchemaVersion; |
|
|
|
|
|
|
|
|
@ -206,19 +207,17 @@ void dbSchemaUpgrade(std::shared_ptr<RawDatabase>& db)
@@ -206,19 +207,17 @@ void dbSchemaUpgrade(std::shared_ptr<RawDatabase>& db)
|
|
|
|
|
databaseSchemaVersion = row[0].toLongLong(); |
|
|
|
|
}))) { |
|
|
|
|
qCritical() << "History failed to read user_version"; |
|
|
|
|
db.reset(); |
|
|
|
|
return; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (databaseSchemaVersion > SCHEMA_VERSION) { |
|
|
|
|
qWarning().nospace() << "Database version (" << databaseSchemaVersion << |
|
|
|
|
") is newer than we currently support (" << SCHEMA_VERSION << "). Please upgrade qTox"; |
|
|
|
|
// We don't know what future versions have done, we have to disable db access until we re-upgrade
|
|
|
|
|
db.reset(); |
|
|
|
|
return; |
|
|
|
|
return false; |
|
|
|
|
} else if (databaseSchemaVersion == SCHEMA_VERSION) { |
|
|
|
|
// No work to do
|
|
|
|
|
return; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
switch (databaseSchemaVersion) { |
|
|
|
@ -231,22 +230,19 @@ void dbSchemaUpgrade(std::shared_ptr<RawDatabase>& db)
@@ -231,22 +230,19 @@ void dbSchemaUpgrade(std::shared_ptr<RawDatabase>& db)
|
|
|
|
|
const bool newDb = isNewDb(db, success); |
|
|
|
|
if (!success) { |
|
|
|
|
qCritical() << "Failed to create current db schema"; |
|
|
|
|
db.reset(); |
|
|
|
|
return; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
if (newDb) { |
|
|
|
|
if (!createCurrentSchema(*db)) { |
|
|
|
|
qCritical() << "Failed to create current db schema"; |
|
|
|
|
db.reset(); |
|
|
|
|
return; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
qDebug() << "Database created at schema version" << SCHEMA_VERSION; |
|
|
|
|
break; // new db is the only case where we don't incrementally upgrade through each version
|
|
|
|
|
} else { |
|
|
|
|
if (!dbSchema0to1(*db)) { |
|
|
|
|
qCritical() << "Failed to upgrade db to schema version 1, aborting"; |
|
|
|
|
db.reset(); |
|
|
|
|
return; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
qDebug() << "Database upgraded incrementally to schema version 1"; |
|
|
|
|
} |
|
|
|
@ -255,23 +251,20 @@ void dbSchemaUpgrade(std::shared_ptr<RawDatabase>& db)
@@ -255,23 +251,20 @@ void dbSchemaUpgrade(std::shared_ptr<RawDatabase>& db)
|
|
|
|
|
case 1: |
|
|
|
|
if (!dbSchema1to2(*db)) { |
|
|
|
|
qCritical() << "Failed to upgrade db to schema version 2, aborting"; |
|
|
|
|
db.reset(); |
|
|
|
|
return; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
qDebug() << "Database upgraded incrementally to schema version 2"; |
|
|
|
|
//fallthrough
|
|
|
|
|
case 2: |
|
|
|
|
if (!dbSchema2to3(*db)) { |
|
|
|
|
qCritical() << "Failed to upgrade db to schema version 3, aborting"; |
|
|
|
|
db.reset(); |
|
|
|
|
return; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
qDebug() << "Database upgraded incrementally to schema version 3"; |
|
|
|
|
case 3: |
|
|
|
|
if (!dbSchema3to4(*db)) { |
|
|
|
|
qCritical() << "Failed to upgrade db to schema version 4, aborting"; |
|
|
|
|
db.reset(); |
|
|
|
|
return; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
qDebug() << "Database upgraded incrementally to schema version 4"; |
|
|
|
|
// etc.
|
|
|
|
@ -279,6 +272,8 @@ void dbSchemaUpgrade(std::shared_ptr<RawDatabase>& db)
@@ -279,6 +272,8 @@ void dbSchemaUpgrade(std::shared_ptr<RawDatabase>& db)
|
|
|
|
|
qInfo() << "Database upgrade finished (databaseSchemaVersion" << databaseSchemaVersion |
|
|
|
|
<< "->" << SCHEMA_VERSION << ")"; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
MessageState getMessageState(bool isPending, bool isBroken) |
|
|
|
@ -318,18 +313,19 @@ FileDbInsertionData::FileDbInsertionData()
@@ -318,18 +313,19 @@ FileDbInsertionData::FileDbInsertionData()
|
|
|
|
|
* @brief Prepares the database to work with the history. |
|
|
|
|
* @param db This database will be prepared for use with the history. |
|
|
|
|
*/ |
|
|
|
|
History::History(std::shared_ptr<RawDatabase> db) |
|
|
|
|
: db(db) |
|
|
|
|
History::History(std::shared_ptr<RawDatabase> db_) |
|
|
|
|
: db(db_) |
|
|
|
|
{ |
|
|
|
|
if (!isValid()) { |
|
|
|
|
qWarning() << "Database not open, init failed"; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
dbSchemaUpgrade(db); |
|
|
|
|
const auto upgradeSucceeded = dbSchemaUpgrade(db); |
|
|
|
|
|
|
|
|
|
// dbSchemaUpgrade may have put us in an invalid state
|
|
|
|
|
if (!isValid()) { |
|
|
|
|
if (!upgradeSucceeded) { |
|
|
|
|
db.reset(); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -370,6 +366,10 @@ bool History::isValid()
@@ -370,6 +366,10 @@ bool History::isValid()
|
|
|
|
|
*/ |
|
|
|
|
bool History::historyExists(const ToxPk& friendPk) |
|
|
|
|
{ |
|
|
|
|
if (historyAccessBlocked()) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return !getMessagesForFriend(friendPk, 0, 1).empty(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -588,6 +588,10 @@ void History::addNewFileMessage(const QString& friendPk, const QString& fileId,
@@ -588,6 +588,10 @@ void History::addNewFileMessage(const QString& friendPk, const QString& fileId,
|
|
|
|
|
const QString& fileName, const QString& filePath, int64_t size, |
|
|
|
|
const QString& sender, const QDateTime& time, QString const& dispName) |
|
|
|
|
{ |
|
|
|
|
if (historyAccessBlocked()) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// This is an incredibly far from an optimal way of implementing this,
|
|
|
|
|
// but given the frequency that people are going to be initiating a file
|
|
|
|
|
// transfer we can probably live with it.
|
|
|
|
@ -644,11 +648,7 @@ void History::addNewMessage(const QString& friendPk, const QString& message, con
@@ -644,11 +648,7 @@ void History::addNewMessage(const QString& friendPk, const QString& message, con
|
|
|
|
|
const QDateTime& time, bool isDelivered, QString dispName, |
|
|
|
|
const std::function<void(RowId)>& insertIdCallback) |
|
|
|
|
{ |
|
|
|
|
if (!Settings::getInstance().getEnableLogging()) { |
|
|
|
|
qWarning() << "Blocked a message from being added to database while history is disabled"; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (!isValid()) { |
|
|
|
|
if (historyAccessBlocked()) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -659,6 +659,10 @@ void History::addNewMessage(const QString& friendPk, const QString& message, con
@@ -659,6 +659,10 @@ void History::addNewMessage(const QString& friendPk, const QString& message, con
|
|
|
|
|
void History::setFileFinished(const QString& fileId, bool success, const QString& filePath, |
|
|
|
|
const QByteArray& fileHash) |
|
|
|
|
{ |
|
|
|
|
if (historyAccessBlocked()) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
auto& fileInfo = fileInfos[fileId]; |
|
|
|
|
if (fileInfo.fileId.get() == -1) { |
|
|
|
|
fileInfo.finished = true; |
|
|
|
@ -674,11 +678,19 @@ void History::setFileFinished(const QString& fileId, bool success, const QString
@@ -674,11 +678,19 @@ void History::setFileFinished(const QString& fileId, bool success, const QString
|
|
|
|
|
|
|
|
|
|
size_t History::getNumMessagesForFriend(const ToxPk& friendPk) |
|
|
|
|
{ |
|
|
|
|
if (historyAccessBlocked()) { |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return getNumMessagesForFriendBeforeDate(friendPk, QDateTime()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
size_t History::getNumMessagesForFriendBeforeDate(const ToxPk& friendPk, const QDateTime& date) |
|
|
|
|
{ |
|
|
|
|
if (historyAccessBlocked()) { |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QString queryText = QString("SELECT COUNT(history.id) " |
|
|
|
|
"FROM history " |
|
|
|
|
"JOIN peers chat ON chat_id = chat.id " |
|
|
|
@ -704,6 +716,10 @@ size_t History::getNumMessagesForFriendBeforeDate(const ToxPk& friendPk, const Q
@@ -704,6 +716,10 @@ size_t History::getNumMessagesForFriendBeforeDate(const ToxPk& friendPk, const Q
|
|
|
|
|
QList<History::HistMessage> History::getMessagesForFriend(const ToxPk& friendPk, size_t firstIdx, |
|
|
|
|
size_t lastIdx) |
|
|
|
|
{ |
|
|
|
|
if (historyAccessBlocked()) { |
|
|
|
|
return {}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QList<HistMessage> messages; |
|
|
|
|
|
|
|
|
|
// Don't forget to update the rowCallback if you change the selected columns!
|
|
|
|
@ -763,6 +779,10 @@ QList<History::HistMessage> History::getMessagesForFriend(const ToxPk& friendPk,
@@ -763,6 +779,10 @@ QList<History::HistMessage> History::getMessagesForFriend(const ToxPk& friendPk,
|
|
|
|
|
|
|
|
|
|
QList<History::HistMessage> History::getUndeliveredMessagesForFriend(const ToxPk& friendPk) |
|
|
|
|
{ |
|
|
|
|
if (historyAccessBlocked()) { |
|
|
|
|
return {}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
auto queryText = |
|
|
|
|
QString("SELECT history.id, faux_offline_pending.id, timestamp, chat.public_key, " |
|
|
|
|
"aliases.display_name, sender.public_key, message, broken_messages.id " |
|
|
|
@ -809,6 +829,10 @@ QList<History::HistMessage> History::getUndeliveredMessagesForFriend(const ToxPk
@@ -809,6 +829,10 @@ QList<History::HistMessage> History::getUndeliveredMessagesForFriend(const ToxPk
|
|
|
|
|
QDateTime History::getDateWhereFindPhrase(const QString& friendPk, const QDateTime& from, |
|
|
|
|
QString phrase, const ParameterSearch& parameter) |
|
|
|
|
{ |
|
|
|
|
if (historyAccessBlocked()) { |
|
|
|
|
return QDateTime(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QDateTime result; |
|
|
|
|
auto rowCallback = [&result](const QVector<QVariant>& row) { |
|
|
|
|
result = QDateTime::fromMSecsSinceEpoch(row[0].toLongLong()); |
|
|
|
@ -903,6 +927,10 @@ QList<History::DateIdx> History::getNumMessagesForFriendBeforeDateBoundaries(con
@@ -903,6 +927,10 @@ QList<History::DateIdx> History::getNumMessagesForFriendBeforeDateBoundaries(con
|
|
|
|
|
const QDate& from, |
|
|
|
|
size_t maxNum) |
|
|
|
|
{ |
|
|
|
|
if (historyAccessBlocked()) { |
|
|
|
|
return {}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
auto friendPkString = friendPk.toString(); |
|
|
|
|
|
|
|
|
|
// No guarantee that this is the most efficient way to do this...
|
|
|
|
@ -954,9 +982,29 @@ QList<History::DateIdx> History::getNumMessagesForFriendBeforeDateBoundaries(con
@@ -954,9 +982,29 @@ QList<History::DateIdx> History::getNumMessagesForFriendBeforeDateBoundaries(con
|
|
|
|
|
*/ |
|
|
|
|
void History::markAsDelivered(RowId messageId) |
|
|
|
|
{ |
|
|
|
|
if (!isValid()) { |
|
|
|
|
if (historyAccessBlocked()) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
db->execLater(QString("DELETE FROM faux_offline_pending WHERE id=%1;").arg(messageId.get())); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Determines if history access should be blocked |
|
|
|
|
* @return True if history should not be accessed |
|
|
|
|
*/ |
|
|
|
|
bool History::historyAccessBlocked() |
|
|
|
|
{ |
|
|
|
|
if (!Settings::getInstance().getEnableLogging()) { |
|
|
|
|
assert(false); |
|
|
|
|
qCritical() << "Blocked history access while history is disabled"; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!isValid()) { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|