diff options
| author | George Hazan <ghazan@miranda.im> | 2020-09-04 19:23:29 +0300 | 
|---|---|---|
| committer | George Hazan <ghazan@miranda.im> | 2020-09-04 19:23:29 +0300 | 
| commit | 016a44540e5f937f2144cfea312e46b414c34420 (patch) | |
| tree | cbf2956aedf2fc1815becd9de1373edf5d662479 /protocols/JabberG/src | |
| parent | 916dd6f5013c2f1afbe3fa35f425d8e517266f90 (diff) | |
Jabber: MAM code rework & optimization
Diffstat (limited to 'protocols/JabberG/src')
| -rw-r--r-- | protocols/JabberG/src/jabber_mam.cpp | 66 | ||||
| -rwxr-xr-x | protocols/JabberG/src/jabber_proto.h | 3 | ||||
| -rwxr-xr-x | protocols/JabberG/src/jabber_thread.cpp | 31 | 
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;
  | 
