summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2020-09-04 19:23:29 +0300
committerGeorge Hazan <ghazan@miranda.im>2020-09-04 19:23:29 +0300
commit016a44540e5f937f2144cfea312e46b414c34420 (patch)
treecbf2956aedf2fc1815becd9de1373edf5d662479
parent916dd6f5013c2f1afbe3fa35f425d8e517266f90 (diff)
Jabber: MAM code rework & optimization
-rw-r--r--protocols/JabberG/src/jabber_mam.cpp66
-rwxr-xr-xprotocols/JabberG/src/jabber_proto.h3
-rwxr-xr-xprotocols/JabberG/src/jabber_thread.cpp31
3 files changed, 57 insertions, 43 deletions
diff --git a/protocols/JabberG/src/jabber_mam.cpp b/protocols/JabberG/src/jabber_mam.cpp
index dbdd1a67b3..9d5ba27b64 100644
--- a/protocols/JabberG/src/jabber_mam.cpp
+++ b/protocols/JabberG/src/jabber_mam.cpp
@@ -45,8 +45,8 @@ void CJabberProto::OnIqResultMamInfo(const TiXmlElement *iqNode, CJabberIqInfo *
}
// shall we retrieve missing messages?
- // if (pInfo->GetUserData())
- // MamRetrieveMissingMessages();
+ if (pInfo->GetUserData())
+ MamRetrieveMissingMessages();
}
void CJabberProto::MamSetMode(int iNewMode)
@@ -75,6 +75,7 @@ void CJabberProto::MamRetrieveMissingMessages()
if (szLastId.IsEmpty()) {
m_bMamDisableMessages = true; // our goal is to save message id, not to store messages
+ m_bMamCreateRead = false;
char buf[100];
time2str(time(0), buf, _countof(buf));
@@ -95,6 +96,27 @@ void CJabberProto::MamRetrieveMissingMessages()
/////////////////////////////////////////////////////////////////////////////////////////
// Contact's history loader
+void CJabberProto::MamSendForm(const char *pszWith, const char *pszAfter)
+{
+ auto *pReq = AddIQ(&CJabberProto::OnIqResultRsm, JABBER_IQ_TYPE_SET);
+ pReq->SetParamsToParse(JABBER_IQ_PARSE_FROM);
+
+ XmlNodeIq iq(pReq);
+ auto *query = iq << XCHILDNS("query", JABBER_FEAT_MAM);
+
+ 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);
+ if (pszWith != nullptr)
+ form << XCHILD("field") << XATTR("var", "with") << XCHILD("value", pszWith);
+
+ auto *rsm = query << XCHILDNS("set", "http://jabber.org/protocol/rsm");
+ rsm << XCHILD("max", "1000");
+ if (pszAfter != nullptr)
+ rsm << XCHILD("after", pszAfter);
+ m_ThreadInfo->send(iq);
+}
+
+
void CJabberProto::OnIqResultRsm(const TiXmlElement *iqNode, CJabberIqInfo *pInfo)
{
// even if that flag was enabled, unset it
@@ -105,23 +127,9 @@ void CJabberProto::OnIqResultRsm(const TiXmlElement *iqNode, CJabberIqInfo *pInf
if (!mir_strcmp(XmlGetAttr(fin, "complete"), "true"))
return;
- auto *lastId = XmlGetChildText(fin, "last");
- if (lastId) {
- ptrA jid(getUStringA(pInfo->GetHContact(), "jid"));
-
- auto *pReq = AddIQ(&CJabberProto::OnIqResultRsm, JABBER_IQ_TYPE_SET);
- pReq->SetParamsToParse(JABBER_IQ_PARSE_FROM);
-
- XmlNodeIq iq(pReq);
- auto *query = iq << XCHILDNS("query", JABBER_FEAT_MAM);
- 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", "with") << XCHILD("value", jid);
- auto *rsm = query << XCHILDNS("set", "http://jabber.org/protocol/rsm");
- rsm << XCHILD("max", "100");
- rsm << XCHILD("after", lastId);
- m_ThreadInfo->send(iq);
- }
+ if (auto *set = XmlGetChildByTag(fin, "set", "xmlns", "http://jabber.org/protocol/rsm"))
+ if (auto *lastId = XmlGetChildText(set, "last"))
+ MamSendForm(ptrA(getUStringA(pInfo->GetHContact(), "jid")), lastId);
}
}
@@ -131,24 +139,18 @@ INT_PTR __cdecl CJabberProto::OnMenuLoadHistory(WPARAM hContact, LPARAM)
return 0;
// wipe out old history first
- DB::ECPTR pCursor(DB::Events(hContact));
- while (pCursor.FetchNext())
- pCursor.DeleteEvent();
+ if (IDYES == MessageBoxW(NULL, TranslateT("Do you want to erase local history before loading it from server?"), m_tszUserName, MB_YESNOCANCEL | MB_ICONQUESTION)) {
+ DB::ECPTR pCursor(DB::Events(hContact));
+ while (pCursor.FetchNext())
+ pCursor.DeleteEvent();
+ }
// load remaining items from server
if (m_bJabberOnline) {
ptrA jid(getUStringA(hContact, "jid"));
if (jid != nullptr) {
- auto *pReq = AddIQ(&CJabberProto::OnIqResultRsm, JABBER_IQ_TYPE_SET);
- pReq->SetParamsToParse(JABBER_IQ_PARSE_FROM);
-
- XmlNodeIq iq(pReq);
- auto *query = iq << XCHILDNS("query", JABBER_FEAT_MAM);
- 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", "with") << XCHILD("value", jid);
- query << XCHILDNS("set", "http://jabber.org/protocol/rsm") << XCHILD("max", "100");
- m_ThreadInfo->send(iq);
+ m_bMamCreateRead = true;
+ MamSendForm(jid);
}
}
return 0;
diff --git a/protocols/JabberG/src/jabber_proto.h b/protocols/JabberG/src/jabber_proto.h
index 64e17bb539..9d78f99b63 100755
--- a/protocols/JabberG/src/jabber_proto.h
+++ b/protocols/JabberG/src/jabber_proto.h
@@ -251,7 +251,7 @@ struct CJabberProto : public PROTO<CJabberProto>, public IJabberInterface
bool m_bPepSupported;
bool m_bStreamSent;
bool m_bMamPrefsAvailable;
- bool m_bMamDisableMessages;
+ bool m_bMamDisableMessages, m_bMamCreateRead;
HWND m_hwndJabberChangePassword;
HWND m_hwndPrivacyRule;
@@ -644,6 +644,7 @@ struct CJabberProto : public PROTO<CJabberProto>, public IJabberInterface
void OnIqResultMamInfo(const TiXmlElement *iqNode, CJabberIqInfo *pInfo);
void OnIqResultRsm(const TiXmlElement *iqNode, CJabberIqInfo *pInfo);
+ void MamSendForm(const char *pszWith, const char *pszAfter = nullptr);
void MamRetrieveMissingMessages(void);
void MamSetMode(int iNewMode);
diff --git a/protocols/JabberG/src/jabber_thread.cpp b/protocols/JabberG/src/jabber_thread.cpp
index a9b3a6c78d..2f1b96a73a 100755
--- a/protocols/JabberG/src/jabber_thread.cpp
+++ b/protocols/JabberG/src/jabber_thread.cpp
@@ -1005,8 +1005,8 @@ void CJabberProto::OnProcessMessage(const TiXmlElement *node, ThreadData *info)
if (!node->Name() || mir_strcmp(node->Name(), "message"))
return;
- bool bEnableDelivery = true;
time_t msgTime = 0;
+ bool bEnableDelivery = true, bCreateRead = false, bWasSent = false;
auto *from = XmlGetAttr(node, "from"), *type = XmlGetAttr(node, "type"), *idStr = XmlGetAttr(node, "id");
const char *szMsgId = nullptr; // MAM support
@@ -1025,17 +1025,28 @@ void CJabberProto::OnProcessMessage(const TiXmlElement *node, ThreadData *info)
node = xmlMessage;
type = XmlGetAttr(node, "type");
from = XmlGetAttr(node, "from");
- if (!mir_strcmpi(from, info->fullJID)) {
+ auto *to = XmlGetAttr(node, "to");
+
+ char szJid[JABBER_MAX_JID_LEN];
+ JabberStripJid(from, szJid, _countof(szJid));
+ if (!mir_strcmpi(szJid, m_szJabberJID)) {
+ bWasSent = true;
+ std::swap(from, to);
+ }
+
+ // we disable message reading with our resource only for the missing messages
+ if (!m_bMamCreateRead && !mir_strcmpi(to, 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 *xmlDelay = XmlGetChildByTag(xmlForwarded, "delay", "xmlns", "urn:xmpp:delay"))
if (auto *ptszTimeStamp = XmlGetAttr(xmlDelay, "stamp"))
- msgTime = JabberIsoToUnixTime(ptszTimeStamp);
+ msgTime = str2time(ptszTimeStamp);
bEnableDelivery = false;
+ bCreateRead = m_bMamCreateRead;
}
if (from == nullptr) {
@@ -1073,12 +1084,11 @@ void CJabberProto::OnProcessMessage(const TiXmlElement *node, ThreadData *info)
// Handle carbons. The message MUST be coming from our bare JID.
const TiXmlElement *carbon = nullptr;
- bool carbonSent = false; //2 cases: received or sent.
if (IsMyOwnJID(from)) {
carbon = XmlGetChildByTag(node, "received", "xmlns", JABBER_FEAT_CARBONS);
if (!carbon) {
if (carbon = XmlGetChildByTag(node, "sent", "xmlns", JABBER_FEAT_CARBONS))
- carbonSent = true;
+ bWasSent = true;
}
if (carbon) {
// If carbons are disabled in options, we should ignore occasional carbons sent to us by server
@@ -1087,6 +1097,7 @@ void CJabberProto::OnProcessMessage(const TiXmlElement *node, ThreadData *info)
return;
}
+ bCreateRead = true;
auto *xmlForwarded = XmlGetChildByTag(carbon, "forwarded", "xmlns", JABBER_XMLNS_FORWARD);
auto *xmlMessage = XmlFirstChild(xmlForwarded, "message");
// Carbons MUST have forwarded/message content
@@ -1099,7 +1110,7 @@ void CJabberProto::OnProcessMessage(const TiXmlElement *node, ThreadData *info)
node = xmlMessage;
type = XmlGetAttr(node, "type");
- if (!carbonSent) {
+ if (!bWasSent) {
// Received should just be treated like incoming messages, except maybe not flash the flasher. Simply unwrap.
from = XmlGetAttr(node, "from");
if (from == nullptr) {
@@ -1278,7 +1289,7 @@ void CJabberProto::OnProcessMessage(const TiXmlElement *node, ThreadData *info)
return;
}
- if (carbon && carbonSent)
+ if (carbon && bWasSent)
szMessage = TranslateU("Unable to decrypt a carbon copy of the encrypted outgoing message");
else {
// XEP-0027 is not strict enough, different clients have different implementations
@@ -1387,9 +1398,9 @@ void CJabberProto::OnProcessMessage(const TiXmlElement *node, ThreadData *info)
msgTime = now;
PROTORECVEVENT recv = {};
- if (carbon) {
+ if (bCreateRead) {
recv.flags |= PREF_CREATEREAD;
- if (carbonSent)
+ if (bWasSent)
recv.flags |= PREF_SENT;
}
recv.timestamp = (DWORD)msgTime;