From d353887c8cde702539d8d0f3d339c158498648ed Mon Sep 17 00:00:00 2001 From: Gluzskiy Alexandr Date: Sun, 2 Apr 2017 16:16:36 +0300 Subject: jabber: omemo: working on 4.3 proper dynamic caps implementation for omemo caps/features and for miranda caps/features in general as required by xep-0115 removed my old attempt to implement dynamic omemo cap fixed few bugs in OmemoHandleDeviceList --- protocols/JabberG/src/jabber_caps.cpp | 63 ++++++++++++++++++++++++++++++---- protocols/JabberG/src/jabber_caps.h | 6 +++- protocols/JabberG/src/jabber_misc.cpp | 3 ++ protocols/JabberG/src/jabber_omemo.cpp | 11 +++--- protocols/JabberG/src/jabber_opt.cpp | 19 +--------- protocols/JabberG/src/jabber_util.cpp | 7 +++- 6 files changed, 77 insertions(+), 32 deletions(-) mode change 100644 => 100755 protocols/JabberG/src/jabber_misc.cpp (limited to 'protocols/JabberG') diff --git a/protocols/JabberG/src/jabber_caps.cpp b/protocols/JabberG/src/jabber_caps.cpp index f92bdc708b..a409a61dca 100755 --- a/protocols/JabberG/src/jabber_caps.cpp +++ b/protocols/JabberG/src/jabber_caps.cpp @@ -83,6 +83,7 @@ const JabberFeatCapPairExt g_JabberFeatCapPairsExt[] = { { JABBER_EXT_SECUREIM, JABBER_CAPS_SECUREIM, "SecureIM/IsContactSecured" }, { JABBER_EXT_MIROTR, JABBER_CAPS_MIROTR, "MirOTRMenuCheckService" }, { JABBER_EXT_NEWGPG, JABBER_CAPS_NEWGPG, "/ExportGPGKeys" }, + { JABBER_EXT_OMEMO, JABBER_CAPS_OMEMO, }, { JABBER_EXT_NUDGE, JABBER_CAPS_ATTENTION, "NUDGE/Send" }, { JABBER_EXT_JINGLE, JABBER_CAPS_JINGLE, "Jingle/StartSession" }, { JABBER_EXT_COMMANDS, JABBER_CAPS_COMMANDS }, @@ -518,16 +519,55 @@ BOOL CJabberClientCaps::SetPartialCaps(int nIqId, JabberCapsBits jcbCaps) ///////////////////////////////////////////////////////////////////////////////////////// // CJabberClientCapsManager class -CJabberClientCapsManager::CJabberClientCapsManager(CJabberProto *proto) +CJabberClientCapsManager::CJabberClientCapsManager(CJabberProto *proto) : m_szFeaturesCrc(nullptr) { ppro = proto; m_pClients = NULL; + + UpdateFeatHash(); + +} + +void CJabberClientCapsManager::UpdateFeatHash() +{ + if (m_szFeaturesCrc) + mir_free(m_szFeaturesCrc); + wchar_t feat_buf[2048]; + mir_wstrcpy(feat_buf, L""); + JabberCapsBits jcb = JABBER_CAPS_MIRANDA_ALL; + for (int i = 0; i < ppro->m_lstJabberFeatCapPairsDynamic.getCount(); i++) + jcb |= ppro->m_lstJabberFeatCapPairsDynamic[i]->jcbCap; + if (!ppro->m_options.AllowVersionRequests) + jcb &= ~JABBER_CAPS_VERSION; + + if (ppro->m_options.UseOMEMO) + jcb |= JABBER_CAPS_OMEMO_DEVICELIST_NOTIFY; + + + for (int i = 0; g_JabberFeatCapPairs[i].szFeature; i++) + if (jcb & g_JabberFeatCapPairs[i].jcbCap) + mir_wstrcat(feat_buf, g_JabberFeatCapPairs[i].szFeature); + + for (int i = 0; i < ppro->m_lstJabberFeatCapPairsDynamic.getCount(); i++) + if (jcb & ppro->m_lstJabberFeatCapPairsDynamic[i]->jcbCap) + mir_wstrcat(feat_buf, ppro->m_lstJabberFeatCapPairsDynamic[i]->szFeature); + unsigned int hash = mir_hashstrW(feat_buf); + char *szHash = mir_base64_encode((BYTE*)&hash, sizeof(int)); + m_szFeaturesCrc = mir_a2u(szHash); + mir_free(szHash); +} + +const wchar_t* CJabberClientCapsManager::GetFeaturesCrc() +{ + return m_szFeaturesCrc; } CJabberClientCapsManager::~CJabberClientCapsManager() { if (m_pClients) delete m_pClients; + if(m_szFeaturesCrc) + mir_free(m_szFeaturesCrc); } CJabberClientCaps * CJabberClientCapsManager::FindClient(const wchar_t *szNode) @@ -546,7 +586,10 @@ CJabberClientCaps * CJabberClientCapsManager::FindClient(const wchar_t *szNode) void CJabberClientCapsManager::AddDefaultCaps() { - SetClientCaps(JABBER_CAPS_MIRANDA_NODE, szCoreVersion, JABBER_CAPS_MIRANDA_ALL); + wchar_t szVerWHash[256]; + mir_snwprintf(szVerWHash, 255, L"%s %s", szCoreVersion, m_szFeaturesCrc); + + SetClientCaps(JABBER_CAPS_MIRANDA_NODE, szVerWHash, ppro->m_options.UseOMEMO ? (JABBER_CAPS_MIRANDA_ALL | JABBER_CAPS_OMEMO_DEVICELIST_NOTIFY) : JABBER_CAPS_MIRANDA_ALL); for (int i=0; g_JabberFeatCapPairsExt[i].szFeature; i++) if (g_JabberFeatCapPairsExt[i].Valid()) @@ -614,10 +657,11 @@ BOOL CJabberClientCapsManager::HandleInfoRequest(HXML, CJabberIqInfo *pInfo, con for (i=0; g_JabberFeatCapPairsExt[i].szFeature; i++) { if (!g_JabberFeatCapPairsExt[i].Valid()) continue; - - wchar_t szExtCap[ 512 ]; + //TODO: something better here + wchar_t szExtCap[ 512 ], szExtCapWHash [560]; mir_snwprintf(szExtCap, L"%s#%s", JABBER_CAPS_MIRANDA_NODE, g_JabberFeatCapPairsExt[i].szFeature); - if (!mir_wstrcmp(szNode, szExtCap)) { + mir_snwprintf(szExtCapWHash, L"%s %s", szExtCap, m_szFeaturesCrc); + if (!mir_wstrcmp(szNode, szExtCap) || !mir_wstrcmp(szNode, szExtCapWHash)) { jcb = g_JabberFeatCapPairsExt[i].jcbCap; break; } @@ -625,9 +669,11 @@ BOOL CJabberClientCapsManager::HandleInfoRequest(HXML, CJabberIqInfo *pInfo, con // check features registered through IJabberNetInterface::RegisterFeature() and IJabberNetInterface::AddFeatures() for (i=0; i < ppro->m_lstJabberFeatCapPairsDynamic.getCount(); i++) { - wchar_t szExtCap[ 512 ]; + //TODO: something better here + wchar_t szExtCap[ 512 ], szExtCapWHash[560]; mir_snwprintf(szExtCap, L"%s#%s", JABBER_CAPS_MIRANDA_NODE, ppro->m_lstJabberFeatCapPairsDynamic[i]->szExt); - if (!mir_wstrcmp(szNode, szExtCap)) { + mir_snwprintf(szExtCapWHash, L"%s %s", szExtCap, m_szFeaturesCrc); + if (!mir_wstrcmp(szNode, szExtCap) || !mir_wstrcmp(szNode, szExtCapWHash)) { jcb = ppro->m_lstJabberFeatCapPairsDynamic[i]->jcbCap; break; } @@ -643,6 +689,9 @@ BOOL CJabberClientCapsManager::HandleInfoRequest(HXML, CJabberIqInfo *pInfo, con jcb |= ppro->m_lstJabberFeatCapPairsDynamic[i]->jcbCap; } + if (ppro->m_options.UseOMEMO) + jcb |= JABBER_CAPS_OMEMO_DEVICELIST_NOTIFY; + if (!ppro->m_options.AllowVersionRequests) jcb &= ~JABBER_CAPS_VERSION; diff --git a/protocols/JabberG/src/jabber_caps.h b/protocols/JabberG/src/jabber_caps.h index 097108c608..16805680b5 100755 --- a/protocols/JabberG/src/jabber_caps.h +++ b/protocols/JabberG/src/jabber_caps.h @@ -167,7 +167,7 @@ typedef unsigned __int64 JabberCapsBits; JABBER_CAPS_ROSTER_EXCHANGE | JABBER_CAPS_DIRECT_MUC_INVITE) #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 | JABBER_CAPS_OMEMO_DEVICELIST_NOTIFY \ + JABBER_CAPS_USER_MOOD_NOTIFY | JABBER_CAPS_USER_TUNE_NOTIFY | JABBER_CAPS_USER_ACTIVITY_NOTIFY \ | JABBER_CAPS_PLATFORMX86 | JABBER_CAPS_PLATFORMX64) @@ -175,6 +175,7 @@ typedef unsigned __int64 JabberCapsBits; #define JABBER_EXT_MIROTR L"mirotr" #define JABBER_EXT_JINGLE L"jingle" #define JABBER_EXT_NEWGPG L"new_gpg" +#define JABBER_EXT_OMEMO L"omemo" #define JABBER_EXT_NUDGE L"nudge" #define JABBER_EXT_COMMANDS L"cmds" #define JABBER_EXT_USER_MOOD L"mood" @@ -276,6 +277,7 @@ protected: mir_cs m_cs; CJabberClientCaps *m_pClients; CJabberProto *ppro; + wchar_t *m_szFeaturesCrc; protected: CJabberClientCaps *FindClient(const wchar_t *szNode); @@ -285,6 +287,8 @@ public: ~CJabberClientCapsManager(); void AddDefaultCaps(); + const wchar_t* GetFeaturesCrc(); + void UpdateFeatHash(); JabberCapsBits GetClientCaps(wchar_t *szNode, wchar_t *szVer); BOOL SetClientCaps(const wchar_t *szNode, const wchar_t *szVer, JabberCapsBits jcbCaps, int nIqId = -1); diff --git a/protocols/JabberG/src/jabber_misc.cpp b/protocols/JabberG/src/jabber_misc.cpp old mode 100644 new mode 100755 index 4950875dd3..6b271d7fca --- a/protocols/JabberG/src/jabber_misc.cpp +++ b/protocols/JabberG/src/jabber_misc.cpp @@ -330,6 +330,9 @@ void CJabberProto::FormatMirVer(pResourceStatus &resource, CMStringW &res) if (resource->m_tszCapsExt && wcsstr(resource->m_tszCapsExt, JABBER_EXT_NEWGPG) && !wcsstr(res, L"(New_GPG)")) res.Append(L" (New_GPG)"); + if (resource->m_tszCapsExt && wcsstr(resource->m_tszCapsExt, JABBER_EXT_OMEMO) && !wcsstr(res, L"(omemo)")) + res.Append(L" (omemo)"); + if (resource->m_tszResourceName && !wcsstr(res, resource->m_tszResourceName)) if (wcsstr(res, L"Miranda IM") || wcsstr(res, L"Miranda NG") || m_options.ShowForeignResourceInMirVer) res.AppendFormat(L" [%s]", resource->m_tszResourceName); diff --git a/protocols/JabberG/src/jabber_omemo.cpp b/protocols/JabberG/src/jabber_omemo.cpp index a86e8e0805..be4f9ce400 100755 --- a/protocols/JabberG/src/jabber_omemo.cpp +++ b/protocols/JabberG/src/jabber_omemo.cpp @@ -559,7 +559,7 @@ void CJabberProto::OmemoHandleDeviceList(HXML node) if (!node) return; HXML message = xmlGetParent(node); - message = xmlGetParent(node); + message = xmlGetParent(message); LPCTSTR jid = XmlGetAttrValue(message, L"from"); MCONTACT hContact = HContactFromJID(jid); node = XmlGetChild(node, "item"); //get node @@ -578,9 +578,9 @@ void CJabberProto::OmemoHandleDeviceList(HXML node) //check if our device exist bool own_device_listed = false; DWORD own_id = omemo::GetOwnDeviceId(this); - int i = 0; char setting_name[64]; - for (HXML list_item = xmlGetFirstChild(node); list_item; xmlGetNextNode(list_item)) + HXML list_item; + for (int p = 1, i = 0; (list_item = XmlGetNthChild(node, L"device", p)) != NULL; p++, i++) { current_id_str = xmlGetAttrValue(list_item, L"id"); current_id = _wtoi(current_id_str); @@ -591,13 +591,14 @@ void CJabberProto::OmemoHandleDeviceList(HXML node) } if (!own_device_listed) OmemoAnnounceDevice(); + //TODO: remove all settings higher than 'i' from db } else { //store device id's - int i = 0; char setting_name[64]; - for (HXML list_item = xmlGetFirstChild(node); list_item; xmlGetNextNode(list_item), i++) + HXML list_item; + for (int p = 1, i = 0; (list_item = XmlGetNthChild(node, L"device", p)) != NULL; p++, i++) { current_id_str = xmlGetAttrValue(list_item, L"id"); current_id = _wtoi(current_id_str); diff --git a/protocols/JabberG/src/jabber_opt.cpp b/protocols/JabberG/src/jabber_opt.cpp index 071c841546..8393b4b964 100755 --- a/protocols/JabberG/src/jabber_opt.cpp +++ b/protocols/JabberG/src/jabber_opt.cpp @@ -848,24 +848,7 @@ public: } } } - //dynamic caps - { - JabberCapsBits jcb = 0; - // set all bits occupied by g_JabberFeatCapPairs - for (int i = 0; g_JabberFeatCapPairs[i].szFeature; i++) - jcb |= g_JabberFeatCapPairs[i].jcbCap; - - // set all bits already occupied by external plugins - for (int i = 0; i < m_proto->m_lstJabberFeatCapPairsDynamic.getCount(); i++) - jcb |= m_proto->m_lstJabberFeatCapPairsDynamic[i]->jcbCap; - if(m_proto->m_options.UseOMEMO) - jcb |= JABBER_CAPS_OMEMO_DEVICELIST_NOTIFY; - else - jcb &= ~JABBER_CAPS_OMEMO_DEVICELIST_NOTIFY; - - m_proto->m_clientCapsManager.SetClientCaps(JABBER_CAPS_MIRANDA_NODE, szCoreVersion, jcb); - } - + m_proto->m_clientCapsManager.UpdateFeatHash(); m_proto->SendPresence(m_proto->m_iStatus, true); } diff --git a/protocols/JabberG/src/jabber_util.cpp b/protocols/JabberG/src/jabber_util.cpp index 19de86f090..c29725c02f 100755 --- a/protocols/JabberG/src/jabber_util.cpp +++ b/protocols/JabberG/src/jabber_util.cpp @@ -385,8 +385,10 @@ void CJabberProto::SendPresenceTo(int status, const wchar_t* to, HXML extra, con // XEP-0115:Entity Capabilities if (m_options.AllowVersionRequests) { + wchar_t szVersionWithFeatHash[256]; + mir_snwprintf(szVersionWithFeatHash, 255, L"%s %s", szCoreVersion, m_clientCapsManager.GetFeaturesCrc()); HXML c = p << XCHILDNS(L"c", JABBER_FEAT_ENTITY_CAPS) << XATTR(L"node", JABBER_CAPS_MIRANDA_NODE) - << XATTR(L"ver", szCoreVersion); + << XATTR(L"ver", szVersionWithFeatHash); LIST arrExtCaps(5); if (bSecureIM) @@ -398,6 +400,9 @@ void CJabberProto::SendPresenceTo(int status, const wchar_t* to, HXML extra, con if (bNewGPG) arrExtCaps.insert(JABBER_EXT_NEWGPG); + if(m_options.UseOMEMO) + arrExtCaps.insert(JABBER_EXT_OMEMO); + if (bPlatform) arrExtCaps.insert(JABBER_EXT_PLATFORMX64); else -- cgit v1.2.3