diff options
author | George Hazan <ghazan@miranda.im> | 2020-02-12 20:49:26 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2020-02-12 20:49:33 +0300 |
commit | c64e697b69c0c36c034f00683011894b7a41efea (patch) | |
tree | ec37956644bc7f354ae42525d6058bca90bac639 /protocols/JabberG | |
parent | 4e6ceb0e009498b4589de4bbe012444ca79881ab (diff) |
Jabber: XEP-0333 implementation (chat markers)
Diffstat (limited to 'protocols/JabberG')
-rwxr-xr-x | protocols/JabberG/src/jabber_caps.h | 5 | ||||
-rw-r--r-- | protocols/JabberG/src/jabber_events.cpp | 22 | ||||
-rwxr-xr-x | protocols/JabberG/src/jabber_proto.cpp | 20 | ||||
-rwxr-xr-x | protocols/JabberG/src/jabber_proto.h | 31 | ||||
-rwxr-xr-x | protocols/JabberG/src/jabber_thread.cpp | 29 | ||||
-rw-r--r-- | 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<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>
|