Verified Commit 007ba433 authored by Linus Jahn's avatar Linus Jahn Committed by Linus Jahn

media-sharing: Save media hashes in database

All media hashes are now saved in the messages table. They are saved just in the
XML format of 'XEP-0300: Use of Cryptographic Hash Functions in XMPP'.

This also adds a mediaThumb column to the messages table.
parent 9a59a190
......@@ -41,7 +41,7 @@
#include <QSqlQuery>
#include <QSqlRecord>
static const int DATABASE_LATEST_VERSION = 6;
static const int DATABASE_LATEST_VERSION = 7;
static const char *DATABASE_TABLE_INFO = "dbinfo";
static const char *DATABASE_TABLE_MESSAGES = "Messages";
static const char *DATABASE_TABLE_ROSTER = "Roster";
......@@ -139,6 +139,8 @@ void Database::convertDatabase()
convertDatabaseToV5(); version = 5; break;
case 5:
convertDatabaseToV6(); version = 6; break;
case 6:
convertDatabaseToV7(); version = 7; break;
default:
break;
}
......@@ -204,6 +206,8 @@ void Database::createNewDatabase()
"'mediaContentType' TEXT,"
"'mediaLastModified' INTEGER,"
"'mediaLocation' TEXT,"
"'mediaThumb' BLOB,"
"'mediaHashes' TEXT,"
"FOREIGN KEY('author') REFERENCES Roster ('jid'),"
"FOREIGN KEY('recipient') REFERENCES Roster ('jid')"
")"
......@@ -290,6 +294,15 @@ void Database::convertDatabaseToV6()
}
}
void Database::convertDatabaseToV7()
{
QSqlQuery query(database);
query.prepare(QString("ALTER TABLE 'Messages' ADD 'mediaThumb' BLOB"));
execQuery(query);
query.prepare(QString("ALTER TABLE 'Messages' ADD 'mediaHashes' TEXT"));
execQuery(query);
}
void Database::execQuery(QSqlQuery &query)
{
if (!query.exec()) {
......
......@@ -58,6 +58,7 @@ private:
void convertDatabaseToV4();
void convertDatabaseToV5();
void convertDatabaseToV6();
void convertDatabaseToV7();
void execQuery(QSqlQuery &query);
QSqlDatabase database;
......
......@@ -149,6 +149,8 @@ void MessageHandler::handleMessage(const gloox::Message &stanza, gloox::MessageS
msg.mediaLastModified = stringToQDateTime(file->date()).toTime_t();
QMimeType mimeType = QMimeDatabase().mimeTypeForName(msg.mediaContentType);
msg.type = getMessageType(mimeType);
for (gloox::Hash &hash : file->hashes())
msg.mediaHashes.append(QString::fromStdString(hash.tag()->xml()));
}
}
......
......@@ -106,38 +106,49 @@ void MessageModel::setMessageAsDelivered(const QString msgId)
void MessageModel::updateMessage(const QString id, Message msg)
{
QStringList list;
QMap<QString, QVariant> values;
if (!msg.timestamp.isEmpty())
list << QString("'timestamp' = '%1'").arg(msg.timestamp);
values["timestamp"] = msg.timestamp;
if (!msg.message.isEmpty())
list << QString("'message' = '%1'").arg(msg.message);
values["message"] = msg.message;
if (!msg.id.isEmpty())
list << QString("'id' = '%1'").arg(msg.id);
values["id"] = msg.id;
if (!msg.mediaUrl.isEmpty())
list << QString("'mediaUrl' = '%1'").arg(msg.mediaUrl);
values["mediaUrl"] = msg.mediaUrl;
if (msg.mediaSize)
list << QString("'mediaSize' = %1").arg(msg.mediaSize);
values["mediaSize"] = msg.mediaSize;
if (!msg.mediaContentType.isEmpty())
list << QString("'mediaContentType' = '%1'").arg(msg.mediaContentType);
values["mediaContentType"] = msg.mediaContentType;
if (msg.mediaLastModified)
list << QString("'mediaLastModified' = %1").arg(msg.mediaLastModified);
values["mediaLastModified"] = msg.mediaLastModified;
if (!msg.mediaLocation.isEmpty())
list << QString("'mediaLocation' = '%1'").arg(msg.mediaLocation);
QString sets;
values["mediaLocation"] = msg.mediaLocation;
if (!msg.mediaThumb.isEmpty())
values["mediaThumb"] = msg.mediaThumb;
if (!msg.mediaHashes.isEmpty())
values["mediaHashes"] = msg.mediaHashes;
// generate command
QString command = "UPDATE 'Messages' SET ";
bool isFirst = true;
for (auto part : list) {
for (auto key : values.keys()) {
if (!isFirst)
sets.append(", ");
sets.append(part);
command.append(", ");
command.append(QString("%1 = :%1").arg(key));
isFirst = false;
}
QString command = "UPDATE 'Messages' SET %1 WHERE 'id' = '%2'";
command = command.arg(sets, id);
command.append(QString(" WHERE 'id' = '%1'").arg(id));
QSqlQuery query(*database);
query.exec(command);
query.prepare(command);
for (auto key : values.keys()) {
query.bindValue(QString(":%1").arg(key), values[key]);
}
if (!query.exec()) {
qDebug() << query.executedQuery();
qWarning("Failed to query database: %s", qPrintable(query.lastError().text()));
}
}
void MessageModel::addMessage(Message msg)
......@@ -164,6 +175,8 @@ void MessageModel::addMessage(Message msg)
if (msg.mediaLastModified)
record.setValue("mediaLastModified", msg.mediaLastModified);
record.setValue("mediaLocation", msg.mediaLocation);
record.setValue("mediaThumb", msg.mediaThumb);
record.setValue("mediaHashes", msg.mediaHashes);
if (!insertRecord(rowCount(), record)) {
qWarning() << "Failed to add message to DB:" << lastError().text();
......
......@@ -66,6 +66,8 @@ public:
QString mediaContentType;
quint64 mediaLastModified;
QString mediaLocation;
QByteArray mediaThumb;
QString mediaHashes;
};
signals:
......
......@@ -99,28 +99,28 @@ void UploadHandler::handleUploadFinished(int id, std::string &name,
unsigned long &size)
{
qDebug() << "[client] A file upload has finished.";
// save new information to database
// prepare new database message
MessageModel::Message msg;
msg.mediaUrl = QString::fromStdString(getUrl);
msg.mediaContentType = QString::fromStdString(contentType);
msg.mediaSize = size;
// TODO: mediaLastModified
emit msgModel->updateMessageRequested(
QString::fromStdString(mediaShares[id].msgId), msg
);
//
// Create SIMS element
//
// TODO: generate thumbnail
// TODO: lastModified / date
// Hashes
QtHttpUploader::HashResult hashResults = uploader->getHashResults(id);
std::list<gloox::Hash> hashes;
hashes.emplace_back(gloox::Hash("sha-256", hashResults.sha256.toBase64().toStdString()));
hashes.emplace_back(gloox::Hash("sha3-256", hashResults.sha3_256.toBase64().toStdString()));
// save hashes in database field
for (gloox::Hash &hash : hashes)
msg.mediaHashes.append(QString::fromStdString(hash.tag()->xml()));
// last modified date
std::string date = "";
// file meta information
gloox::Jingle::File *fileInfo = new gloox::Jingle::File(
name, size, hashes, contentType, date,
mediaShares[id].message.toStdString()
......@@ -130,14 +130,11 @@ void UploadHandler::handleUploadFinished(int id, std::string &name,
gloox::StringList sources;
sources.emplace_back(getUrl);
// create message
gloox::SIMS *sims = new gloox::SIMS(fileInfo, sources);
gloox::Reference *simsRef = new gloox::Reference(gloox::Reference::Data);
simsRef->embedSIMS(sims);
//
// Create message
//
gloox::JID to(mediaShares[id].jid.toStdString());
// message body for clients without SIMS support
std::string msgBody = getUrl;
......@@ -150,6 +147,11 @@ void UploadHandler::handleUploadFinished(int id, std::string &name,
client->send(message);
// save to database
emit msgModel->updateMessageRequested(
QString::fromStdString(mediaShares[id].msgId), msg
);
// the media meta isn't needed anymore, so delete it
mediaShares.remove(id);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment