From c64e697b69c0c36c034f00683011894b7a41efea Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 12 Feb 2020 20:49:26 +0300 Subject: Jabber: XEP-0333 implementation (chat markers) --- protocols/JabberG/src/jabber_caps.h | 5 +++-- protocols/JabberG/src/jabber_events.cpp | 22 ++++++++++++++++++++++ protocols/JabberG/src/jabber_proto.cpp | 20 ++++++++++++++++++-- protocols/JabberG/src/jabber_proto.h | 31 ++++++++++++++++++++++++------- protocols/JabberG/src/jabber_thread.cpp | 29 ++++++++++++++++++++++------- protocols/JabberG/src/version.h | 6 +++--- 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(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(); @@ -905,6 +907,18 @@ HANDLE CJabberProto::SendFile(MCONTACT hContact, const wchar_t *szDescription, w return ft; } +//////////////////////////////////////////////////////////////////////////////////////// +// 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 @@ -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, public IJabberInterface { class CJabberProtoImpl @@ -113,6 +125,8 @@ struct CJabberProto : public PROTO, 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, 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, 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, public IJabberInterface CNoteList m_notes; + OBJLIST 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 -- cgit v1.2.3