diff options
| -rwxr-xr-x | protocols/JabberG/src/jabber_caps.cpp | 1 | ||||
| -rwxr-xr-x | protocols/JabberG/src/jabber_caps.h | 4 | ||||
| -rwxr-xr-x | protocols/JabberG/src/jabber_iqid.cpp | 3 | ||||
| -rwxr-xr-x | protocols/JabberG/src/jabber_proto.h | 2 | ||||
| -rwxr-xr-x | protocols/JabberG/src/jabber_thread.cpp | 53 | 
5 files changed, 63 insertions, 0 deletions
| diff --git a/protocols/JabberG/src/jabber_caps.cpp b/protocols/JabberG/src/jabber_caps.cpp index 4b99b77219..83a13dcd39 100755 --- a/protocols/JabberG/src/jabber_caps.cpp +++ b/protocols/JabberG/src/jabber_caps.cpp @@ -76,6 +76,7 @@ const JabberFeatCapPair g_JabberFeatCapPairs[] = {  	{ JABBER_FEAT_ROSTER_EXCHANGE,      JABBER_CAPS_ROSTER_EXCHANGE,      LPGENW("Supports Roster Exchange") },
  	{ JABBER_FEAT_DIRECT_MUC_INVITE,    JABBER_CAPS_DIRECT_MUC_INVITE,    LPGENW("Supports direct chat invitations (XEP-0249)") },
  	{ JABBER_FEAT_OMEMO_DEVICELIST_NOTIFY,			JABBER_CAPS_OMEMO_DEVICELIST_NOTIFY,		  LPGENW("Receives information about OMEMO devices") },
 +	{ JABBER_FEAT_CARBONS,				JABBER_CAPS_CARBONS,			  LPGENW("Supports message carbons (XEP-0280)")},
  	{ nullptr }
  };
 diff --git a/protocols/JabberG/src/jabber_caps.h b/protocols/JabberG/src/jabber_caps.h index 66f033119d..fe69024b21 100755 --- a/protocols/JabberG/src/jabber_caps.h +++ b/protocols/JabberG/src/jabber_caps.h @@ -154,6 +154,9 @@ typedef unsigned __int64 JabberCapsBits;  #define JABBER_FEAT_PUBSUB_EVENT                L"http://jabber.org/protocol/pubsub#event"
  #define JABBER_FEAT_PUBSUB_NODE_CONFIG          L"http://jabber.org/protocol/pubsub#node_config"
 +#define JABBER_FEAT_CARBONS						L"urn:xmpp:carbons:2"
 +#define JABBER_CAPS_CARBONS						((JabberCapsBits)1<<43)
 +
  #define JABBER_CAPS_MESSAGE_EVENTS_NO_DELIVERY  ((JabberCapsBits)1<<63)
  #define JABBER_CAPS_OTHER_SPECIAL               (JABBER_CAPS_MESSAGE_EVENTS_NO_DELIVERY|JABBER_RESOURCE_CAPS_ERROR) // must contain all the caps not listed in g_JabberFeatCapPairs, to prevent using these bits for features registered through IJabberNetInterface::RegisterFeature()
 @@ -168,6 +171,7 @@ typedef unsigned __int64 JabberCapsBits;                                       JABBER_CAPS_USER_MOOD_NOTIFY | JABBER_CAPS_USER_TUNE_NOTIFY | JABBER_CAPS_USER_ACTIVITY_NOTIFY  \
  									 | JABBER_CAPS_PLATFORMX86 | JABBER_CAPS_PLATFORMX64)
 +#define JABBER_XMLNS_FORWARD					L"urn:xmpp:forward:0"
  #define JABBER_EXT_SECUREIM                     L"secureim"
  #define JABBER_EXT_MIROTR                       L"mirotr"
 diff --git a/protocols/JabberG/src/jabber_iqid.cpp b/protocols/JabberG/src/jabber_iqid.cpp index da7c1260f6..4ecac9d48e 100755 --- a/protocols/JabberG/src/jabber_iqid.cpp +++ b/protocols/JabberG/src/jabber_iqid.cpp @@ -135,6 +135,9 @@ void CJabberProto::OnProcessLoginRq(ThreadData *info, DWORD rq)  		if (info->jabberServerCaps & JABBER_CAPS_ARCHIVE_AUTO)
  			EnableArchive(m_options.EnableMsgArchive != 0);
 +		if (info->jabberServerCaps & JABBER_CAPS_CARBONS)
 +			EnableCarbons(true);
 +
  		if (m_options.AutoJoinBookmarks) {
  			LIST<JABBER_LIST_ITEM> ll(10);
  			LISTFOREACH(i, this, LIST_BOOKMARK)
 diff --git a/protocols/JabberG/src/jabber_proto.h b/protocols/JabberG/src/jabber_proto.h index b04f639967..350b5e438c 100755 --- a/protocols/JabberG/src/jabber_proto.h +++ b/protocols/JabberG/src/jabber_proto.h @@ -737,6 +737,8 @@ struct CJabberProto : public PROTO<CJabberProto>, public IJabberInterface  	bool   ProcessCaptcha(HXML node, HXML parentNode, ThreadData *info);
 +	void   EnableCarbons(bool bEnable);
 +
  	//---- jabber_util.c -----------------------------------------------------------------
  	pResourceStatus ResourceInfoFromJID(const wchar_t *jid);
 diff --git a/protocols/JabberG/src/jabber_thread.cpp b/protocols/JabberG/src/jabber_thread.cpp index 60cf077661..1177020ab0 100755 --- a/protocols/JabberG/src/jabber_thread.cpp +++ b/protocols/JabberG/src/jabber_thread.cpp @@ -1051,6 +1051,43 @@ void CJabberProto::OnProcessMessage(HXML node, ThreadData *info)  	if (m_messageManager.HandleMessagePermanent(node, info))
  		return;
 +	//Handle carbons. The message MUST be coming from our bare JID.
 +	HXML carbon = nullptr;
 +	bool carbonSent = false; //2 cases: received or sent.
 +	if (this->IsMyOwnJID(from)) {
 +		carbon = XmlGetChildByTag(node, "received", "xmlns", JABBER_FEAT_CARBONS);
 +		if (!carbon) {
 +			carbon = XmlGetChildByTag(node, "sent", "xmlns", JABBER_FEAT_CARBONS);
 +			if (carbon)
 +				carbonSent = true;
 +		}
 +		if (carbon) {
 +			HXML forwarded = NULL;
 +			HXML message = NULL;
 +			//Carbons MUST have forwarded/message content
 +			if (!(forwarded = XmlGetChildByTag(carbon, "forwarded", "xmlns", JABBER_XMLNS_FORWARD))
 +				|| !(message = XmlGetChild(forwarded, "message")))
 +				return;
 +
 +			//Unwrap the carbon in any case
 +			node = message;
 +			type = XmlGetAttrValue(node, L"type");
 +
 +			if (!carbonSent) {
 +				//Received should just be treated like incoming messages, except maybe not flash the flasher. Simply unwrap.
 +				from = XmlGetAttrValue(node, L"from");
 +				if (from == nullptr)
 +					return;
 +			}
 +			else {
 +				//Sent should set SENT flag and invert from/to.
 +				from = XmlGetAttrValue(node, L"to");
 +				if (from == nullptr)
 +					return;
 +			}
 +		}
 +	}
 +
  	MCONTACT hContact = HContactFromJID(from);
  	JABBER_LIST_ITEM *chatItem = ListGetItemPtr(LIST_CHATROOM, from);
  	if (chatItem) {
 @@ -1416,6 +1453,11 @@ void CJabberProto::OnProcessMessage(HXML node, ThreadData *info)  		msgTime = now;
  	PROTORECVEVENT recv = { 0 };
 +	if (carbon) {
 +		recv.flags |= PREF_CREATEREAD;
 +		if (carbonSent)
 +			recv.flags |= PREF_SENT;
 +	}
  	recv.timestamp = (DWORD)msgTime;
  	recv.szMessage = buf;
  	recv.lParam = (LPARAM)((pFromResource != nullptr && m_options.EnableRemoteControl) ? pFromResource->m_tszResourceName : 0);
 @@ -1941,6 +1983,17 @@ void CJabberProto::OnProcessRegIq(HXML node, ThreadData *info)  	}
  }
 +
 +/////////////////////////////////////////////////////////////////////////////////////////
 +// Carbons -- this might need to go into its own module
 +
 +void CJabberProto::EnableCarbons(bool bEnable)
 +{
 +	m_ThreadInfo->send(XmlNodeIq(L"set", SerialNext())
 +		<< XCHILDNS((bEnable) ? L"enable" : L"disable", JABBER_FEAT_CARBONS));
 +}
 +
 +
  /////////////////////////////////////////////////////////////////////////////////////////
  // ThreadData constructor & destructor
 | 
