forked from blue/squawk
account refactoring, pep support discovery started
This commit is contained in:
parent
82d54ba4df
commit
69e0c88d8d
12 changed files with 588 additions and 394 deletions
|
@ -3,4 +3,6 @@ target_sources(squawk PRIVATE
|
|||
messagehandler.h
|
||||
rosterhandler.cpp
|
||||
rosterhandler.h
|
||||
vcardhandler.cpp
|
||||
vcardhandler.h
|
||||
)
|
||||
|
|
|
@ -176,7 +176,7 @@ void Core::MessageHandler::initializeMessage(Shared::Message& target, const QXmp
|
|||
target.setForwarded(forwarded);
|
||||
|
||||
if (guessing) {
|
||||
if (target.getFromJid() == acc->getLogin() + "@" + acc->getServer()) {
|
||||
if (target.getFromJid() == acc->getBareJid()) {
|
||||
outgoing = true;
|
||||
} else {
|
||||
outgoing = false;
|
||||
|
|
|
@ -26,7 +26,8 @@ Core::RosterHandler::RosterHandler(Core::Account* account):
|
|||
conferences(),
|
||||
groups(),
|
||||
queuedContacts(),
|
||||
outOfRosterContacts()
|
||||
outOfRosterContacts(),
|
||||
pepSupport(false)
|
||||
{
|
||||
connect(acc->rm, &QXmppRosterManager::rosterReceived, this, &RosterHandler::onRosterReceived);
|
||||
connect(acc->rm, &QXmppRosterManager::itemAdded, this, &RosterHandler::onRosterItemAdded);
|
||||
|
@ -51,8 +52,7 @@ Core::RosterHandler::~RosterHandler()
|
|||
|
||||
void Core::RosterHandler::onRosterReceived()
|
||||
{
|
||||
acc->vm->requestClientVCard(); //TODO need to make sure server actually supports vCards
|
||||
acc->ownVCardRequestInProgress = true;
|
||||
acc->requestVCard(acc->getBareJid()); //TODO need to make sure server actually supports vCards
|
||||
|
||||
QStringList bj = acc->rm->getRosterBareJids();
|
||||
for (int i = 0; i < bj.size(); ++i) {
|
||||
|
@ -588,4 +588,13 @@ void Core::RosterHandler::handleOffline()
|
|||
pair.second->clearArchiveRequests();
|
||||
pair.second->downgradeDatabaseState();
|
||||
}
|
||||
setPepSupport(false);
|
||||
}
|
||||
|
||||
|
||||
void Core::RosterHandler::setPepSupport(bool support)
|
||||
{
|
||||
if (pepSupport != support) {
|
||||
pepSupport = support;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ public:
|
|||
|
||||
void storeConferences();
|
||||
void clearConferences();
|
||||
void setPepSupport(bool support);
|
||||
|
||||
private slots:
|
||||
void onRosterReceived();
|
||||
|
@ -107,6 +108,7 @@ private:
|
|||
std::map<QString, std::set<QString>> groups;
|
||||
std::map<QString, QString> queuedContacts;
|
||||
std::set<QString> outOfRosterContacts;
|
||||
bool pepSupport;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
312
core/handlers/vcardhandler.cpp
Normal file
312
core/handlers/vcardhandler.cpp
Normal file
|
@ -0,0 +1,312 @@
|
|||
// Squawk messenger.
|
||||
// Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "vcardhandler.h"
|
||||
#include "core/account.h"
|
||||
|
||||
Core::VCardHandler::VCardHandler(Account* account):
|
||||
QObject(),
|
||||
acc(account),
|
||||
ownVCardRequestInProgress(false),
|
||||
pendingVCardRequests(),
|
||||
avatarHash(),
|
||||
avatarType()
|
||||
{
|
||||
connect(acc->vm, &QXmppVCardManager::vCardReceived, this, &VCardHandler::onVCardReceived);
|
||||
//for some reason it doesn't work, launching from common handler
|
||||
//connect(acc->vm, &QXmppVCardManager::clientVCardReceived, this, &VCardHandler::onOwnVCardReceived);
|
||||
|
||||
QString path(QStandardPaths::writableLocation(QStandardPaths::CacheLocation));
|
||||
path += "/" + acc->name;
|
||||
QDir dir(path);
|
||||
|
||||
if (!dir.exists()) {
|
||||
bool res = dir.mkpath(path);
|
||||
if (!res) {
|
||||
qDebug() << "Couldn't create a cache directory for account" << acc->name;
|
||||
throw 22;
|
||||
}
|
||||
}
|
||||
|
||||
QFile* avatar = new QFile(path + "/avatar.png");
|
||||
QString type = "png";
|
||||
if (!avatar->exists()) {
|
||||
delete avatar;
|
||||
avatar = new QFile(path + "/avatar.jpg");
|
||||
type = "jpg";
|
||||
if (!avatar->exists()) {
|
||||
delete avatar;
|
||||
avatar = new QFile(path + "/avatar.jpeg");
|
||||
type = "jpeg";
|
||||
if (!avatar->exists()) {
|
||||
delete avatar;
|
||||
avatar = new QFile(path + "/avatar.gif");
|
||||
type = "gif";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (avatar->exists()) {
|
||||
if (avatar->open(QFile::ReadOnly)) {
|
||||
QCryptographicHash sha1(QCryptographicHash::Sha1);
|
||||
sha1.addData(avatar);
|
||||
avatarHash = sha1.result();
|
||||
avatarType = type;
|
||||
}
|
||||
}
|
||||
if (avatarType.size() != 0) {
|
||||
acc->presence.setVCardUpdateType(QXmppPresence::VCardUpdateValidPhoto);
|
||||
acc->presence.setPhotoHash(avatarHash.toUtf8());
|
||||
} else {
|
||||
acc->presence.setVCardUpdateType(QXmppPresence::VCardUpdateNotReady);
|
||||
}
|
||||
}
|
||||
|
||||
Core::VCardHandler::~VCardHandler()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Core::VCardHandler::onVCardReceived(const QXmppVCardIq& card)
|
||||
{
|
||||
QString id = card.from();
|
||||
QStringList comps = id.split("/");
|
||||
QString jid = comps.front().toLower();
|
||||
QString resource("");
|
||||
if (comps.size() > 1) {
|
||||
resource = comps.back();
|
||||
}
|
||||
pendingVCardRequests.erase(id);
|
||||
RosterItem* item = acc->rh->getRosterItem(jid);
|
||||
|
||||
if (item == 0) {
|
||||
if (jid == acc->getBareJid()) {
|
||||
onOwnVCardReceived(card);
|
||||
} else {
|
||||
qDebug() << "received vCard" << jid << "doesn't belong to any of known contacts or conferences, skipping";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Shared::VCard vCard = item->handleResponseVCard(card, resource);
|
||||
|
||||
emit acc->receivedVCard(jid, vCard);
|
||||
}
|
||||
|
||||
void Core::VCardHandler::onOwnVCardReceived(const QXmppVCardIq& card)
|
||||
{
|
||||
QByteArray ava = card.photo();
|
||||
bool avaChanged = false;
|
||||
QString path = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/" + acc->name + "/";
|
||||
if (ava.size() > 0) {
|
||||
QCryptographicHash sha1(QCryptographicHash::Sha1);
|
||||
sha1.addData(ava);
|
||||
QString newHash(sha1.result());
|
||||
QMimeDatabase db;
|
||||
QMimeType newType = db.mimeTypeForData(ava);
|
||||
if (avatarType.size() > 0) {
|
||||
if (avatarHash != newHash) {
|
||||
QString oldPath = path + "avatar." + avatarType;
|
||||
QFile oldAvatar(oldPath);
|
||||
bool oldToRemove = false;
|
||||
if (oldAvatar.exists()) {
|
||||
if (oldAvatar.rename(oldPath + ".bak")) {
|
||||
oldToRemove = true;
|
||||
} else {
|
||||
qDebug() << "Received new avatar for account" << acc->name << "but can't get rid of the old one, doing nothing";
|
||||
}
|
||||
}
|
||||
QFile newAvatar(path + "avatar." + newType.preferredSuffix());
|
||||
if (newAvatar.open(QFile::WriteOnly)) {
|
||||
newAvatar.write(ava);
|
||||
newAvatar.close();
|
||||
avatarHash = newHash;
|
||||
avatarType = newType.preferredSuffix();
|
||||
avaChanged = true;
|
||||
} else {
|
||||
qDebug() << "Received new avatar for account" << acc->name << "but can't save it";
|
||||
if (oldToRemove) {
|
||||
qDebug() << "rolling back to the old avatar";
|
||||
if (!oldAvatar.rename(oldPath)) {
|
||||
qDebug() << "Couldn't roll back to the old avatar in account" << acc->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
QFile newAvatar(path + "avatar." + newType.preferredSuffix());
|
||||
if (newAvatar.open(QFile::WriteOnly)) {
|
||||
newAvatar.write(ava);
|
||||
newAvatar.close();
|
||||
avatarHash = newHash;
|
||||
avatarType = newType.preferredSuffix();
|
||||
avaChanged = true;
|
||||
} else {
|
||||
qDebug() << "Received new avatar for account" << acc->name << "but can't save it";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (avatarType.size() > 0) {
|
||||
QFile oldAvatar(path + "avatar." + avatarType);
|
||||
if (!oldAvatar.remove()) {
|
||||
qDebug() << "Received vCard for account" << acc->name << "without avatar, but can't get rid of the file, doing nothing";
|
||||
} else {
|
||||
avatarType = "";
|
||||
avatarHash = "";
|
||||
avaChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (avaChanged) {
|
||||
QMap<QString, QVariant> change;
|
||||
if (avatarType.size() > 0) {
|
||||
acc->presence.setPhotoHash(avatarHash.toUtf8());
|
||||
acc->presence.setVCardUpdateType(QXmppPresence::VCardUpdateValidPhoto);
|
||||
change.insert("avatarPath", path + "avatar." + avatarType);
|
||||
} else {
|
||||
acc->presence.setPhotoHash("");
|
||||
acc->presence.setVCardUpdateType(QXmppPresence::VCardUpdateNoPhoto);
|
||||
change.insert("avatarPath", "");
|
||||
}
|
||||
acc->client.setClientPresence(acc->presence);
|
||||
emit acc->changed(change);
|
||||
}
|
||||
|
||||
ownVCardRequestInProgress = false;
|
||||
|
||||
Shared::VCard vCard;
|
||||
initializeVCard(vCard, card);
|
||||
|
||||
if (avatarType.size() > 0) {
|
||||
vCard.setAvatarType(Shared::Avatar::valid);
|
||||
vCard.setAvatarPath(path + "avatar." + avatarType);
|
||||
} else {
|
||||
vCard.setAvatarType(Shared::Avatar::empty);
|
||||
}
|
||||
|
||||
emit acc->receivedVCard(acc->getBareJid(), vCard);
|
||||
}
|
||||
|
||||
void Core::VCardHandler::handleOffline()
|
||||
{
|
||||
pendingVCardRequests.clear();
|
||||
Shared::VCard vCard; //just to show, that there is now more pending request
|
||||
for (const QString& jid : pendingVCardRequests) {
|
||||
emit acc->receivedVCard(jid, vCard); //need to show it better in the future, like with an error
|
||||
}
|
||||
pendingVCardRequests.clear();
|
||||
ownVCardRequestInProgress = false;
|
||||
}
|
||||
|
||||
void Core::VCardHandler::requestVCard(const QString& jid)
|
||||
{
|
||||
if (pendingVCardRequests.find(jid) == pendingVCardRequests.end()) {
|
||||
qDebug() << "requesting vCard" << jid;
|
||||
if (jid == acc->getBareJid()) {
|
||||
if (!ownVCardRequestInProgress) {
|
||||
acc->vm->requestClientVCard();
|
||||
ownVCardRequestInProgress = true;
|
||||
}
|
||||
} else {
|
||||
acc->vm->requestVCard(jid);
|
||||
pendingVCardRequests.insert(jid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Core::VCardHandler::handleOtherPresenceOfMyAccountChange(const QXmppPresence& p_presence)
|
||||
{
|
||||
if (!ownVCardRequestInProgress) {
|
||||
switch (p_presence.vCardUpdateType()) {
|
||||
case QXmppPresence::VCardUpdateNone: //this presence has nothing to do with photo
|
||||
break;
|
||||
case QXmppPresence::VCardUpdateNotReady: //let's say the photo didn't change here
|
||||
break;
|
||||
case QXmppPresence::VCardUpdateNoPhoto: //there is no photo, need to drop if any
|
||||
if (avatarType.size() > 0) {
|
||||
acc->vm->requestClientVCard();
|
||||
ownVCardRequestInProgress = true;
|
||||
}
|
||||
break;
|
||||
case QXmppPresence::VCardUpdateValidPhoto: //there is a photo, need to load
|
||||
if (avatarHash != p_presence.photoHash()) {
|
||||
acc->vm->requestClientVCard();
|
||||
ownVCardRequestInProgress = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Core::VCardHandler::uploadVCard(const Shared::VCard& card)
|
||||
{
|
||||
QXmppVCardIq iq;
|
||||
initializeQXmppVCard(iq, card);
|
||||
|
||||
if (card.getAvatarType() != Shared::Avatar::empty) {
|
||||
QString newPath = card.getAvatarPath();
|
||||
QString oldPath = getAvatarPath();
|
||||
QByteArray data;
|
||||
QString type;
|
||||
if (newPath != oldPath) {
|
||||
QFile avatar(newPath);
|
||||
if (!avatar.open(QFile::ReadOnly)) {
|
||||
qDebug() << "An attempt to upload new vCard to account" << acc->name
|
||||
<< "but it wasn't possible to read file" << newPath
|
||||
<< "which was supposed to be new avatar, uploading old avatar";
|
||||
if (avatarType.size() > 0) {
|
||||
QFile oA(oldPath);
|
||||
if (!oA.open(QFile::ReadOnly)) {
|
||||
qDebug() << "Couldn't read old avatar of account" << acc->name << ", uploading empty avatar";
|
||||
} else {
|
||||
data = oA.readAll();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
data = avatar.readAll();
|
||||
}
|
||||
} else {
|
||||
if (avatarType.size() > 0) {
|
||||
QFile oA(oldPath);
|
||||
if (!oA.open(QFile::ReadOnly)) {
|
||||
qDebug() << "Couldn't read old avatar of account" << acc->name << ", uploading empty avatar";
|
||||
} else {
|
||||
data = oA.readAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (data.size() > 0) {
|
||||
QMimeDatabase db;
|
||||
type = db.mimeTypeForData(data).name();
|
||||
iq.setPhoto(data);
|
||||
iq.setPhotoType(type);
|
||||
}
|
||||
}
|
||||
|
||||
acc->vm->setClientVCard(iq);
|
||||
onOwnVCardReceived(iq);
|
||||
}
|
||||
|
||||
QString Core::VCardHandler::getAvatarPath() const
|
||||
{
|
||||
if (avatarType.size() == 0) {
|
||||
return "";
|
||||
} else {
|
||||
return QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/" + acc->name + "/" + "avatar." + avatarType;
|
||||
}
|
||||
}
|
65
core/handlers/vcardhandler.h
Normal file
65
core/handlers/vcardhandler.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
// Squawk messenger.
|
||||
// Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef CORE_VCARDHANDLER_H
|
||||
#define CORE_VCARDHANDLER_H
|
||||
|
||||
#include <set>
|
||||
|
||||
#include <QXmppVCardIq.h>
|
||||
#include <QXmppPresence.h>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <shared/vcard.h>
|
||||
#include <core/adapterfunctions.h>
|
||||
|
||||
/**
|
||||
* @todo write docs
|
||||
*/
|
||||
|
||||
namespace Core {
|
||||
|
||||
class Account;
|
||||
|
||||
class VCardHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
VCardHandler(Account* account);
|
||||
~VCardHandler();
|
||||
|
||||
void handleOffline();
|
||||
void requestVCard(const QString& jid);
|
||||
void handleOtherPresenceOfMyAccountChange(const QXmppPresence& p_presence);
|
||||
void uploadVCard(const Shared::VCard& card);
|
||||
QString getAvatarPath() const;
|
||||
|
||||
private slots:
|
||||
void onVCardReceived(const QXmppVCardIq& card);
|
||||
void onOwnVCardReceived(const QXmppVCardIq& card);
|
||||
|
||||
private:
|
||||
Account* acc;
|
||||
|
||||
bool ownVCardRequestInProgress;
|
||||
std::set<QString> pendingVCardRequests;
|
||||
QString avatarHash;
|
||||
QString avatarType;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // CORE_VCARDHANDLER_H
|
Loading…
Add table
Add a link
Reference in a new issue