From 3fef3db56fa55e9b8952b6682d3b3c7bd4aa4c98 Mon Sep 17 00:00:00 2001
From: George Hazan <george.hazan@gmail.com>
Date: Thu, 24 Aug 2023 20:41:48 +0300
Subject: =?UTF-8?q?fixes=20#3661=20(tabSRMM:=20=D0=B2=D1=81=D0=BF=D0=BB?=
 =?UTF-8?q?=D1=8B=D0=B2=D0=B0=D1=8E=D1=89=D0=B8=D0=B5=20=D1=83=D0=B2=D0=B5?=
 =?UTF-8?q?=D0=B4=D0=BE=D0=BC=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BE=20?=
 =?UTF-8?q?=D0=BD=D0=B0=D0=B1=D0=BE=D1=80=D0=B5=20=D1=82=D0=B5=D0=BA=D1=81?=
 =?UTF-8?q?=D1=82=D0=B0=20=D0=BF=D1=80=D0=B8=20=D0=BF=D0=BE=D0=BB=D1=83?=
 =?UTF-8?q?=D1=87=D0=B5=D0=BD=D0=B8=D0=B8=20=D0=BE=D1=84=D1=84=D0=BB=D0=B0?=
 =?UTF-8?q?=D0=B9=D0=BD=D0=BE=D0=B2=D0=BE=D0=B3=D0=BE=20=D1=81=D0=BE=D0=BE?=
 =?UTF-8?q?=D0=B1=D1=89=D0=B5=D0=BD=D0=B8=D1=8F),=20also=20implements=20XE?=
 =?UTF-8?q?P-0160=20in=20Jabber?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 protocols/JabberG/src/jabber_caps.cpp      |  3 ++-
 protocols/JabberG/src/jabber_caps.h        |  3 +++
 protocols/JabberG/src/jabber_groupchat.cpp |  8 ++----
 protocols/JabberG/src/jabber_thread.cpp    | 19 +++++++-------
 protocols/JabberG/src/jabber_util.cpp      | 41 ++++++++++++++++--------------
 protocols/JabberG/src/stdafx.h             |  2 +-
 6 files changed, 39 insertions(+), 37 deletions(-)

(limited to 'protocols/JabberG')

diff --git a/protocols/JabberG/src/jabber_caps.cpp b/protocols/JabberG/src/jabber_caps.cpp
index 77a7ed9ac9..dea74127ce 100644
--- a/protocols/JabberG/src/jabber_caps.cpp
+++ b/protocols/JabberG/src/jabber_caps.cpp
@@ -77,7 +77,8 @@ const JabberFeatCapPair g_JabberFeatCapPairs[] =
 	{ JABBER_FEAT_ROSTER_EXCHANGE,         JABBER_CAPS_ROSTER_EXCHANGE,         LPGEN("Supports Roster Exchange") },
 	{ JABBER_FEAT_DIRECT_MUC_INVITE,       JABBER_CAPS_DIRECT_MUC_INVITE,       LPGEN("Supports direct chat invitations (XEP-0249)") },
 	{ JABBER_FEAT_OMEMO_DEVICELIST_NOTIFY, JABBER_CAPS_OMEMO_DEVICELIST_NOTIFY, LPGEN("Receives information about OMEMO devices") },
-	{ JABBER_FEAT_CARBONS,				   JABBER_CAPS_CARBONS,                 LPGEN("Supports message carbons (XEP-0280)")},
+	{ JABBER_FEAT_CARBONS,                 JABBER_CAPS_CARBONS,                 LPGEN("Supports message carbons (XEP-0280)") },
+	{ JABBER_FEAT_MSGOFFLINE,              JABBER_CAPS_MSGOFFLINE,              LPGEN("Supports offline messages (XEP-0160)") },
 };
 
 const int g_cJabberFeatCapPairs = _countof(g_JabberFeatCapPairs);
diff --git a/protocols/JabberG/src/jabber_caps.h b/protocols/JabberG/src/jabber_caps.h
index 66d0ecf2b8..8ed6a24996 100644
--- a/protocols/JabberG/src/jabber_caps.h
+++ b/protocols/JabberG/src/jabber_caps.h
@@ -192,6 +192,9 @@ typedef unsigned __int64 JabberCapsBits;
 #define JABBER_FEAT_BITS                        "urn:xmpp:bob"
 #define JABBER_CAPS_BITS                        ((JabberCapsBits)1<<50)
 
+#define JABBER_FEAT_MSGOFFLINE                  "msgoffline"
+#define JABBER_CAPS_MSGOFFLINE                  ((JabberCapsBits)1<<51)
+
 #define JABBER_FEAT_ARCHIVE                     "urn:xmpp:archive"
 #define JABBER_FEAT_BIND                        "urn:ietf:params:xml:ns:xmpp-bind"
 #define JABBER_FEAT_CAPTCHA                     "urn:xmpp:captcha"
diff --git a/protocols/JabberG/src/jabber_groupchat.cpp b/protocols/JabberG/src/jabber_groupchat.cpp
index 81f432bc0f..fe0af588c5 100644
--- a/protocols/JabberG/src/jabber_groupchat.cpp
+++ b/protocols/JabberG/src/jabber_groupchat.cpp
@@ -976,7 +976,7 @@ void CJabberProto::GroupchatProcessPresence(const TiXmlElement *node)
 void CJabberProto::GroupchatProcessMessage(const TiXmlElement *node)
 {
 	const TiXmlElement *n, *m;
-	const char *from, *type, *p, *nick;
+	const char *from, *type, *nick;
 	JABBER_LIST_ITEM *item;
 	CMStringW imgLink;
 
@@ -1046,11 +1046,7 @@ void CJabberProto::GroupchatProcessMessage(const TiXmlElement *node)
 	gce.si = GcInit(item);
 
 	time_t msgTime = 0;
-	if (!JabberReadXep203delay(node, msgTime)) {
-		auto *xDelay = XmlGetChildByTag(node, "x", "xmlns", "jabber:x:delay");
-		if (xDelay && (p = XmlGetAttr(xDelay, "stamp")) != nullptr)
-			msgTime = JabberIsoToUnixTime(p);
-	}
+	JabberProcessDelay(node, msgTime);
 
 	time_t now = time(0);
 	if (!msgTime || msgTime > now)
diff --git a/protocols/JabberG/src/jabber_thread.cpp b/protocols/JabberG/src/jabber_thread.cpp
index 4ab15f6805..ae99fb29d2 100644
--- a/protocols/JabberG/src/jabber_thread.cpp
+++ b/protocols/JabberG/src/jabber_thread.cpp
@@ -1056,9 +1056,7 @@ void CJabberProto::OnProcessMessage(const TiXmlElement *node, ThreadData *info)
 			}
 		}
 
-		if (auto *xmlDelay = XmlGetChildByTag(xmlForwarded, "delay", "xmlns", "urn:xmpp:delay"))
-			if (auto *ptszTimeStamp = XmlGetAttr(xmlDelay, "stamp"))
-				msgTime = str2time(ptszTimeStamp);
+		JabberProcessDelay(xmlForwarded, msgTime);
 
 		bEnableDelivery = false;
 		bCreateRead = m_bMamCreateRead;
@@ -1225,15 +1223,15 @@ void CJabberProto::OnProcessMessage(const TiXmlElement *node, ThreadData *info)
 
 	// Timestamp
 	time_t now = time(0);
+	bool bOffline = false;
 	if (!msgTime) {
-		if (!JabberReadXep203delay(node, msgTime)) {
-			msgTime = now;
-			if (auto *xNode = XmlGetChildByTag(node, "x", "xmlns", JABBER_FEAT_DELAY))
-				if (const char *ptszTimeStamp = XmlGetAttr(xNode, "stamp"))
-					if (time_t t = JabberIsoToUnixTime(ptszTimeStamp))
-						msgTime = t;
+		if (auto *n = JabberProcessDelay(node, msgTime)) {
+			if ((m_ThreadInfo->jabberServerCaps & JABBER_CAPS_MSGOFFLINE) && !mir_strcmp(n->GetText(), "Offline Storage"))
+				bOffline = true;
 		}
+		else msgTime = now;
 	}
+
 	if (m_bFixIncorrectTimestamps && (msgTime > now || (hContact && (msgTime < (time_t)JabberGetLastContactMessageTime(hContact)))))
 		msgTime = now;
 
@@ -1425,7 +1423,8 @@ void CJabberProto::OnProcessMessage(const TiXmlElement *node, ThreadData *info)
 	// Create a temporary contact, if needed
 	if (hContact == 0)
 		hContact = CreateTemporaryContact(from, chatItem);
-	CallService(MS_PROTO_CONTACTISTYPING, hContact, PROTOTYPE_CONTACTTYPING_OFF);
+	if (!bOffline)
+		CallService(MS_PROTO_CONTACTISTYPING, hContact, PROTOTYPE_CONTACTTYPING_OFF);
 
 	PROTORECVEVENT recv = {};
 	if (bCreateRead)
diff --git a/protocols/JabberG/src/jabber_util.cpp b/protocols/JabberG/src/jabber_util.cpp
index 165f00bcd3..f8190485ae 100644
--- a/protocols/JabberG/src/jabber_util.cpp
+++ b/protocols/JabberG/src/jabber_util.cpp
@@ -781,27 +781,30 @@ BOOL CJabberProto::EnterString(CMStringW &result, const wchar_t *caption, int ty
 /////////////////////////////////////////////////////////////////////////////////////////
 // XEP-0203 delay support
 
-bool JabberReadXep203delay(const TiXmlElement *node, time_t &msgTime)
-{
-	auto *n = XmlGetChildByTag(node, "delay", "xmlns", "urn:xmpp:delay");
-	if (n == nullptr)
-		return false;
+const TiXmlElement* JabberProcessDelay(const TiXmlElement *node, time_t &msgTime)
+{
+	if (auto *n = XmlGetChildByTag(node, "delay", "xmlns", "urn:xmpp:delay"))
+		if (auto *pszTimeStamp = XmlGetAttr(n, "stamp")) {
+			// skip '-' chars
+			char *szStamp = NEWSTR_ALLOCA(pszTimeStamp);
+			int si = 0, sj = 0;
+			while (true) {
+				if (szStamp[si] == '-')
+					si++;
+				else if (!(szStamp[sj++] = szStamp[si++]))
+					break;
+			};
+			msgTime = JabberIsoToUnixTime(szStamp);
+			return (msgTime != 0) ? n : nullptr;
+		}
 
-	const char *ptszTimeStamp = XmlGetAttr(n, "stamp");
-	if (ptszTimeStamp == nullptr)
-		return false;
+	if (auto *n = XmlGetChildByTag(node, "x", "xmlns", JABBER_FEAT_DELAY))
+		if (auto *pszTimeStamp = XmlGetAttr(n, "stamp")) {
+			msgTime = JabberIsoToUnixTime(pszTimeStamp);
+			return (msgTime != 0) ? n : nullptr;
+		}
 
-	// skip '-' chars
-	char *szStamp = NEWSTR_ALLOCA(ptszTimeStamp);
-	int si = 0, sj = 0;
-	while (true) {
-		if (szStamp[si] == '-')
-			si++;
-		else if (!(szStamp[sj++] = szStamp[si++]))
-			break;
-	};
-	msgTime = JabberIsoToUnixTime(szStamp);
-	return msgTime != 0;
+	return nullptr;
 }
 
 /////////////////////////////////////////////////////////////////////////////////////////
diff --git a/protocols/JabberG/src/stdafx.h b/protocols/JabberG/src/stdafx.h
index 7123b8443e..152255c782 100644
--- a/protocols/JabberG/src/stdafx.h
+++ b/protocols/JabberG/src/stdafx.h
@@ -700,7 +700,7 @@ CMStringW JabberErrorMsg(const TiXmlElement *errorNode, int *errorCode = nullptr
 const wchar_t *JabberStrIStr(const wchar_t *str, const wchar_t *substr);
 CJabberProto*  JabberChooseInstance(bool bIsLink=false);
 
-bool JabberReadXep203delay(const TiXmlElement *node, time_t &msgTime);
+const TiXmlElement* JabberProcessDelay(const TiXmlElement *node, time_t &msgTime);
 
 void SetWindowTextUtf(HWND hwndDlg, const char *szValue);
 void SetDlgItemTextUtf(HWND hwndDlg, int ctrlId, const char *szValue);
-- 
cgit v1.2.3