summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2020-08-28 20:16:04 +0300
committerGeorge Hazan <ghazan@miranda.im>2020-08-28 20:16:04 +0300
commit7650b1b0aa057df686e7d44bae58eaeba03b9b93 (patch)
treed233c6393d8831002729beaa0432ff9e4099dac1
parent8fa3e54ad4fd6d3f3055273a2f400a3360ab82ea (diff)
Jabber: MAM adaptation for OpenFire
-rw-r--r--protocols/JabberG/src/jabber_mam.cpp30
-rwxr-xr-xprotocols/JabberG/src/jabber_proto.h1
-rwxr-xr-xprotocols/JabberG/src/jabber_thread.cpp61
3 files changed, 59 insertions, 33 deletions
diff --git a/protocols/JabberG/src/jabber_mam.cpp b/protocols/JabberG/src/jabber_mam.cpp
index f369dcb0c4..4fb0359e93 100644
--- a/protocols/JabberG/src/jabber_mam.cpp
+++ b/protocols/JabberG/src/jabber_mam.cpp
@@ -69,13 +69,26 @@ void CJabberProto::MamSetMode(int iNewMode)
void CJabberProto::MamRetrieveMissingMessages()
{
CMStringA szLastId = getMStringA("LastMamId");
- if (szLastId.IsEmpty())
- return;
XmlNodeIq iq("set", SerialNext());
- auto *set = iq << XCHILDNS("query", JABBER_FEAT_MAM) << XCHILDNS("set", "http://jabber.org/protocol/rsm");
- set << XCHILD("max", "100");
- set << XCHILD("after", szLastId);
+ auto *query = iq << XCHILDNS("query", JABBER_FEAT_MAM);
+
+ if (szLastId.IsEmpty()) {
+ m_bMamDisableMessages = true; // our goal is to save message id, not to store messages
+
+ char buf[100];
+ time2str(time(0), buf, _countof(buf));
+
+ auto *form = query << XCHILDNS("x", JABBER_FEAT_DATA_FORMS) << XATTR("type", "submit");
+ form << XCHILD("field") << XATTR("var", "FORM_TYPE") << XATTR("type", "hidden") << XCHILD("value", JABBER_FEAT_MAM);
+ form << XCHILD("field") << XATTR("var", "end") << XCHILD("value", buf);
+ }
+ else {
+ auto *set = query << XCHILDNS("set", "http://jabber.org/protocol/rsm");
+ set << XCHILD("max", "1000");
+ set << XCHILD("after", szLastId);
+ }
+
m_ThreadInfo->send(iq);
}
@@ -84,6 +97,9 @@ void CJabberProto::MamRetrieveMissingMessages()
void CJabberProto::OnIqResultRsm(const TiXmlElement *iqNode, CJabberIqInfo *pInfo)
{
+ // even if that flag was enabled, unset it
+ m_bMamDisableMessages = false;
+
if (auto *fin = XmlGetChildByTag(iqNode, "fin", "xmlns", JABBER_FEAT_MAM)) {
// if dataset is complete, there's nothing more to do
if (!mir_strcmp(XmlGetAttr(fin, "complete"), "true"))
@@ -98,7 +114,7 @@ void CJabberProto::OnIqResultRsm(const TiXmlElement *iqNode, CJabberIqInfo *pInf
XmlNodeIq iq(pReq);
auto *query = iq << XCHILDNS("query", JABBER_FEAT_MAM);
- auto *x = query << XCHILDNS("x", "jabber:x:data") << XATTR("type", "submit");
+ auto *x = query << XCHILDNS("x", JABBER_FEAT_DATA_FORMS) << XATTR("type", "submit");
x << XCHILD("var", "FORM_TYPE") << XATTR("type", "hidden") << XCHILD("value", JABBER_FEAT_MAM);
x << XCHILD("var", "with") << XCHILD("value", jid);
auto *rsm = query << XCHILDNS("set", "http://jabber.org/protocol/rsm");
@@ -128,7 +144,7 @@ INT_PTR __cdecl CJabberProto::OnMenuLoadHistory(WPARAM hContact, LPARAM)
XmlNodeIq iq(pReq);
auto *query = iq << XCHILDNS("query", JABBER_FEAT_MAM);
- auto *x = query << XCHILDNS("x", "jabber:x:data") << XATTR("type", "submit");
+ auto *x = query << XCHILDNS("x", JABBER_FEAT_DATA_FORMS) << XATTR("type", "submit");
x << XCHILD("var", "FORM_TYPE") << XATTR("type", "hidden") << XCHILD("value", JABBER_FEAT_MAM);
x << XCHILD("var", "with") << XCHILD("value", jid);
query << XCHILDNS("set", "http://jabber.org/protocol/rsm") << XCHILD("max", "100");
diff --git a/protocols/JabberG/src/jabber_proto.h b/protocols/JabberG/src/jabber_proto.h
index c09b07ce34..64e17bb539 100755
--- a/protocols/JabberG/src/jabber_proto.h
+++ b/protocols/JabberG/src/jabber_proto.h
@@ -251,6 +251,7 @@ struct CJabberProto : public PROTO<CJabberProto>, public IJabberInterface
bool m_bPepSupported;
bool m_bStreamSent;
bool m_bMamPrefsAvailable;
+ bool m_bMamDisableMessages;
HWND m_hwndJabberChangePassword;
HWND m_hwndPrivacyRule;
diff --git a/protocols/JabberG/src/jabber_thread.cpp b/protocols/JabberG/src/jabber_thread.cpp
index f295adbfc7..a9b3a6c78d 100755
--- a/protocols/JabberG/src/jabber_thread.cpp
+++ b/protocols/JabberG/src/jabber_thread.cpp
@@ -1005,18 +1005,49 @@ void CJabberProto::OnProcessMessage(const TiXmlElement *node, ThreadData *info)
if (!node->Name() || mir_strcmp(node->Name(), "message"))
return;
- const char *from, *type = XmlGetAttr(node, "type");
- if ((from = XmlGetAttr(node, "from")) == nullptr) {
+ bool bEnableDelivery = true;
+ time_t msgTime = 0;
+ auto *from = XmlGetAttr(node, "from"), *type = XmlGetAttr(node, "type"), *idStr = XmlGetAttr(node, "id");
+ const char *szMsgId = nullptr; // MAM support
+
+ // check for MAM response
+ if (auto *mamResult = XmlGetChildByTag(node, "result", "xmlns", JABBER_FEAT_MAM)) {
+ szMsgId = XmlGetAttr(mamResult, "id");
+ if (szMsgId)
+ setString("LastMamId", szMsgId);
+
+ // we only collect ids, no need to store messages
+ if (m_bMamDisableMessages)
+ return;
+
+ auto *xmlForwarded = XmlGetChildByTag(mamResult, "forwarded", "xmlns", JABBER_XMLNS_FORWARD);
+ if (auto *xmlMessage = XmlFirstChild(xmlForwarded, "message")) {
+ node = xmlMessage;
+ type = XmlGetAttr(node, "type");
+ from = XmlGetAttr(node, "from");
+ if (!mir_strcmpi(from, info->fullJID)) {
+ debugLogA("MAM: outgoing message from this machine (%s), ignored", from);
+ return;
+ }
+ }
+
+ if (auto *xmlDelay = XmlGetChildByTag(xmlForwarded, "delay", "xmlns", JABBER_FEAT_DELAY))
+ if (auto *ptszTimeStamp = XmlGetAttr(xmlDelay, "stamp"))
+ msgTime = JabberIsoToUnixTime(ptszTimeStamp);
+
+ bEnableDelivery = false;
+ }
+
+ if (from == nullptr) {
debugLogA("no 'from' attribute, returning");
return;
}
- const char *idStr = XmlGetAttr(node, "id");
pResourceStatus pFromResource(ResourceInfoFromJID(from));
// Message receipts delivery request. Reply here, before a call to HandleMessagePermanent() to make sure message receipts are handled for external plugins too.
bool bSendMark = false;
- if ((!type || mir_strcmpi(type, "error"))) {
+ if (bEnableDelivery && (!type || mir_strcmpi(type, "error"))) {
bool bSendReceipt = XmlGetChildByTag(node, "request", "xmlns", JABBER_FEAT_MESSAGE_RECEIPTS) != 0;
bSendMark = XmlGetChildByTag(node, "markable", "xmlns", JABBER_FEAT_CHAT_MARKERS) != 0;
if (bSendReceipt || bSendMark) {
@@ -1040,8 +1071,6 @@ void CJabberProto::OnProcessMessage(const TiXmlElement *node, ThreadData *info)
return;
}
- time_t msgTime = 0;
-
// Handle carbons. The message MUST be coming from our bare JID.
const TiXmlElement *carbon = nullptr;
bool carbonSent = false; //2 cases: received or sent.
@@ -1087,24 +1116,6 @@ void CJabberProto::OnProcessMessage(const TiXmlElement *node, ThreadData *info)
}
}
}
- else { // check for MAM response
- if (auto *mamResult = XmlGetChildByTag(node, "result", "xmlns", JABBER_FEAT_MAM)) {
- auto *xmlForwarded = XmlGetChildByTag(mamResult, "forwarded", "xmlns", JABBER_XMLNS_FORWARD);
- if (auto *xmlMessage = XmlFirstChild(xmlForwarded, "message")) {
- node = xmlMessage;
- type = XmlGetAttr(node, "type");
- from = XmlGetAttr(node, "from");
- if (!mir_strcmpi(from, info->fullJID)) {
- debugLogA("MAM: outgoing message from this machine (%s), ignored", from);
- return;
- }
- }
- if (auto *xmlDelay = XmlGetChildByTag(xmlForwarded, "delay", "xmlns", JABBER_FEAT_DELAY)) {
- if (auto *ptszTimeStamp = XmlGetAttr(xmlDelay, "stamp"))
- msgTime = JabberIsoToUnixTime(ptszTimeStamp);
- }
- }
- }
}
MCONTACT hContact = HContactFromJID(from);
@@ -1146,8 +1157,6 @@ void CJabberProto::OnProcessMessage(const TiXmlElement *node, ThreadData *info)
if (bodyNode != nullptr)
szMessage.Append(bodyNode->GetText());
- // check MAM support
- const char *szMsgId = nullptr;
if (auto *n = XmlGetChildByTag(node, "stanza-id", "xmlns", JABBER_FEAT_SID))
if (szMsgId = n->Attribute("id"))
setString("LastMamId", szMsgId);