From e5f9cdd6090ae8ede23d7e95977fb31a54ab95cb Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sun, 6 Oct 2024 15:48:33 +0300 Subject: fixes #4713 (Add support for XEP-0059: Result Set Management) --- protocols/JabberG/src/jabber_caps.h | 1 + protocols/JabberG/src/jabber_disco.cpp | 37 +++++++++++++++++++++++++++++++--- protocols/JabberG/src/jabber_disco.h | 33 ++++++++++-------------------- protocols/JabberG/src/jabber_mam.cpp | 6 +++--- 4 files changed, 49 insertions(+), 28 deletions(-) (limited to 'protocols') diff --git a/protocols/JabberG/src/jabber_caps.h b/protocols/JabberG/src/jabber_caps.h index ea270e4e88..eaea80b919 100644 --- a/protocols/JabberG/src/jabber_caps.h +++ b/protocols/JabberG/src/jabber_caps.h @@ -208,6 +208,7 @@ typedef unsigned __int64 JabberCapsBits; #define JABBER_FEAT_UPLOAD0 "urn:xmpp:http:upload:0" #define JABBER_FEAT_CHANNEL_BINDING "urn:xmpp:sasl-cb:0" +#define JABBER_FEAT_RSM "http://jabber.org/protocol/rsm" #define JABBER_FEAT_PUBSUB_EVENT "http://jabber.org/protocol/pubsub#event" #define JABBER_FEAT_PUBSUB_NODE_CONFIG "http://jabber.org/protocol/pubsub#node_config" diff --git a/protocols/JabberG/src/jabber_disco.cpp b/protocols/JabberG/src/jabber_disco.cpp index 709ca45e72..e427ad3ace 100644 --- a/protocols/JabberG/src/jabber_disco.cpp +++ b/protocols/JabberG/src/jabber_disco.cpp @@ -149,11 +149,38 @@ void CJabberProto::OnIqResultServiceDiscoveryItems(const TiXmlElement *iqNode, C if (query == nullptr) pNode->SetItemsRequestId(JABBER_DISCO_RESULT_ERROR); else { - for (auto *item : TiXmlEnum(query)) + int iRows = 0; + for (auto *item : TiXmlFilter(query, "item")) { + iRows++; pNode->AddChildNode(XmlGetAttr(item, "jid"), XmlGetAttr(item, "node"), XmlGetAttr(item, "name")); + } + + if (auto *pSet = XmlGetChildByTag(query, "set", "xmlns", JABBER_FEAT_RSM)) { + if (iRows == 0) { + pNode->SetItemsRequestId(JABBER_DISCO_RESULT_OK); + pNode->SetItemsRequestErrorText(nullptr); + } + else if (auto *pszLast = XmlGetChildText(pSet, "last")) { + auto *pNew = AddIQ(&CJabberProto::OnIqResultServiceDiscoveryItems, JABBER_IQ_TYPE_GET, pNode->GetJid()); + pNew->SetTimeout(60000); + pNode->SetItemsRequestId(pNew->GetIqId()); + + XmlNodeIq iq(pNew); + auto *pQuery = iq << XQUERY(JABBER_FEAT_DISCO_ITEMS); + if (pNode->GetNode()) + pQuery->SetAttribute("node", pNode->GetNode()); + + auto *pNextSet = pQuery << XCHILDNS("set", JABBER_FEAT_RSM); + pNextSet << XCHILD("max", "100"); + pNextSet << XCHILD("after", pszLast); - pNode->SetItemsRequestId(JABBER_DISCO_RESULT_OK); - pNode->SetItemsRequestErrorText(nullptr); + m_ThreadInfo->send(iq); + } + } + else { + pNode->SetItemsRequestId(JABBER_DISCO_RESULT_OK); + pNode->SetItemsRequestErrorText(nullptr); + } } } else { @@ -280,6 +307,10 @@ bool CJabberProto::SendBothRequests(CJabberSDNode *pNode, TiXmlNode *parent) if (pNode->GetNode()) query->SetAttribute("node", pNode->GetNode()); + auto *pNextSet = query << XCHILDNS("set", JABBER_FEAT_RSM); + pNextSet << XCHILD("max", "100"); + pNextSet << XCHILD("after", " "); + if (parent) parent->InsertEndChild(iq.node()->DeepClone(parent->GetDocument())); else diff --git a/protocols/JabberG/src/jabber_disco.h b/protocols/JabberG/src/jabber_disco.h index 70e0fbeea9..9f1132bbf0 100644 --- a/protocols/JabberG/src/jabber_disco.h +++ b/protocols/JabberG/src/jabber_disco.h @@ -121,17 +121,17 @@ protected: char *m_szJid; char *m_szNode; char *m_szName; - CJabberSDIdentity *m_pIdentities; - CJabberSDFeature *m_pFeatures; - CJabberSDNode *m_pNext; - CJabberSDNode *m_pChild; - uint32_t m_dwInfoRequestTime; - uint32_t m_dwItemsRequestTime; - int m_nInfoRequestId; - int m_nItemsRequestId; - HTREELISTITEM m_hTreeItem; - wchar_t *m_szInfoError; - wchar_t *m_szItemsError; + CJabberSDIdentity *m_pIdentities = nullptr; + CJabberSDFeature *m_pFeatures = nullptr; + CJabberSDNode *m_pNext = nullptr; + CJabberSDNode *m_pChild = nullptr; + uint32_t m_dwInfoRequestTime = 0; + uint32_t m_dwItemsRequestTime = 0; + int m_nInfoRequestId = 0; + int m_nItemsRequestId = 0; + HTREELISTITEM m_hTreeItem = 0; + wchar_t *m_szInfoError = 0; + wchar_t *m_szItemsError = 0; public: CJabberSDNode(const char *szJid = nullptr, const char *szNode = nullptr, const char *szName = nullptr) @@ -139,17 +139,6 @@ public: m_szJid = mir_strdup(szJid); m_szNode = mir_strdup(szNode); m_szName = mir_strdup(szName); - m_pIdentities = nullptr; - m_pFeatures = nullptr; - m_pNext = nullptr; - m_pChild = nullptr; - m_dwInfoRequestTime = 0; - m_dwItemsRequestTime = 0; - m_nInfoRequestId = 0; - m_nItemsRequestId = 0; - m_hTreeItem = nullptr; - m_szInfoError = nullptr; - m_szItemsError = nullptr; } ~CJabberSDNode() { diff --git a/protocols/JabberG/src/jabber_mam.cpp b/protocols/JabberG/src/jabber_mam.cpp index 19f81a66c9..dd31bf93ff 100644 --- a/protocols/JabberG/src/jabber_mam.cpp +++ b/protocols/JabberG/src/jabber_mam.cpp @@ -88,7 +88,7 @@ void CJabberProto::MamRetrieveMissingMessages() form << XCHILD("field") << XATTR("var", "end") << XCHILD("value", buf); } else { - auto *set = query << XCHILDNS("set", "http://jabber.org/protocol/rsm"); + auto *set = query << XCHILDNS("set", JABBER_FEAT_RSM); set << XCHILD("max", "1000"); set << XCHILD("after", szLastId); } @@ -112,7 +112,7 @@ void CJabberProto::MamSendForm(const char *pszWith, const char *pszAfter) if (pszWith != nullptr) form << XCHILD("field") << XATTR("var", "with") << XCHILD("value", pszWith); - auto *rsm = query << XCHILDNS("set", "http://jabber.org/protocol/rsm"); + auto *rsm = query << XCHILDNS("set", JABBER_FEAT_RSM); rsm << XCHILD("max", "1000"); if (pszAfter != nullptr) rsm << XCHILD("after", pszAfter); @@ -130,7 +130,7 @@ void CJabberProto::OnIqResultRsm(const TiXmlElement *iqNode, CJabberIqInfo *pInf if (!mir_strcmp(XmlGetAttr(fin, "complete"), "true")) return; - if (auto *set = XmlGetChildByTag(fin, "set", "xmlns", "http://jabber.org/protocol/rsm")) + if (auto *set = XmlGetChildByTag(fin, "set", "xmlns", JABBER_FEAT_RSM)) if (auto *lastId = XmlGetChildText(set, "last")) MamSendForm(ptrA(getUStringA(pInfo->GetHContact(), "jid")), lastId); } -- cgit v1.2.3