Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mam in progress #59

Merged
merged 20 commits into from
Sep 29, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/iris/xmpp_carbons.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "../../src/xmpp/xmpp-im/xmpp_carbons.h"
4 changes: 4 additions & 0 deletions src/xmpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@ set(HEADERS
xmpp-im/xmpp_thumbs.h
xmpp-im/xmpp_agentitem.h
xmpp-im/xmpp_captcha.h
xmpp-im/xmpp_carbons.h
xmpp-im/xmpp_chatstate.h
xmpp-im/xmpp_discoitem.h
xmpp-im/xmpp_features.h
xmpp-im/xmpp_forwarding.h
xmpp-im/xmpp_htmlelement.h
xmpp-im/xmpp_httpauthrequest.h
xmpp-im/xmpp_liveroster.h
Expand Down Expand Up @@ -113,9 +115,11 @@ set(SOURCES
xmpp-im/xmpp_bitsofbinary.cpp
xmpp-im/xmpp_bytestream.cpp
xmpp-im/xmpp_caps.cpp
xmpp-im/xmpp_carbons.cpp
xmpp-im/xmpp_discoinfotask.cpp
xmpp-im/xmpp_discoitem.cpp
xmpp-im/xmpp_ibb.cpp
xmpp-im/xmpp_forwarding.cpp
xmpp-im/xmpp_serverinfomanager.cpp
xmpp-im/xmpp_subsets.cpp
xmpp-im/xmpp_task.cpp
Expand Down
18 changes: 16 additions & 2 deletions src/xmpp/xmpp-im/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
#include "xmpp_bitsofbinary.h"
#include "filetransfer.h"
#include "xmpp_caps.h"
#include "xmpp_carbons.h"
#include "xmpp_hash.h"
#include "xmpp_serverinfomanager.h"
#include "protocol.h"
Expand Down Expand Up @@ -132,6 +133,7 @@ class Client::ClientPrivate
LiveRoster roster;
ResourceList resourceList;
CapsManager *capsman = nullptr;
CarbonsManager *carbonsman = nullptr;
S5BManager *s5bman = nullptr;
Jingle::S5B::Manager *jingleS5BManager = nullptr;
IBBManager *ibbman = nullptr;
Expand All @@ -142,6 +144,7 @@ class Client::ClientPrivate
Jingle::Manager *jingleManager = nullptr;
QList<GroupChat> groupChatList;
EncryptionHandler *encryptionHandler = nullptr;
JT_PushMessage *pushMessage = nullptr;
};


Expand Down Expand Up @@ -225,8 +228,9 @@ void Client::start(const QString &host, const QString &user, const QString &pass
connect(pp, SIGNAL(subscription(Jid,QString,QString)), SLOT(ppSubscription(Jid,QString,QString)));
connect(pp, SIGNAL(presence(Jid,Status)), SLOT(ppPresence(Jid,Status)));

JT_PushMessage *pm = new JT_PushMessage(rootTask(), d->encryptionHandler);
connect(pm, SIGNAL(message(Message)), SLOT(pmMessage(Message)));
d->pushMessage = new JT_PushMessage(rootTask(), d->encryptionHandler);
connect(d->pushMessage, SIGNAL(message(Message)), SLOT(pmMessage(Message)));
d->carbonsman = new CarbonsManager(d->pushMessage);

JT_PushRoster *pr = new JT_PushRoster(rootTask());
connect(pr, SIGNAL(roster(Roster)), SLOT(prRoster(Roster)));
Expand Down Expand Up @@ -286,6 +290,16 @@ ServerInfoManager *Client::serverInfoManager() const
return d->serverInfoManager;
}

CarbonsManager *Client::carbonsManager() const
{
return d->carbonsman;
}

JT_PushMessage *Client::pushMessage() const
{
return d->pushMessage;
}

HttpFileUploadManager *Client::httpFileUploadManager() const
{
return d->httpFileUploadManager;
Expand Down
64 changes: 46 additions & 18 deletions src/xmpp/xmpp-im/types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
#include "xmpp_bitsofbinary.h"
#include "xmpp_ibb.h"
#include "xmpp_captcha.h"
#include "xmpp_forwarding.h"
#include "xmpp_carbons.h"
#include "protocol.h"
#include "xmpp/blake2/blake2qt.h"
#define NS_XML "http://www.w3.org/XML/1998/namespace"
Expand Down Expand Up @@ -1056,7 +1058,6 @@ class Message::Private : public QSharedData
QMap<QString,HTMLElement> htmlElements;
QDomElement sxe;
QList<BoBData> bobDataList;
Jid forwardedFrom;

QList<int> mucStatuses;
QList<MUCInvite> mucInvites;
Expand All @@ -1067,12 +1068,12 @@ class Message::Private : public QSharedData
bool spooled = false, wasEncrypted = false;

//XEP-0280 Message Carbons
bool isDisabledCarbons = false;
Message::CarbonDir carbonDir = Message::NoCarbon; // it's a forwarded message
bool carbonsPrivate = false;
Message::ProcessingHints processingHints;
QString replaceId;
QString originId; // XEP-0359
Message::StanzaId stanzaId; // XEP-0359
Forwarding forwarding;
liuch marked this conversation as resolved.
Show resolved Hide resolved
};

#define MessageD() (d? d : (d = new Private))
Expand Down Expand Up @@ -1624,34 +1625,57 @@ IBBData Message::ibbData() const
return d? d->ibbData: IBBData();
}

void Message::setDisabledCarbons(bool disabled)
Jid Message::displayJid() const
liuch marked this conversation as resolved.
Show resolved Hide resolved
{
MessageD()->isDisabledCarbons = disabled;
if (!d)
return Jid();

switch (d->forwarding.type()) {
case Forwarding::ForwardedCarbonsSent:
return d->forwarding.message()->to();
case Forwarding::ForwardedCarbonsReceived:
return d->forwarding.message()->from();
default:
break;
}
return from();
}

const Message &Message::displayMessage() const
{
if (d && d->forwarding.isCarbons() && d->forwarding.message())
liuch marked this conversation as resolved.
Show resolved Hide resolved
return *d->forwarding.message();

return *this;
}

bool Message::isDisabledCarbons() const
Message &Message::displayMessage()
{
return d && d->isDisabledCarbons;
if (d && d->forwarding.isCarbons() && d->forwarding.message())
liuch marked this conversation as resolved.
Show resolved Hide resolved
return *d->forwarding.message();

return *this;
}

void Message::setCarbonDirection(Message::CarbonDir cd)
void Message::setCarbonsPrivate(bool enable)
{
MessageD()->carbonDir = cd;
MessageD()->carbonsPrivate = enable;
}

Message::CarbonDir Message::carbonDirection() const
bool Message::carbonsPrivate() const
{
return d? d->carbonDir: NoCarbon;
return (d && d->carbonsPrivate);
}

void Message::setForwardedFrom(const Jid &jid)
void Message::setForwarded(const Forwarding &frw)
{
MessageD()->forwardedFrom = jid;
MessageD()->forwarding = frw;
}

Jid Message::forwardedFrom() const
const Forwarding &Message::forwarded() const
{
return d? d->forwardedFrom: Jid();
static Forwarding f;
liuch marked this conversation as resolved.
Show resolved Hide resolved
return d ? d->forwarding : f;
}

bool Message::spooled() const
Expand Down Expand Up @@ -1922,10 +1946,10 @@ Stanza Message::toStanza(Stream *stream) const
}

// Avoiding Carbons
if (isDisabledCarbons() || wasEncrypted()) {
QDomElement e = s.createElement("urn:xmpp:carbons:2","private");
s.appendChild(e);
if (d->carbonsPrivate || d->wasEncrypted) {
s.appendChild(CarbonsManager::privateElement(stream->doc()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to xep 280, a private stanza also need a <no-copy/> node.

}

if (!d->replaceId.isEmpty()) {
QDomElement e = s.createElement("urn:xmpp:message-correct:0", "replace");
e.setAttribute("id", d->replaceId);
Expand Down Expand Up @@ -1962,6 +1986,10 @@ Stanza Message::toStanza(Stream *stream) const
s.appendChild(e);
}

// XEP-0297: Stanza Forwarding
if (d->forwarding.type() != Forwarding::ForwardedNone)
s.appendChild(d->forwarding.toXml(stream));

return s;
}

Expand Down
190 changes: 190 additions & 0 deletions src/xmpp/xmpp-im/xmpp_carbons.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
/*
* xmpp_carbons.cpp - Message Carbons (XEP-0280)
* Copyright (C) 2019 Aleksey Andreev
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/

#include <QDomElement>

#include "xmpp_carbons.h"
#include "xmpp_xmlcommon.h"
#include "xmpp_message.h"
#include "xmpp_forwarding.h"

namespace XMPP
{

static const QString xmlns_carbons(QStringLiteral("urn:xmpp:carbons:2"));

//----------------------------------------------------------------------------
// JT_MessageCarbons
//----------------------------------------------------------------------------
JT_MessageCarbons::JT_MessageCarbons(Task *parent)
: Task(parent)
{
}

void JT_MessageCarbons::enable()
{
iq = createIQ(doc(), QLatin1String("set"), QString(), id());
QDomElement enable = doc()->createElement(QLatin1String("enable"));
enable.setAttribute(QLatin1String("xmlns"), xmlns_carbons);
iq.appendChild(enable);
}

void JT_MessageCarbons::disable()
{
iq = createIQ(doc(), QLatin1String("set"), QString(), id());
QDomElement disable = doc()->createElement(QLatin1String("disable"));
disable.setAttribute(QLatin1String("xmlns"), xmlns_carbons);
iq.appendChild(disable);
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is clearly rooms to create an helper taking a bool enabled parameter to change the enable/disable element name.

void JT_MessageCarbons::onGo()
{
if (!iq.isNull())
send(iq);
}

bool JT_MessageCarbons::take(const QDomElement &e)
{
if (iqVerify(e, Jid(), id())) {
if (e.attribute(QLatin1String("type")) != QLatin1String("result"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no QLatin1String variant for QDN::attribute() so it's waonas you domore allocations.
Use QString::fromLatin1("...")

setError(e);
else
setSuccess();
return true;
}
return false;
}

//--------------------------------------------------
// class CarbonsSubscriber
//--------------------------------------------------

bool CarbonsSubscriber::xmlEvent(const QDomElement &root, QDomElement &e, Client *client, int userData, bool nested)
{
Q_UNUSED(root);
liuch marked this conversation as resolved.
Show resolved Hide resolved
bool drop = false;
frw.setType(Forwarding::ForwardedNone);
if (!nested) {
Jid from(root.attribute(QLatin1String("from")));
Jid to(root.attribute(QLatin1String("to")));
if (from.resource().isEmpty() && from.compare(to, false)) {
QDomElement child = e.firstChildElement();
while (!child.isNull()) {
if (frw.fromXml(child, client)) {
frw.setType(static_cast<Forwarding::Type>(userData));
break;
}
child = child.nextSiblingElement();
}
}
else
drop = true;
e = QDomElement();
}
return drop;
}

bool CarbonsSubscriber::messageEvent(Message &msg, int userData, bool nested)
{
Q_UNUSED(userData)
if (!nested && frw.type() != Forwarding::ForwardedNone) {
msg.setForwarded(frw);
frw.setType(Forwarding::ForwardedNone);
}
return false;
}

//--------------------------------------------------
// class CarbonsManager
//--------------------------------------------------

class CarbonsManager::Private {
public:
void subscribe() {
push_m->subscribeXml(sbs.get(), QLatin1String("received"), xmlns_carbons, Forwarding::ForwardedCarbonsReceived);
push_m->subscribeXml(sbs.get(), QLatin1String("sent"), xmlns_carbons, Forwarding::ForwardedCarbonsSent);
push_m->subscribeMessage(sbs.get(), 0);
}

void unsubscribe() {
push_m->unsubscribeXml(sbs.get(), QLatin1String("received"), xmlns_carbons);
push_m->unsubscribeXml(sbs.get(), QLatin1String("sent"), xmlns_carbons);
push_m->unsubscribeMessage(sbs.get());
}

JT_PushMessage *push_m;
std::unique_ptr<CarbonsSubscriber> sbs;
bool enable = false;
};

CarbonsManager::CarbonsManager(JT_PushMessage *push_m)
: QObject(push_m)
, d(new Private)
{
d->push_m = push_m;
d->sbs.reset(new CarbonsSubscriber());
}

CarbonsManager::~CarbonsManager()
{
// if (d->sbs.get())
// d->unsubscribe();
}
liuch marked this conversation as resolved.
Show resolved Hide resolved

QDomElement CarbonsManager::privateElement(QDomDocument &doc)
{
return doc.createElementNS(xmlns_carbons, QLatin1String("private"));
}

void CarbonsManager::setEnabled(bool enable)
{
if (d->enable == enable)
return;

if (enable) {
d->subscribe();
JT_MessageCarbons *jt = new JT_MessageCarbons(d->push_m->client()->rootTask());
connect(jt, &JT_MessageCarbons::finished, this, [=]() {
if (jt->success())
d->enable = true;
else
d->unsubscribe();
emit finished();
}, Qt::QueuedConnection);
jt->enable();
jt->go(true);
}
else if (d->sbs.get()) {
JT_MessageCarbons *jt = new JT_MessageCarbons(d->push_m->client()->rootTask());
connect(jt, &JT_MessageCarbons::finished, this, [=]() {
d->enable = false;
d->unsubscribe();
emit finished();
}, Qt::QueuedConnection);
jt->disable();
jt->go(true);
}
liuch marked this conversation as resolved.
Show resolved Hide resolved
}

bool CarbonsManager::isEnabled() const {
return d->enable;
}

} //namespace XMPP
Loading