summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2024-10-06 15:48:33 +0300
committerGeorge Hazan <george.hazan@gmail.com>2024-10-06 15:48:33 +0300
commite5f9cdd6090ae8ede23d7e95977fb31a54ab95cb (patch)
tree8582e09e994e4d8477f2fd96e33dd2775366e68f
parent831e8eece6de0d6939e3ef593a83687a39df24d3 (diff)
fixes #4713 (Add support for XEP-0059: Result Set Management)
-rw-r--r--protocols/JabberG/src/jabber_caps.h1
-rw-r--r--protocols/JabberG/src/jabber_disco.cpp37
-rw-r--r--protocols/JabberG/src/jabber_disco.h33
-rw-r--r--protocols/JabberG/src/jabber_mam.cpp6
4 files changed, 49 insertions, 28 deletions
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);
}