1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00

Fix avatars for encrypted profiles

WARNING: Note that avatars for encrypted profiles are currently stored unencrypted!
This commit is contained in:
tux3 2015-12-05 19:08:28 +01:00
parent d71986c20a
commit 25ed3d4fba
No known key found for this signature in database
GPG Key ID: 7E086DD661263264
14 changed files with 92 additions and 141 deletions

View File

@ -298,8 +298,7 @@ void Core::start()
tox_callback_file_recv_chunk(tox, CoreFile::onFileRecvChunkCallback, this); tox_callback_file_recv_chunk(tox, CoreFile::onFileRecvChunkCallback, this);
tox_callback_file_recv_control(tox, CoreFile::onFileControlCallback, this); tox_callback_file_recv_control(tox, CoreFile::onFileControlCallback, this);
HistoryKeeper::getInstance()->importAvatarToDatabase(getSelfId().toString().left(64)); QPixmap pic = profile.loadAvatar();
QPixmap pic = Settings::getInstance().getSavedAvatar(getSelfId().toString());
if (!pic.isNull() && !pic.size().isEmpty()) if (!pic.isNull() && !pic.size().isEmpty())
{ {
QByteArray data; QByteArray data;
@ -767,7 +766,7 @@ void Core::setAvatar(const QByteArray& data)
{ {
QPixmap pic; QPixmap pic;
pic.loadFromData(data); pic.loadFromData(data);
Settings::getInstance().saveAvatar(pic, getSelfId().toString()); profile.saveAvatar(data, getSelfId().publicKey);
emit selfAvatarChanged(pic); emit selfAvatarChanged(pic);
} }
else else

View File

@ -23,6 +23,7 @@
#include "corestructs.h" #include "corestructs.h"
#include "src/core/cstring.h" #include "src/core/cstring.h"
#include "src/persistence/settings.h" #include "src/persistence/settings.h"
#include "src/persistence/profile.h"
#include <QDebug> #include <QDebug>
#include <QFile> #include <QFile>
#include <QThread> #include <QThread>
@ -278,7 +279,7 @@ void CoreFile::onFileReceiveCallback(Tox*, uint32_t friendId, uint32_t fileId, u
static_assert(TOX_HASH_LENGTH <= TOX_FILE_ID_LENGTH, "TOX_HASH_LENGTH > TOX_FILE_ID_LENGTH!"); static_assert(TOX_HASH_LENGTH <= TOX_FILE_ID_LENGTH, "TOX_HASH_LENGTH > TOX_FILE_ID_LENGTH!");
uint8_t avatarHash[TOX_FILE_ID_LENGTH]; uint8_t avatarHash[TOX_FILE_ID_LENGTH];
tox_file_get_file_id(core->tox, friendId, fileId, avatarHash, nullptr); tox_file_get_file_id(core->tox, friendId, fileId, avatarHash, nullptr);
if (Settings::getInstance().getAvatarHash(friendAddr) == QByteArray((char*)avatarHash, TOX_HASH_LENGTH)) if (core->profile.getAvatarHash(friendAddr) == QByteArray((char*)avatarHash, TOX_HASH_LENGTH))
{ {
// If it's an avatar but we already have it cached, cancel // If it's an avatar but we already have it cached, cancel
qDebug() << QString("Received avatar request %1:%2, reject, since we have it in cache.").arg(friendId).arg(fileId); qDebug() << QString("Received avatar request %1:%2, reject, since we have it in cache.").arg(friendId).arg(fileId);
@ -402,11 +403,12 @@ void CoreFile::onFileDataCallback(Tox *tox, uint32_t friendId, uint32_t fileId,
} }
void CoreFile::onFileRecvChunkCallback(Tox *tox, uint32_t friendId, uint32_t fileId, uint64_t position, void CoreFile::onFileRecvChunkCallback(Tox *tox, uint32_t friendId, uint32_t fileId, uint64_t position,
const uint8_t *data, size_t length, void *core) const uint8_t *data, size_t length, void *_core)
{ {
//qDebug() << QString("Received chunk for %1:%2 pos %3 size %4") //qDebug() << QString("Received chunk for %1:%2 pos %3 size %4")
// .arg(friendId).arg(fileId).arg(position).arg(length); // .arg(friendId).arg(fileId).arg(position).arg(length);
Core* core = static_cast<Core*>(_core);
ToxFile* file = findFile(friendId, fileId); ToxFile* file = findFile(friendId, fileId);
if (!file) if (!file)
{ {
@ -420,7 +422,7 @@ void CoreFile::onFileRecvChunkCallback(Tox *tox, uint32_t friendId, uint32_t fil
/// TODO: Allow ooo receiving for non-stream transfers, with very careful checking /// TODO: Allow ooo receiving for non-stream transfers, with very careful checking
qWarning("onFileRecvChunkCallback: Received a chunk out-of-order, aborting transfer"); qWarning("onFileRecvChunkCallback: Received a chunk out-of-order, aborting transfer");
if (file->fileKind != TOX_FILE_KIND_AVATAR) if (file->fileKind != TOX_FILE_KIND_AVATAR)
emit static_cast<Core*>(core)->fileTransferCancelled(*file); emit core->fileTransferCancelled(*file);
tox_file_control(tox, friendId, fileId, TOX_FILE_CONTROL_CANCEL, nullptr); tox_file_control(tox, friendId, fileId, TOX_FILE_CONTROL_CANCEL, nullptr);
removeFile(friendId, fileId); removeFile(friendId, fileId);
return; return;
@ -435,15 +437,14 @@ void CoreFile::onFileRecvChunkCallback(Tox *tox, uint32_t friendId, uint32_t fil
if (!pic.isNull()) if (!pic.isNull())
{ {
qDebug() << "Got"<<file->avatarData.size()<<"bytes of avatar data from" <<friendId; qDebug() << "Got"<<file->avatarData.size()<<"bytes of avatar data from" <<friendId;
Settings::getInstance().saveAvatar(pic, static_cast<Core*>(core)->getFriendAddress(friendId)); core->profile.saveAvatar(file->avatarData, core->getFriendAddress(friendId));
Settings::getInstance().saveAvatarHash(file->resumeFileId, static_cast<Core*>(core)->getFriendAddress(friendId)); emit core->friendAvatarChanged(friendId, pic);
emit static_cast<Core*>(core)->friendAvatarChanged(friendId, pic);
} }
} }
else else
{ {
emit static_cast<Core*>(core)->fileTransferFinished(*file); emit core->fileTransferFinished(*file);
emit static_cast<Core*>(core)->fileDownloadFinished(file->filePath); emit core->fileDownloadFinished(file->filePath);
} }
removeFile(friendId, fileId); removeFile(friendId, fileId);
return; return;

View File

@ -40,7 +40,6 @@ Friend::Friend(uint32_t FriendId, const ToxId &UserId)
widget = new FriendWidget(friendId, getDisplayedName()); widget = new FriendWidget(friendId, getDisplayedName());
chatForm = new ChatForm(this); chatForm = new ChatForm(this);
HistoryKeeper::getInstance()->importAvatarToDatabase(UserId.publicKey);
} }
Friend::~Friend() Friend::~Friend()

View File

@ -169,24 +169,6 @@ HistoryKeeper::HistoryKeeper(GenericDdInterface *db_) :
messageID = sqlAnswer.value(0).toLongLong(); messageID = sqlAnswer.value(0).toLongLong();
} }
void HistoryKeeper::importAvatarToDatabase(const QString& ownerId)
{
if (needImport)
{
QString puth (Settings::getInstance().getSettingsDirPath() +
QString("avatars") + QDir::separator() +
ownerId +".png");
qDebug() << QString("Try import avatar for: %1.").arg(ownerId);
getAliasID(ownerId);
if (QFile::exists(puth) && !hasAvatar(ownerId))
{
QPixmap pic(puth);
saveAvatar(pic,ownerId);
qDebug() << QString("Import avatar for: %1.").arg(ownerId);
}
}
}
HistoryKeeper::~HistoryKeeper() HistoryKeeper::~HistoryKeeper()
{ {
delete db; delete db;
@ -512,64 +494,3 @@ QList<HistoryKeeper::HistMessage> HistoryKeeper::exportMessagesDeleteFile()
return msgs; return msgs;
} }
void HistoryKeeper::removeAvatar(const QString& ownerId)
{
QSqlQuery query;
query.prepare("UPDATE aliases SET avatar=NULL, av_hash=NULL WHERE user_id = (:id)");
query.bindValue(":id", ownerId.left(64));
query.exec();
}
bool HistoryKeeper::hasAvatar(const QString& ownerId)
{
QSqlQuery sqlAnswer = db->exec(QString("SELECT avatar FROM aliases WHERE user_id= '%1'").arg(ownerId.left(64)));
return !sqlAnswer.isNull(0);
}
void HistoryKeeper::saveAvatar(QPixmap& pic, const QString& ownerId)
{
QByteArray bArray;
QBuffer buffer(&bArray);
buffer.open(QIODevice::WriteOnly);
pic.save(&buffer, "PNG");
QSqlQuery query;
query.prepare("UPDATE aliases SET avatar=:image WHERE user_id = (:id)");
query.bindValue(":image", bArray);
query.bindValue(":id", ownerId.left(64));
query.exec();
}
QPixmap HistoryKeeper::getSavedAvatar(const QString &ownerId)
{
QByteArray bArray;
QPixmap pixmap = QPixmap();
QSqlQuery sqlAnswer = db->exec(QString("SELECT avatar FROM aliases WHERE user_id= '%1'").arg(ownerId.left(64)));
if (sqlAnswer.first())
{
bArray = sqlAnswer.value(0).toByteArray();
pixmap.loadFromData(bArray);
}
return pixmap;
}
void HistoryKeeper::saveAvatarHash(const QByteArray& hash, const QString& ownerId)
{
QSqlQuery query;
query.prepare("UPDATE aliases SET av_hash=:hash WHERE user_id = (:id)");
query.bindValue(":hash", QString(hash.toBase64()));
query.bindValue(":id", ownerId.left(64));
query.exec();
}
QByteArray HistoryKeeper::getAvatarHash(const QString& ownerId)
{
QByteArray bArray;
QSqlQuery sqlAnswer = db->exec(QString("SELECT avatar FROM aliases WHERE user_id= '%1'").arg(ownerId.left(64)));
if (sqlAnswer.first())
{
bArray = sqlAnswer.value(0).toByteArray();
}
return bArray;
}

View File

@ -74,17 +74,6 @@ public:
void setSyncType(Db::syncType sType); void setSyncType(Db::syncType sType);
void saveAvatar(QPixmap& pic, const QString& ownerId);
QPixmap getSavedAvatar(const QString &ownerId);
void saveAvatarHash(const QByteArray& hash, const QString& ownerId);
QByteArray getAvatarHash(const QString& ownerId);
void removeAvatar(const QString& ownerId);
bool hasAvatar(const QString& ownerId);
void importAvatarToDatabase(const QString& ownerId); // may be deleted after all move to new db structure
private: private:
HistoryKeeper(GenericDdInterface *db_); HistoryKeeper(GenericDdInterface *db_);
HistoryKeeper(HistoryKeeper &hk) = delete; HistoryKeeper(HistoryKeeper &hk) = delete;

View File

@ -325,6 +325,62 @@ void Profile::saveToxSave(QByteArray data)
newProfile = false; newProfile = false;
} }
QString Profile::avatarPath(const QString &ownerId)
{
return Settings::getInstance().getSettingsDirPath() + "avatars/" + ownerId + ".png";
}
QPixmap Profile::loadAvatar()
{
return loadAvatar(core->getSelfId().publicKey);
}
QPixmap Profile::loadAvatar(const QString &ownerId)
{
QPixmap pic;
pic.loadFromData(loadAvatarData(ownerId));
return pic;
}
QByteArray Profile::loadAvatarData(const QString &ownerId)
{
QFile file(avatarPath(ownerId));
if (!file.open(QIODevice::ReadOnly))
return {};
return file.readAll();
}
void Profile::saveAvatar(QByteArray pic, const QString &ownerId)
{
QString path = avatarPath(ownerId);
QSaveFile file(avatarPath(ownerId));
if (!file.open(QIODevice::WriteOnly))
{
qWarning() << "Tox avatar " << path << " couldn't be saved";
return;
}
file.write(pic);
file.commit();
}
QByteArray Profile::getAvatarHash(const QString &ownerId)
{
QByteArray pic = loadAvatarData(ownerId);
QByteArray avatarHash(TOX_HASH_LENGTH, 0);
tox_hash((uint8_t*)avatarHash.data(), (uint8_t*)pic.data(), pic.size());
return avatarHash;
}
void Profile::removeAvatar()
{
removeAvatar(core->getSelfId().publicKey);
}
void Profile::removeAvatar(const QString &ownerId)
{
QFile::remove(avatarPath(ownerId));
}
bool Profile::exists(QString name) bool Profile::exists(QString name)
{ {
QString path = Settings::getInstance().getSettingsDirPath() + name; QString path = Settings::getInstance().getSettingsDirPath() + name;

View File

@ -24,6 +24,7 @@
#include <QVector> #include <QVector>
#include <QString> #include <QString>
#include <QByteArray> #include <QByteArray>
#include <QPixmap>
#include <tox/toxencryptsave.h> #include <tox/toxencryptsave.h>
class Core; class Core;
@ -58,6 +59,14 @@ public:
void saveToxSave(); ///< Saves the profile's .tox save, encrypted if needed. Invalid on deleted profiles. void saveToxSave(); ///< Saves the profile's .tox save, encrypted if needed. Invalid on deleted profiles.
void saveToxSave(QByteArray data); ///< Write the .tox save, encrypted if needed. Invalid on deleted profiles. void saveToxSave(QByteArray data); ///< Write the .tox save, encrypted if needed. Invalid on deleted profiles.
QPixmap loadAvatar(); ///< Get our avatar from cache
QPixmap loadAvatar(const QString& ownerId); ///< Get a contact's avatar from cache
QByteArray loadAvatarData(const QString& ownerId); ///< Get a contact's avatar from cache
void saveAvatar(QByteArray pic, const QString& ownerId); ///< Save an avatar to cache
QByteArray getAvatarHash(const QString& ownerId); ///< Get the tox hash of a cached avatar
void removeAvatar(const QString& ownerId); ///< Removes a cached avatar
void removeAvatar(); ///< Removes our own avatar
/// Removes the profile permanently /// Removes the profile permanently
/// It is invalid to call loadToxSave or saveToxSave on a deleted profile /// It is invalid to call loadToxSave or saveToxSave on a deleted profile
/// Updates the profiles vector /// Updates the profiles vector
@ -82,6 +91,7 @@ private:
/// Creates a .ini file for the given .tox profile /// Creates a .ini file for the given .tox profile
/// Only pass the basename, without extension /// Only pass the basename, without extension
static void importProfile(QString name); static void importProfile(QString name);
QString avatarPath(const QString& ownerId);
private: private:
Core* core; Core* core;

View File

@ -539,26 +539,6 @@ QString Settings::getSettingsDirPath()
#endif #endif
} }
QPixmap Settings::getSavedAvatar(const QString &ownerId)
{
return HistoryKeeper::getInstance()->getSavedAvatar(ownerId);
}
void Settings::saveAvatar(QPixmap& pic, const QString& ownerId)
{
HistoryKeeper::getInstance()->saveAvatar(pic,ownerId);
}
void Settings::saveAvatarHash(const QByteArray& hash, const QString& ownerId)
{
HistoryKeeper::getInstance()->saveAvatarHash(hash,ownerId);
}
QByteArray Settings::getAvatarHash(const QString& ownerId)
{
return HistoryKeeper::getInstance()->getAvatarHash(ownerId);
}
const QList<DhtServer>& Settings::getDhtServerList() const const QList<DhtServer>& Settings::getDhtServerList() const
{ {
QMutexLocker locker{&bigLock}; QMutexLocker locker{&bigLock};

View File

@ -142,12 +142,6 @@ public:
bool getGroupAlwaysNotify() const; bool getGroupAlwaysNotify() const;
void setGroupAlwaysNotify(bool newValue); void setGroupAlwaysNotify(bool newValue);
QPixmap getSavedAvatar(const QString& ownerId);
void saveAvatar(QPixmap& pic, const QString& ownerId);
QByteArray getAvatarHash(const QString& ownerId);
void saveAvatarHash(const QByteArray& hash, const QString& ownerId);
QString getInDev() const; QString getInDev() const;
void setInDev(const QString& deviceSpecifier); void setInDev(const QString& deviceSpecifier);

View File

@ -20,9 +20,10 @@
#include "groupnetcamview.h" #include "groupnetcamview.h"
#include "src/widget/tool/croppinglabel.h" #include "src/widget/tool/croppinglabel.h"
#include "src/video/videosurface.h" #include "src/video/videosurface.h"
#include "src/persistence/settings.h" #include "src/persistence/profile.h"
#include "src/audio/audio.h" #include "src/audio/audio.h"
#include "src/core/core.h" #include "src/core/core.h"
#include "src/nexus.h"
#include "src/friendlist.h" #include "src/friendlist.h"
#include "src/friend.h" #include "src/friend.h"
#include <QBoxLayout> #include <QBoxLayout>
@ -132,7 +133,7 @@ GroupNetCamView::GroupNetCamView(int group, QWidget *parent)
horLayout = new QHBoxLayout(widget); horLayout = new QHBoxLayout(widget);
horLayout->addStretch(1); horLayout->addStretch(1);
selfVideoSurface = new LabeledVideo(Settings::getInstance().getSavedAvatar(Core::getInstance()->getSelfId().toString()), this); selfVideoSurface = new LabeledVideo(Nexus::getProfile()->loadAvatar(), this);
horLayout->addWidget(selfVideoSurface); horLayout->addWidget(selfVideoSurface);
horLayout->addStretch(1); horLayout->addStretch(1);
@ -171,7 +172,7 @@ void GroupNetCamView::clearPeers()
void GroupNetCamView::addPeer(int peer, const QString& name) void GroupNetCamView::addPeer(int peer, const QString& name)
{ {
QPixmap groupAvatar = Settings::getInstance().getSavedAvatar(Core::getInstance()->getGroupPeerToxId(group, peer).toString()); QPixmap groupAvatar = Nexus::getProfile()->loadAvatar(Core::getInstance()->getGroupPeerToxId(group, peer).toString());
LabeledVideo* labeledVideo = new LabeledVideo(groupAvatar, this); LabeledVideo* labeledVideo = new LabeledVideo(groupAvatar, this);
labeledVideo->setText(name); labeledVideo->setText(name);
horLayout->insertWidget(horLayout->count() - 1, labeledVideo); horLayout->insertWidget(horLayout->count() - 1, labeledVideo);

View File

@ -25,6 +25,8 @@
#include "src/video/videosurface.h" #include "src/video/videosurface.h"
#include "src/widget/tool/movablewidget.h" #include "src/widget/tool/movablewidget.h"
#include "src/persistence/settings.h" #include "src/persistence/settings.h"
#include "src/persistence/profile.h"
#include "src/nexus.h"
#include <QLabel> #include <QLabel>
#include <QBoxLayout> #include <QBoxLayout>
#include <QFrame> #include <QFrame>
@ -35,13 +37,13 @@ NetCamView::NetCamView(int friendId, QWidget* parent)
, friendId{friendId} , friendId{friendId}
{ {
QString id = FriendList::findFriend(friendId)->getToxId().toString(); QString id = FriendList::findFriend(friendId)->getToxId().toString();
videoSurface = new VideoSurface(Settings::getInstance().getSavedAvatar(id), this); videoSurface = new VideoSurface(Nexus::getProfile()->loadAvatar(id), this);
videoSurface->setMinimumHeight(256); videoSurface->setMinimumHeight(256);
videoSurface->setContentsMargins(6, 6, 6, 6); videoSurface->setContentsMargins(6, 6, 6, 6);
verLayout->insertWidget(0, videoSurface, 1); verLayout->insertWidget(0, videoSurface, 1);
selfVideoSurface = new VideoSurface(Settings::getInstance().getSavedAvatar(Core::getInstance()->getSelfId().toString()), this, true); selfVideoSurface = new VideoSurface(Nexus::getProfile()->loadAvatar(), this, true);
selfVideoSurface->setObjectName(QStringLiteral("CamVideoSurface")); selfVideoSurface->setObjectName(QStringLiteral("CamVideoSurface"));
selfVideoSurface->setMouseTracking(true); selfVideoSurface->setMouseTracking(true);
selfVideoSurface->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); selfVideoSurface->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

View File

@ -2,6 +2,8 @@
#include "ui_aboutuser.h" #include "ui_aboutuser.h"
#include "src/persistence/settings.h" #include "src/persistence/settings.h"
#include "src/persistence/historykeeper.h" #include "src/persistence/historykeeper.h"
#include "src/persistence/profile.h"
#include "src/nexus.h"
#include <QDir> #include <QDir>
#include <QFileDialog> #include <QFileDialog>
@ -37,7 +39,7 @@ void AboutUser::setFriend(Friend *f)
ui->publicKey->setCursorPosition(0); //scroll textline to left ui->publicKey->setCursorPosition(0); //scroll textline to left
ui->note->setPlainText(Settings::getInstance().getContactNote(f->getToxId())); ui->note->setPlainText(Settings::getInstance().getContactNote(f->getToxId()));
QPixmap avatar = Settings::getInstance().getSavedAvatar(f->getToxId().toString()); QPixmap avatar = Nexus::getProfile()->loadAvatar(f->getToxId().toString());
ui->statusMessage->setText(f->getStatusMessage()); ui->statusMessage->setText(f->getStatusMessage());
if(!avatar.isNull()) { if(!avatar.isNull()) {
ui->avatar->setPixmap(avatar); ui->avatar->setPixmap(avatar);

View File

@ -188,11 +188,7 @@ void ProfileForm::showProfilePictureContextMenu(const QPoint &point)
QAction *selectedItem = contextMenu.exec(pos); QAction *selectedItem = contextMenu.exec(pos);
if (selectedItem == removeAction) if (selectedItem == removeAction)
{ Nexus::getProfile()->removeAvatar();
QString selfPubKey = Core::getInstance()->getSelfId().publicKey;
HistoryKeeper::getInstance()->removeAvatar(selfPubKey);
Core::getInstance()->setAvatar({});
}
} }
void ProfileForm::copyIdClicked() void ProfileForm::copyIdClicked()

View File

@ -43,6 +43,7 @@
#include "src/platform/timer.h" #include "src/platform/timer.h"
#include "systemtrayicon.h" #include "systemtrayicon.h"
#include "src/nexus.h" #include "src/nexus.h"
#include "src/persistence/profile.h"
#include "src/widget/gui.h" #include "src/widget/gui.h"
#include "src/persistence/offlinemsgengine.h" #include "src/persistence/offlinemsgengine.h"
#include "src/widget/translator.h" #include "src/widget/translator.h"
@ -918,7 +919,7 @@ void Widget::addFriend(int friendId, const QString &userId)
connect(core, &Core::friendAvatarRemoved, newfriend->getFriendWidget(), &FriendWidget::onAvatarRemoved); connect(core, &Core::friendAvatarRemoved, newfriend->getFriendWidget(), &FriendWidget::onAvatarRemoved);
// Try to get the avatar from the cache // Try to get the avatar from the cache
QPixmap avatar = Settings::getInstance().getSavedAvatar(userId); QPixmap avatar = Nexus::getProfile()->loadAvatar(userId);
if (!avatar.isNull()) if (!avatar.isNull())
{ {
newfriend->getChatForm()->onAvatarChange(friendId, avatar); newfriend->getChatForm()->onAvatarChange(friendId, avatar);
@ -1118,7 +1119,7 @@ void Widget::addFriendDialog(Friend *frnd, ContentDialog *dialog)
connect(Core::getInstance(), &Core::friendAvatarChanged, friendWidget, &FriendWidget::onAvatarChange); connect(Core::getInstance(), &Core::friendAvatarChanged, friendWidget, &FriendWidget::onAvatarChange);
connect(Core::getInstance(), &Core::friendAvatarRemoved, friendWidget, &FriendWidget::onAvatarRemoved); connect(Core::getInstance(), &Core::friendAvatarRemoved, friendWidget, &FriendWidget::onAvatarRemoved);
QPixmap avatar = Settings::getInstance().getSavedAvatar(frnd->getToxId().toString()); QPixmap avatar = Nexus::getProfile()->loadAvatar(frnd->getToxId().toString());
if (!avatar.isNull()) if (!avatar.isNull())
friendWidget->onAvatarChange(frnd->getFriendID(), avatar); friendWidget->onAvatarChange(frnd->getFriendID(), avatar);
} }