summaryrefslogtreecommitdiff
path: root/protocols
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2020-02-12 20:49:26 +0300
committerGeorge Hazan <ghazan@miranda.im>2020-02-12 20:49:33 +0300
commitc64e697b69c0c36c034f00683011894b7a41efea (patch)
treeec37956644bc7f354ae42525d6058bca90bac639 /protocols
parent4e6ceb0e009498b4589de4bbe012444ca79881ab (diff)
Jabber: XEP-0333 implementation (chat markers)
Diffstat (limited to 'protocols')
-rwxr-xr-xprotocols/JabberG/src/jabber_caps.h5
-rw-r--r--protocols/JabberG/src/jabber_events.cpp22
-rwxr-xr-xprotocols/JabberG/src/jabber_proto.cpp20
-rwxr-xr-xprotocols/JabberG/src/jabber_proto.h31
-rwxr-xr-xprotocols/JabberG/src/jabber_thread.cpp29
-rw-r--r--protocols/JabberG/src/version.h6
6 files changed, 92 insertions, 21 deletions
diff --git a/protocols/JabberG/src/jabber_caps.h b/protocols/JabberG/src/jabber_caps.h
index 873739064b..2db7ba7fe4 100755
--- a/protocols/JabberG/src/jabber_caps.h
+++ b/protocols/JabberG/src/jabber_caps.h
@@ -96,7 +96,8 @@ typedef unsigned __int64 JabberCapsBits;
#define JABBER_FEAT_DATA_FORMS "jabber:x:data"
#define JABBER_CAPS_DATA_FORMS ((JabberCapsBits)1<<16)
-//!!!!!!!! Vacancy
+#define JABBER_FEAT_CHAT_MARKERS "urn:xmpp:chat-markers:0"
+#define JABBER_CAPS_CHAT_MARKERS ((JabberCapsBits)1<<17)
#define JABBER_FEAT_VCARD_TEMP "vcard-temp"
#define JABBER_CAPS_VCARD_TEMP ((JabberCapsBits)1<<18)
@@ -208,7 +209,7 @@ typedef unsigned __int64 JabberCapsBits;
JABBER_CAPS_BYTESTREAMS | JABBER_CAPS_IBB | JABBER_CAPS_OOB | JABBER_CAPS_CHATSTATES | JABBER_CAPS_AGENTS | JABBER_CAPS_BROWSE | \
JABBER_CAPS_VERSION | JABBER_CAPS_LAST_ACTIVITY | JABBER_CAPS_DATA_FORMS | JABBER_CAPS_VCARD_TEMP | \
JABBER_CAPS_ENTITY_TIME | JABBER_CAPS_PING | JABBER_CAPS_PRIVACY_LISTS | JABBER_CAPS_MESSAGE_RECEIPTS | JABBER_CAPS_PRIVATE_STORAGE | \
- JABBER_CAPS_ROSTER_EXCHANGE | JABBER_CAPS_DIRECT_MUC_INVITE)
+ JABBER_CAPS_ROSTER_EXCHANGE | JABBER_CAPS_DIRECT_MUC_INVITE | JABBER_CAPS_CHAT_MARKERS)
#define JABBER_CAPS_MIRANDA_ALL (JABBER_CAPS_MIRANDA_PARTIAL | JABBER_CAPS_COMMANDS | \
JABBER_CAPS_USER_MOOD_NOTIFY | JABBER_CAPS_USER_TUNE_NOTIFY | JABBER_CAPS_USER_ACTIVITY_NOTIFY \
diff --git a/protocols/JabberG/src/jabber_events.cpp b/protocols/JabberG/src/jabber_events.cpp
index ea5db1e5cb..e6592e1705 100644
--- a/protocols/JabberG/src/jabber_events.cpp
+++ b/protocols/JabberG/src/jabber_events.cpp
@@ -154,6 +154,28 @@ void __cdecl CJabberProto::OnAddContactForever(MCONTACT hContact)
Contact_Hide(hContact, false);
}
+int __cdecl CJabberProto::OnDbMarkedRead(WPARAM, LPARAM hDbEvent)
+{
+ MCONTACT hContact = db_event_getContact(hDbEvent);
+ if (!hContact)
+ return 0;
+
+ // filter out only events of my protocol
+ const char *szProto = Proto_GetBaseAccountName(hContact);
+ if (mir_strcmp(szProto, m_szModuleName))
+ return 0;
+
+ auto *pMark = m_arChatMarks.find((CChatMark *)&hDbEvent);
+ if (pMark) {
+ XmlNode reply("message"); reply << XATTR("to", pMark->szFrom) << XATTR("id", pMark->szId)
+ << XCHILDNS("displayed", JABBER_FEAT_CHAT_MARKERS) << XATTR("id", pMark->szId);
+ m_ThreadInfo->send(reply);
+
+ m_arChatMarks.remove(pMark);
+ }
+ return 0;
+}
+
int __cdecl CJabberProto::OnDbSettingChanged(WPARAM hContact, LPARAM lParam)
{
if (hContact == 0 || !m_bJabberOnline)
diff --git a/protocols/JabberG/src/jabber_proto.cpp b/protocols/JabberG/src/jabber_proto.cpp
index 74b957ef82..9a3008cfa8 100755
--- a/protocols/JabberG/src/jabber_proto.cpp
+++ b/protocols/JabberG/src/jabber_proto.cpp
@@ -56,6 +56,7 @@ CJabberProto::CJabberProto(const char *aProtoName, const wchar_t *aUserName) :
PROTO<CJabberProto>(aProtoName, aUserName),
m_impl(*this),
m_omemo(this),
+ m_arChatMarks(50, NumericKeySortT),
m_lstTransports(50, compareTransports),
m_lstRoster(50, compareListItems),
m_iqManager(this),
@@ -184,6 +185,7 @@ CJabberProto::CJabberProto(const char *aProtoName, const wchar_t *aUserName) :
HookProtoEvent(ME_LANGPACK_CHANGED, &CJabberProto::OnLangChanged);
HookProtoEvent(ME_OPT_INITIALISE, &CJabberProto::OnOptionsInit);
HookProtoEvent(ME_SKIN_ICONSCHANGED, &CJabberProto::OnReloadIcons);
+ HookProtoEvent(ME_DB_EVENT_MARKED_READ, &CJabberProto::OnDbMarkedRead);
HookProtoEvent(ME_DB_CONTACT_SETTINGCHANGED, &CJabberProto::OnDbSettingChanged);
m_iqManager.FillPermanentHandlers();
@@ -906,6 +908,18 @@ HANDLE CJabberProto::SendFile(MCONTACT hContact, const wchar_t *szDescription, w
}
////////////////////////////////////////////////////////////////////////////////////////
+// receives a message
+
+MEVENT CJabberProto::RecvMsg(MCONTACT hContact, PROTORECVEVENT *pre)
+{
+ MEVENT res = CSuper::RecvMsg(hContact, pre);
+ if (pre->szMsgId)
+ m_arChatMarks.insert(new CChatMark(res, pre->szMsgId, (const char*)pre->lParam));
+
+ return res;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
// JabberSendMessage - sends a message
struct TFakeAckParams
@@ -956,7 +970,7 @@ int CJabberProto::SendMsg(MCONTACT hContact, int unused_unknown, const char *psz
int isEncrypted, id = SerialNext();
if (!strncmp(pszSrc, PGP_PROLOG, mir_strlen(PGP_PROLOG))) {
const char *szEnd = strstr(pszSrc, PGP_EPILOG);
- char *tempstring = (char*)alloca(mir_strlen(pszSrc) + 2);
+ char *tempstring = (char *)alloca(mir_strlen(pszSrc) + 2);
size_t nStrippedLength = mir_strlen(pszSrc) - mir_strlen(PGP_PROLOG) - (szEnd ? mir_strlen(szEnd) : 0) + 1;
strncpy_s(tempstring, nStrippedLength, pszSrc + mir_strlen(PGP_PROLOG), _TRUNCATE);
tempstring[nStrippedLength] = 0;
@@ -1006,8 +1020,10 @@ int CJabberProto::SendMsg(MCONTACT hContact, int unused_unknown, const char *psz
m << XATTR("to", szClientJid);
bool bSendReceipt = (m_bMsgAck || getByte(hContact, "MsgAck", false));
- if (bSendReceipt)
+ if (bSendReceipt) {
m << XCHILDNS("request", JABBER_FEAT_MESSAGE_RECEIPTS);
+ m << XCHILDNS("markable", JABBER_FEAT_CHAT_MARKERS);
+ }
if (
// if message delivery check disabled by entity caps manager
diff --git a/protocols/JabberG/src/jabber_proto.h b/protocols/JabberG/src/jabber_proto.h
index 20e6a34ee0..e30d434c58 100755
--- a/protocols/JabberG/src/jabber_proto.h
+++ b/protocols/JabberG/src/jabber_proto.h
@@ -62,6 +62,18 @@ struct TFilterInfo
wchar_t pattern[256];
};
+struct CChatMark
+{
+ CChatMark(MEVENT _p1, const CMStringA &_p2, const CMStringA &_p3) :
+ hEvent(_p1),
+ szId(_p2),
+ szFrom(_p3)
+ {}
+
+ MEVENT hEvent;
+ CMStringA szId, szFrom;
+};
+
struct CJabberProto : public PROTO<CJabberProto>, public IJabberInterface
{
class CJabberProtoImpl
@@ -113,6 +125,8 @@ struct CJabberProto : public PROTO<CJabberProto>, public IJabberInterface
HWND SearchAdvanced(HWND owner) override;
HWND CreateExtendedSearchUI(HWND owner) override;
+ MEVENT RecvMsg(MCONTACT hContact, PROTORECVEVENT *) override;
+
int SendContacts(MCONTACT hContact, int flags, int nContacts, MCONTACT *hContactsList) override;
HANDLE SendFile(MCONTACT hContact, const wchar_t *szDescription, wchar_t **ppszFiles) override;
int SendMsg(MCONTACT hContact, int flags, const char *msg) override;
@@ -136,6 +150,7 @@ struct CJabberProto : public PROTO<CJabberProto>, public IJabberInterface
//====| Events |======================================================================
void __cdecl OnAddContactForever(MCONTACT hContact);
+ int __cdecl OnDbMarkedRead(WPARAM, LPARAM);
int __cdecl OnDbSettingChanged(WPARAM, LPARAM);
int __cdecl OnIdleChanged(WPARAM, LPARAM);
int __cdecl OnLangChanged(WPARAM, LPARAM);
@@ -219,14 +234,14 @@ struct CJabberProto : public PROTO<CJabberProto>, public IJabberInterface
HANDLE m_hThreadHandle;
- char *m_szJabberJID;
- int m_nJabberSearchID;
- time_t m_tmJabberLoggedInTime;
- time_t m_tmJabberIdleStartTime;
- UINT m_nJabberCodePage;
- char *m_tszSelectedLang;
+ char* m_szJabberJID;
+ int m_nJabberSearchID;
+ time_t m_tmJabberLoggedInTime;
+ time_t m_tmJabberIdleStartTime;
+ UINT m_nJabberCodePage;
+ char* m_tszSelectedLang;
- mir_cs m_csModeMsgMutex;
+ mir_cs m_csModeMsgMutex;
JABBER_MODEMSGS m_modeMsgs;
bool m_bCisAvailable;
@@ -312,6 +327,8 @@ struct CJabberProto : public PROTO<CJabberProto>, public IJabberInterface
CNoteList m_notes;
+ OBJLIST<CChatMark> m_arChatMarks;
+
/*******************************************************************
* Function declarations
*******************************************************************/
diff --git a/protocols/JabberG/src/jabber_thread.cpp b/protocols/JabberG/src/jabber_thread.cpp
index 18cd3d03fb..e46d5a3c9b 100755
--- a/protocols/JabberG/src/jabber_thread.cpp
+++ b/protocols/JabberG/src/jabber_thread.cpp
@@ -1060,13 +1060,24 @@ void CJabberProto::OnProcessMessage(const TiXmlElement *node, ThreadData *info)
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.
- if ((!type || mir_strcmpi(type, "error")) && XmlGetChildByTag(node, "request", "xmlns", JABBER_FEAT_MESSAGE_RECEIPTS)) {
- info->send(
- XmlNode("message") << XATTR("to", from) << XATTR("id", idStr)
- << XCHILDNS("received", JABBER_FEAT_MESSAGE_RECEIPTS) << XATTR("id", idStr));
-
- if (pFromResource)
- pFromResource->m_jcbManualDiscoveredCaps |= JABBER_CAPS_MESSAGE_RECEIPTS;
+ bool bSendMark = false;
+ if ((!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) {
+ XmlNode reply("message"); reply << XATTR("to", from) << XATTR("id", idStr);
+ if (bSendReceipt) {
+ if (pFromResource)
+ pFromResource->m_jcbManualDiscoveredCaps |= JABBER_CAPS_MESSAGE_RECEIPTS;
+ reply << XCHILDNS("received", JABBER_FEAT_MESSAGE_RECEIPTS) << XATTR("id", idStr);
+ }
+ if (bSendMark) {
+ if (pFromResource)
+ pFromResource->m_jcbManualDiscoveredCaps |= JABBER_CAPS_CHAT_MARKERS;
+ reply << XCHILDNS("received", JABBER_FEAT_CHAT_MARKERS) << XATTR("id", idStr);
+ }
+ info->send(reply);
+ }
}
if (m_messageManager.HandleMessagePermanent(node, info))
@@ -1399,6 +1410,10 @@ void CJabberProto::OnProcessMessage(const TiXmlElement *node, ThreadData *info)
}
recv.timestamp = (DWORD)msgTime;
recv.szMessage = szMessage.GetBuffer();
+ if (bSendMark) {
+ recv.szMsgId = idStr;
+ recv.lParam = (LPARAM)from;
+ }
ProtoChainRecvMsg(hContact, &recv);
}
diff --git a/protocols/JabberG/src/version.h b/protocols/JabberG/src/version.h
index f60e186d99..5f7904a159 100644
--- a/protocols/JabberG/src/version.h
+++ b/protocols/JabberG/src/version.h
@@ -1,7 +1,7 @@
#define __MAJOR_VERSION 0
-#define __MINOR_VERSION 11
-#define __RELEASE_NUM 0
-#define __BUILD_NUM 5
+#define __MINOR_VERSION 95
+#define __RELEASE_NUM 11
+#define __BUILD_NUM 1
#include <stdver.h>