summaryrefslogtreecommitdiff
path: root/protocols/JabberG/src/jabber_thread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/JabberG/src/jabber_thread.cpp')
-rw-r--r--protocols/JabberG/src/jabber_thread.cpp106
1 files changed, 65 insertions, 41 deletions
diff --git a/protocols/JabberG/src/jabber_thread.cpp b/protocols/JabberG/src/jabber_thread.cpp
index b43afa84c0..fa0bd377e7 100644
--- a/protocols/JabberG/src/jabber_thread.cpp
+++ b/protocols/JabberG/src/jabber_thread.cpp
@@ -5,7 +5,7 @@ Jabber Protocol Plugin for Miranda NG
Copyright (c) 2002-04 Santithorn Bunchua
Copyright (c) 2005-12 George Hazan
Copyright (c) 2007 Maxim Mluhov
-Copyright (C) 2012-24 Miranda NG team
+Copyright (C) 2012-25 Miranda NG team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -29,7 +29,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "jabber_list.h"
#include "jabber_iq.h"
-#include "jabber_secur.h"
#include "jabber_caps.h"
#include "jabber_privacy.h"
#include "jabber_rc.h"
@@ -639,6 +638,8 @@ void CJabberProto::PerformAuthentication(ThreadData *info)
if (m_hasSasl2) {
XmlNode node("authenticate");
+ for (auto &it : m_arSaslUpgrade)
+ node << XCHILD("upgrade", it->getName()) << XATTR("xmlns", "urn:xmpp:sasl:upgrade:0");
node << XATTR("xmlns", JABBER_FEAT_SASL2) << XATTR("mechanism", auth.getName()) << XCHILD("initial-response", auth.getInitialRequest());
info->send(node);
}
@@ -647,6 +648,18 @@ void CJabberProto::PerformAuthentication(ThreadData *info)
/////////////////////////////////////////////////////////////////////////////////////////
+void CJabberProto::OnProcessChannelBinding(const TiXmlElement *node)
+{
+ for (auto *it : TiXmlFilter(node, "channel-binding")) {
+ if (auto *pszType = it->Attribute("type")) {
+ if (!mir_strcmp(pszType, "tls-exporter"))
+ m_bTlsExporter = true;
+ else if (!mir_strcmp(pszType, "tls-server-end-point"))
+ m_bTlsServerEndpoint = true;
+ }
+ }
+}
+
void CJabberProto::OnProcessFeatures(const TiXmlElement *node, ThreadData *info)
{
info->jabberServerCaps = JABBER_RESOURCE_CAPS_NONE;
@@ -693,6 +706,7 @@ void CJabberProto::OnProcessFeatures(const TiXmlElement *node, ThreadData *info)
else if (!mir_strcmp(pszName, "authentication") && !mir_strcmp(xmlns, JABBER_FEAT_SASL2) && m_bEnableSasl2) {
m_hasSasl2 = areMechanismsDefined = true;
m_arAuthMechs.destroy();
+ m_arSaslUpgrade.destroy();
replaceStr(info->gssapiHostName, nullptr);
for (auto *c : TiXmlEnum(n)) {
@@ -703,10 +717,14 @@ void CJabberProto::OnProcessFeatures(const TiXmlElement *node, ThreadData *info)
if (auto *sm = XmlGetChildByTag(c, "sm", "xmlns", JABBER_FEAT_SM))
m_StrmMgmt.CheckStreamFeatures(sm);
- if (auto *bind = XmlGetChildByTag(c, "sm", "xmlns", "urn:xmpp:bind:0")) {
+ if (auto *bind = XmlGetChildByTag(c, "bind", "xmlns", "urn:xmpp:bind:0")) {
// dunno why we need to handle that
}
}
+ else if (!mir_strcmp(c->Name(), "upgrade") && c->Attribute("xmlns", "urn:xmpp:sasl:upgrade:0"))
+ OnProcessUpgrade(c, info);
+ else if (!mir_strcmp(pszName, "sasl-channel-binding") && c->Attribute("xmlns", JABBER_FEAT_CHANNEL_BINDING))
+ OnProcessChannelBinding(c);
}
}
else if (!mir_strcmp(pszName, "session"))
@@ -724,16 +742,8 @@ void CJabberProto::OnProcessFeatures(const TiXmlElement *node, ThreadData *info)
}
else info->jabberServerCaps |= pCaps->GetCaps();
}
- else if (!mir_strcmp(pszName, "sasl-channel-binding") && !mir_strcmp(xmlns, JABBER_FEAT_CHANNEL_BINDING)) {
- for (auto *it : TiXmlFilter(n, "channel-binding")) {
- if (auto *pszType = it->Attribute("type")) {
- if (!mir_strcmp(pszType, "tls-exporter"))
- m_bTlsExporter = true;
- else if (!mir_strcmp(pszType, "tls-server-end-point"))
- m_bTlsServerEndpoint = true;
- }
- }
- }
+ else if (!mir_strcmp(pszName, "sasl-channel-binding") && !mir_strcmp(xmlns, JABBER_FEAT_CHANNEL_BINDING))
+ OnProcessChannelBinding(n);
}
if (areMechanismsDefined) {
@@ -829,7 +839,10 @@ void CJabberProto::OnProcessSuccess(const TiXmlElement *node, ThreadData *info)
return;
}
- if (!pszFinal || !m_arAuthMechs[0].validateLogin(pszFinal)) {
+ if (m_hasSasl2 && !pszFinal && info->m_saslUpgrade)
+ pszFinal = info->m_saslUpgrade->getInitData();
+
+ if (!m_arAuthMechs[0].validateLogin(pszFinal)) {
info->send("</stream:stream>");
return;
}
@@ -867,40 +880,45 @@ void CJabberProto::OnProcessProtocol(const TiXmlElement *node, ThreadData *info)
if (m_StrmMgmt.HandleIncommingNode(node))
return;
- if (!mir_strcmp(node->Name(), "proceed"))
+ auto *pszName = node->Name();
+ if (!mir_strcmp(pszName, "proceed"))
OnProcessProceed(node, info);
- else if (!mir_strcmp(node->Name(), "compressed"))
+ else if (!mir_strcmp(pszName, "compressed"))
OnProcessCompressed(node, info);
- else if (!mir_strcmp(node->Name(), "stream:features"))
+ else if (!mir_strcmp(pszName, "stream:features"))
OnProcessFeatures(node, info);
- else if (!mir_strcmp(node->Name(), "stream:stream"))
+ else if (!mir_strcmp(pszName, "stream:stream"))
OnProcessStreamOpening(node, info);
- else if (!mir_strcmp(node->Name(), "success"))
+ else if (!mir_strcmp(pszName, "success"))
OnProcessSuccess(node, info);
- else if (!mir_strcmp(node->Name(), "failure"))
+ else if (!mir_strcmp(pszName, "failure"))
OnProcessFailure(node, info);
- else if (!mir_strcmp(node->Name(), "stream:error"))
+ else if (!mir_strcmp(pszName, "continue"))
+ OnProcessContinue(node, info);
+ else if (!mir_strcmp(pszName, "task-data"))
+ OnProcessTaskData(node, info);
+ else if (!mir_strcmp(pszName, "stream:error"))
OnProcessError(node, info);
- else if (!mir_strcmp(node->Name(), "challenge"))
+ else if (!mir_strcmp(pszName, "challenge"))
OnProcessChallenge(node, info);
else if (!info->bIsReg) {
- if (!mir_strcmp(node->Name(), "message"))
+ if (!mir_strcmp(pszName, "message"))
OnProcessMessage(node, info);
- else if (!mir_strcmp(node->Name(), "presence"))
+ else if (!mir_strcmp(pszName, "presence"))
OnProcessPresence(node, info);
- else if (!mir_strcmp(node->Name(), "iq"))
+ else if (!mir_strcmp(pszName, "iq"))
OnProcessIq(node);
- else if (!mir_strcmp(node->Name(), "failed"))
+ else if (!mir_strcmp(pszName, "failed"))
OnProcessFailed(node, info);
- else if (!mir_strcmp(node->Name(), "enabled"))
+ else if (!mir_strcmp(pszName, "enabled"))
OnProcessEnabled(node, info);
- else if (m_bEnableStreamMgmt && !mir_strcmp(node->Name(), "resumed"))
+ else if (m_bEnableStreamMgmt && !mir_strcmp(pszName, "resumed"))
m_StrmMgmt.OnProcessResumed(node, info);
else
debugLogA("Invalid top-level tag (only <message/> <presence/> and <iq/> allowed)");
}
else {
- if (!mir_strcmp(node->Name(), "iq"))
+ if (!mir_strcmp(pszName, "iq"))
OnProcessRegIq(node, info);
else
debugLogA("Invalid top-level tag (only <iq/> allowed)");
@@ -1003,7 +1021,7 @@ uint32_t JabberGetLastContactMessageTime(MCONTACT hContact)
return 0;
DB::EventInfo dbei(hDbEvent, false);
- return (dbei) ? dbei.timestamp : 0;
+ return (dbei) ? dbei.getUnixtime() : 0;
}
MCONTACT CJabberProto::CreateTemporaryContact(const char *szJid, JABBER_LIST_ITEM *chatItem)
@@ -1157,7 +1175,7 @@ void CJabberProto::XmppMsg::handle_chatstates()
_dbei.cbBlob = 1;
_dbei.eventType = EVENTTYPE_JABBER_CHATSTATES;
_dbei.flags = DBEF_READ;
- _dbei.timestamp = time(0);
+ _dbei.iTimestamp = time(0);
_dbei.szModule = m_proto->m_szModuleName;
db_event_add(hContact, &_dbei);
}
@@ -1349,12 +1367,10 @@ void CJabberProto::XmppMsg::process()
}
}
else if (!mir_strcmp(pszXmlns, JABBER_FEAT_OOB2)) {
- if (auto* url = XmlGetChildText(xNode, "url")) {
- m_proto->FileProcessHttpDownload(hContact, from, url, XmlGetChildText(xNode, "desc"));
- return;
- }
-
- m_proto->debugLogA("No URL in OOB file transfer, ignoring");
+ if (auto* url = XmlGetChildText(xNode, "url"))
+ m_proto->FileProcessHttpDownload(dbei, url, XmlGetChildText(xNode, "desc"));
+ else
+ m_proto->debugLogA("No URL in OOB file transfer, ignoring");
}
else if (!mir_strcmp(pszXmlns, JABBER_FEAT_MUC_USER)) {
auto* inviteNode = XmlFirstChild(xNode, "invite");
@@ -1402,7 +1418,7 @@ void CJabberProto::XmppMsg::process()
szMessage += m_proto->ExtractImage(node);
// all service info was already processed
- if (szMessage.IsEmpty()) {
+ if (dbei.eventType == EVENTTYPE_MESSAGE && szMessage.IsEmpty()) {
m_proto->debugLogA("empty message, returning");
return;
}
@@ -1445,11 +1461,19 @@ void CJabberProto::XmppMsg::add_to_db()
if (bWasSent)
dbei.flags |= DBEF_SENT;
- dbei.timestamp = (uint32_t)msgTime;
- dbei.pBlob = szMessage.GetBuffer();
+ dbei.iTimestamp = (uint32_t)msgTime;
dbei.szId = szMamMsgId;
- MEVENT hDbEVent = (MEVENT)ProtoChainRecvMsg(hContact, dbei);
+ MEVENT hDbEVent;
+ if (dbei.eventType == EVENTTYPE_FILE) {
+ dbei.flags |= DBEF_TEMPORARY;
+ hDbEVent = (MEVENT)ProtoChainRecvFile(hContact, DB::FILE_BLOB(dbei), dbei);
+ }
+ else {
+ dbei.pBlob = szMessage.GetBuffer();
+ hDbEVent = (MEVENT)ProtoChainRecvMsg(hContact, dbei);
+ }
+
if (idStr)
m_proto->m_arChatMarks.insert(new CChatMark(hDbEVent, idStr, from));