From 5ce5965da1db4cfd5e39a89b0dd922e2fe6cf59e Mon Sep 17 00:00:00 2001 From: George Hazan Date: Mon, 2 Mar 2020 22:40:54 +0300 Subject: Jabber: - capability cache is stored in a json file now instead of database; - caps manager became global; - account-dependent methods of CJabberClientCapsManager moved to CJabberProto; - code cleaning --- protocols/JabberG/src/jabber.cpp | 9 + protocols/JabberG/src/jabber_api.cpp | 2 +- protocols/JabberG/src/jabber_caps.cpp | 344 ++++++++++++++++----------- protocols/JabberG/src/jabber_caps.h | 27 +-- protocols/JabberG/src/jabber_iq_handlers.cpp | 2 +- protocols/JabberG/src/jabber_opt.cpp | 2 +- protocols/JabberG/src/jabber_proto.cpp | 3 +- protocols/JabberG/src/jabber_proto.h | 6 +- protocols/JabberG/src/jabber_thread.cpp | 16 +- protocols/JabberG/src/jabber_util.cpp | 2 +- protocols/JabberG/src/stdafx.h | 2 + 11 files changed, 234 insertions(+), 181 deletions(-) (limited to 'protocols/JabberG/src') diff --git a/protocols/JabberG/src/jabber.cpp b/protocols/JabberG/src/jabber.cpp index 80aceb2c5b..e6066538d6 100755 --- a/protocols/JabberG/src/jabber.cpp +++ b/protocols/JabberG/src/jabber.cpp @@ -177,6 +177,13 @@ int CMPlugin::Load() g_MenuInit(); HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded); JabberUserInfoInit(); + + if (!db_get_b(0, "Compatibility", "JabberCaps", 0)) { + db_delete_module(0, "JabberCaps"); + db_set_b(0, "Compatibility", "JabberCaps", 1); + } + + g_clientCapsManager.Load(); return 0; } @@ -185,6 +192,8 @@ int CMPlugin::Load() int CMPlugin::Unload() { + g_clientCapsManager.Save(); + g_XstatusIconsUninit(); JabberUserInfoUninit(); diff --git a/protocols/JabberG/src/jabber_api.cpp b/protocols/JabberG/src/jabber_api.cpp index f238fa7d15..59104f3dfd 100644 --- a/protocols/JabberG/src/jabber_api.cpp +++ b/protocols/JabberG/src/jabber_api.cpp @@ -226,7 +226,7 @@ int CJabberProto::RegisterFeature(const char *szFeature, const char *szDescripti if (wcschr(L"bcdfghjklmnpqrstvwxz0123456789", *pSrc)) *pDst++ = *pSrc; *pDst = 0; - m_clientCapsManager.SetOwnCaps(JABBER_CAPS_MIRANDA_NODE, szExt, jcb); + g_clientCapsManager.SetClientCaps(JABBER_CAPS_MIRANDA_NODE, m_szFeaturesCrc, szExt, jcb); fcp = new JabberFeatCapPairDynamic(); fcp->szExt = szExt; // will be deallocated along with other values of JabberFeatCapPairDynamic in CJabberProto destructor diff --git a/protocols/JabberG/src/jabber_caps.cpp b/protocols/JabberG/src/jabber_caps.cpp index 8ee625bf42..d696b687d5 100755 --- a/protocols/JabberG/src/jabber_caps.cpp +++ b/protocols/JabberG/src/jabber_caps.cpp @@ -28,6 +28,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "jabber_caps.h" #include "version.h" +CJabberClientCapsManager g_clientCapsManager; + const JabberFeatCapPair g_JabberFeatCapPairs[] = { { JABBER_FEAT_DISCO_INFO, JABBER_CAPS_DISCO_INFO, LPGEN("Supports Service Discovery info") }, @@ -114,7 +116,7 @@ void CJabberProto::AddDefaultCaps() char szOsBuffer[256]; OS_GetDisplayString(szOsBuffer, _countof(szOsBuffer)); - CJabberClientPartialCaps *pCaps = m_clientCapsManager.SetOwnCaps(JABBER_CAPS_MIRANDA_NODE, __VERSION_STRING_DOTS, myCaps); + CJabberClientPartialCaps *pCaps = g_clientCapsManager.SetClientCaps(JABBER_CAPS_MIRANDA_NODE, m_szFeaturesCrc, __VERSION_STRING_DOTS, myCaps); pCaps->m_szOs = mir_strdup("Microsoft Windows"); pCaps->m_szOsVer = mir_strdup(szOsBuffer); pCaps->m_szSoft = mir_strdup("Miranda NG Jabber Protocol"); @@ -315,6 +317,97 @@ JabberCapsBits CJabberProto::GetResourceCapabilities(const char *jid, pResourceS return JABBER_RESOURCE_CAPS_IN_PROGRESS; } +bool CJabberProto::HandleCapsInfoRequest(const TiXmlElement *, CJabberIqInfo *pInfo, const char *szNode) +{ + JabberCapsBits jcb = 0; + + if (szNode) { + char szExtCap[512], szExtCapWHash[560]; + mir_snprintf(szExtCap, "%s#%s", JABBER_CAPS_MIRANDA_NODE, m_szFeaturesCrc.c_str()); + if (!mir_strcmp(szExtCap, szNode)) { + szNode = nullptr; + goto LBL_All; + } + + for (auto &it : g_JabberFeatCapPairsExt) { + if (!it.Valid()) + continue; + + // TODO: something better here + mir_snprintf(szExtCap, "%s#%s", JABBER_CAPS_MIRANDA_NODE, it.szFeature); + mir_snprintf(szExtCapWHash, "%s %s", szExtCap, m_szFeaturesCrc.c_str()); + if (!mir_strcmp(szNode, szExtCap) || !mir_strcmp(szNode, szExtCapWHash)) { + jcb = it.jcbCap; + break; + } + } + + // check features registered through IJabberNetInterface::RegisterFeature() and IJabberNetInterface::AddFeatures() + for (auto &it : m_lstJabberFeatCapPairsDynamic) { + // TODO: something better here + mir_snprintf(szExtCap, "%s#%s", JABBER_CAPS_MIRANDA_NODE, it->szExt); + mir_snprintf(szExtCapWHash, "%s %s", szExtCap, m_szFeaturesCrc.c_str()); + if (!mir_strcmp(szNode, szExtCap) || !mir_strcmp(szNode, szExtCapWHash)) { + jcb = it->jcbCap; + break; + } + } + + // unknown node, not XEP-0115 request + if (!jcb) + return false; + } + else { + LBL_All: + jcb = JABBER_CAPS_MIRANDA_ALL; + for (auto &it : m_lstJabberFeatCapPairsDynamic) + jcb |= it->jcbCap; + } + + if (m_bUseOMEMO) + jcb |= JABBER_CAPS_OMEMO_DEVICELIST_NOTIFY; + + if (!m_bAllowVersionRequests) + jcb &= ~JABBER_CAPS_VERSION; + + XmlNodeIq iq("result", pInfo); + + TiXmlElement *query = iq << XQUERY(JABBER_FEAT_DISCO_INFO); + if (szNode) + query << XATTR("node", szNode); + + CMStringA szName(FORMAT, "Miranda %d.%d.%d.%d", __MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM); + query << XCHILD("identity") << XATTR("category", "client") << XATTR("type", "pc") << XATTR("name", szName); + + for (auto &it : g_JabberFeatCapPairs) + if (jcb & it.jcbCap) + query << XCHILD("feature") << XATTR("var", it.szFeature); + + for (auto &it : m_lstJabberFeatCapPairsDynamic) + if (jcb & it->jcbCap) + query << XCHILD("feature") << XATTR("var", it->szFeature); + + if (m_bAllowVersionRequests && !szNode) { + TiXmlElement *form = query << XCHILDNS("x", JABBER_FEAT_DATA_FORMS) << XATTR("type", "result"); + form << XCHILD("field") << XATTR("var", "FORM_TYPE") << XATTR("type", "hidden") + << XCHILD("value", "urn:xmpp:dataforms:softwareinfo"); + + CJabberClientPartialCaps *pCaps = g_clientCapsManager.GetPartialCaps(JABBER_CAPS_MIRANDA_NODE, m_szFeaturesCrc); + if (pCaps) { + if (m_bShowOSVersion) { + form << XCHILD("field") << XATTR("var", "os") << XCHILD("value", pCaps->GetOs()); + form << XCHILD("field") << XATTR("var", "os_version") << XCHILD("value", pCaps->GetOsVer()); + } + form << XCHILD("field") << XATTR("var", "software") << XCHILD("value", pCaps->GetSoft()); + form << XCHILD("field") << XATTR("var", "software_version") << XCHILD("value", pCaps->GetSoftVer()); + form << XCHILD("field") << XATTR("var", "x-miranda-core-version") << XCHILD("value", pCaps->GetSoftMir()); + } + } + + m_ThreadInfo->send(iq); + return true; +} + void CJabberProto::RequestOldCapsInfo(pResourceStatus &r, const char *fullJid) { CJabberIqInfo *pInfo = AddIQ(&CJabberProto::OnIqResultCapsDiscoInfo, JABBER_IQ_TYPE_GET, fullJid); @@ -325,22 +418,42 @@ void CJabberProto::RequestOldCapsInfo(pResourceStatus &r, const char *fullJid) m_ThreadInfo->send(XmlNodeIq(pInfo) << XQUERY(JABBER_FEAT_DISCO_INFO)); } -void CJabberProto::GetCachedCaps(const char *szNode, const char *szVer, pResourceStatus &r) +void CJabberProto::UpdateFeatHash() { - CMStringA szName(FORMAT, "%s#%s", szNode, szVer); - ptrA szValue(db_get_sa(0, "JabberCaps", szName)); - if (szValue != 0) { - JSONNode root = JSONNode::parse(szValue); - if (root) { - CMStringW wszCaps = root["c"].as_mstring(); - r->m_pCaps = m_clientCapsManager.SetClientCaps(szNode, szVer, nullptr, _wtoi64(wszCaps)); - r->m_pCaps->m_szOs = mir_utf8encodeW(root["o"].as_mstring()); - r->m_pCaps->m_szOsVer = mir_utf8encodeW(root["ov"].as_mstring()); - r->m_pCaps->m_szSoft = mir_utf8encodeW(root["s"].as_mstring()); - r->m_pCaps->m_szSoftVer = mir_utf8encodeW(root["sv"].as_mstring()); - r->m_pCaps->m_szSoftMir = mir_utf8encodeW(root["sm"].as_mstring()); + m_szFeaturesCrc.Empty(); + + JabberCapsBits jcb = JABBER_CAPS_MIRANDA_ALL; + for (auto &it : m_lstJabberFeatCapPairsDynamic) + jcb |= it->jcbCap; + if (!m_bAllowVersionRequests) + jcb &= ~JABBER_CAPS_VERSION; + + if (m_bUseOMEMO) + jcb |= JABBER_CAPS_OMEMO_DEVICELIST_NOTIFY; + + CMStringA feat_buf(FORMAT, "client/pc//Miranda %d.%d.%d.%d<", __MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM); + for (auto &it : g_JabberFeatCapPairs) + if (jcb & it.jcbCap) { + feat_buf.Append(it.szFeature); + feat_buf.AppendChar('<'); } - } + + for (auto &it : m_lstJabberFeatCapPairsDynamic) + if (jcb & it->jcbCap) { + feat_buf.Append(it->szFeature); + feat_buf.AppendChar('<'); + } + + feat_buf.Append("software_version"); feat_buf.AppendChar('<'); + feat_buf.Append(__VERSION_STRING_DOTS); feat_buf.AppendChar('<'); + + feat_buf.Append("x-miranda-core-version"); feat_buf.AppendChar('<'); + feat_buf.Append(szCoreVersion); feat_buf.AppendChar('<'); + + BYTE hash[MIR_SHA1_HASH_SIZE]; + mir_sha1_hash((BYTE *)feat_buf.c_str(), feat_buf.GetLength(), hash); + ptrA szHash(mir_base64_encode(&hash, sizeof(hash))); + m_szFeaturesCrc = szHash; } ///////////////////////////////////////////////////////////////////////////////////////// @@ -349,12 +462,9 @@ void CJabberProto::GetCachedCaps(const char *szNode, const char *szVer, pResourc CJabberClientPartialCaps::CJabberClientPartialCaps(CJabberClientCaps *pParent, const char *szHash, const char *szVer) : m_parent(pParent), m_szHash(mir_strdup(szHash)), - m_szSoftVer(mir_strdup(szVer)), - m_jcbCaps(JABBER_RESOURCE_CAPS_UNINIT), - m_pNext(nullptr), - m_nIqId(-1), - m_dwRequestTime(0) + m_szSoftVer(mir_strdup(szVer)) { + m_iTime = time(0); } CJabberClientPartialCaps::~CJabberClientPartialCaps() @@ -458,61 +568,15 @@ static int sttCompareNodes(const CJabberClientCaps *p1, const CJabberClientCaps return mir_strcmp(p1->GetNode(), p2->GetNode()); } -CJabberClientCapsManager::CJabberClientCapsManager(CJabberProto *proto) : +CJabberClientCapsManager::CJabberClientCapsManager() : m_arCaps(10, sttCompareNodes) { - ppro = proto; - - UpdateFeatHash(); } CJabberClientCapsManager::~CJabberClientCapsManager() { } -void CJabberClientCapsManager::UpdateFeatHash() -{ - m_szFeaturesCrc.Empty(); - - JabberCapsBits jcb = JABBER_CAPS_MIRANDA_ALL; - for (auto &it : ppro->m_lstJabberFeatCapPairsDynamic) - jcb |= it->jcbCap; - if (!ppro->m_bAllowVersionRequests) - jcb &= ~JABBER_CAPS_VERSION; - - if (ppro->m_bUseOMEMO) - jcb |= JABBER_CAPS_OMEMO_DEVICELIST_NOTIFY; - - CMStringA feat_buf(FORMAT, "client/pc//Miranda %d.%d.%d.%d<", __MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM); - for (auto &it : g_JabberFeatCapPairs) - if (jcb & it.jcbCap) { - feat_buf.Append(it.szFeature); - feat_buf.AppendChar('<'); - } - - for (auto &it : ppro->m_lstJabberFeatCapPairsDynamic) - if (jcb & it->jcbCap) { - feat_buf.Append(it->szFeature); - feat_buf.AppendChar('<'); - } - - feat_buf.Append("software_version"); feat_buf.AppendChar('<'); - feat_buf.Append(__VERSION_STRING_DOTS); feat_buf.AppendChar('<'); - - feat_buf.Append("x-miranda-core-version"); feat_buf.AppendChar('<'); - feat_buf.Append(szCoreVersion); feat_buf.AppendChar('<'); - - BYTE hash[MIR_SHA1_HASH_SIZE]; - mir_sha1_hash((BYTE*)feat_buf.c_str(), feat_buf.GetLength(), hash); - ptrA szHash(mir_base64_encode(&hash, sizeof(hash))); - m_szFeaturesCrc = szHash; -} - -const char* CJabberClientCapsManager::GetFeaturesCrc() -{ - return m_szFeaturesCrc.c_str(); -} - CJabberClientCaps* CJabberClientCapsManager::FindClient(const char *szNode) { if (szNode == nullptr) @@ -527,12 +591,12 @@ JabberCapsBits CJabberClientCapsManager::GetClientCaps(const char *szNode, const CJabberClientCaps *pClient = FindClient(szNode); if (!pClient) { lck.unlock(); - ppro->debugLogA("CAPS: get no caps for: %s, %s", szNode, szVer); + Netlib_Logf(0, "CAPS: get no caps for: %s, %s", szNode, szVer); return JABBER_RESOURCE_CAPS_UNINIT; } JabberCapsBits jcbCaps = pClient->GetPartialCaps(szVer); lck.unlock(); - ppro->debugLogA("CAPS: get caps %I64x for: %s, %s", jcbCaps, szNode, szVer); + Netlib_Logf(0, "CAPS: get caps %I64x for: %s, %s", jcbCaps, szNode, szVer); return jcbCaps; } @@ -546,7 +610,7 @@ CJabberClientPartialCaps* CJabberClientCapsManager::GetPartialCaps(const char *s CJabberClientPartialCaps* CJabberClientCapsManager::SetClientCaps(const char *szNode, const char *szHash, const char *szVer, JabberCapsBits jcbCaps, int nIqId) { mir_cslockfull lck(m_cs); - CJabberClientCaps *pClient = FindClient(szNode); + auto *pClient = FindClient(szNode); if (!pClient) { pClient = new CJabberClientCaps(szNode); m_arCaps.insert(pClient); @@ -554,97 +618,87 @@ CJabberClientPartialCaps* CJabberClientCapsManager::SetClientCaps(const char *sz CJabberClientPartialCaps *res = pClient->SetPartialCaps(szHash, szVer, jcbCaps, nIqId); lck.unlock(); - ppro->debugLogA("CAPS: set caps %I64x for: %s#%s => [%s]", jcbCaps, szHash, szNode, szVer); + Netlib_Logf(0, "CAPS: set caps %I64x for: %s#%s => [%s]", jcbCaps, szHash, szNode, szVer); return res; } -bool CJabberClientCapsManager::HandleInfoRequest(const TiXmlElement*, CJabberIqInfo *pInfo, const char *szNode) +///////////////////////////////////////////////////////////////////////////////////////// + +static char *str2buf(const std::string str) { - JabberCapsBits jcb = 0; + return (str.empty()) ? nullptr : mir_strdup(str.c_str()); +} - if (szNode) { - char szExtCap[512], szExtCapWHash[560]; - mir_snprintf(szExtCap, "%s#%s", JABBER_CAPS_MIRANDA_NODE, m_szFeaturesCrc.c_str()); - if (!mir_strcmp(szExtCap, szNode)) { - szNode = nullptr; - goto LBL_All; - } +void CJabberClientCapsManager::Load() +{ + int fileId = _wopen(VARSW(L"%miranda_userdata%\\jabberCaps.json"), _O_BINARY | _O_RDONLY); + if (fileId == -1) + return; - for (auto &it : g_JabberFeatCapPairsExt) { - if (!it.Valid()) - continue; + size_t dwFileLength = _filelength(fileId), dwReadLen; + ptrA szBuf((char *)mir_alloc(dwFileLength + 1)); + dwReadLen = _read(fileId, szBuf, (unsigned)dwFileLength); + _close(fileId); + if (dwFileLength != dwReadLen) + return; - // TODO: something better here - mir_snprintf(szExtCap, "%s#%s", JABBER_CAPS_MIRANDA_NODE, it.szFeature); - mir_snprintf(szExtCapWHash, "%s %s", szExtCap, m_szFeaturesCrc.c_str()); - if (!mir_strcmp(szNode, szExtCap) || !mir_strcmp(szNode, szExtCapWHash)) { - jcb = it.jcbCap; - break; - } - } + szBuf[dwFileLength] = 0; - // check features registered through IJabberNetInterface::RegisterFeature() and IJabberNetInterface::AddFeatures() - for (auto &it : ppro->m_lstJabberFeatCapPairsDynamic) { - // TODO: something better here - mir_snprintf(szExtCap, "%s#%s", JABBER_CAPS_MIRANDA_NODE, it->szExt); - mir_snprintf(szExtCapWHash, "%s %s", szExtCap, m_szFeaturesCrc.c_str()); - if (!mir_strcmp(szNode, szExtCap) || !mir_strcmp(szNode, szExtCapWHash)) { - jcb = it->jcbCap; - break; - } + JSONNode root = JSONNode::parse(szBuf); + if (!root) + return; + + for (auto &node : root) { + std::string szNode = node["node"].as_string(); + auto *pClient = FindClient(szNode.c_str()); + if (!pClient) { + pClient = new CJabberClientCaps(szNode.c_str()); + m_arCaps.insert(pClient); } - // unknown node, not XEP-0115 request - if (!jcb) - return false; - } - else { -LBL_All: - jcb = JABBER_CAPS_MIRANDA_ALL; - for (auto &it : ppro->m_lstJabberFeatCapPairsDynamic) - jcb |= it->jcbCap; + for (auto &ver : node["versions"]) { + std::string szVer = ver["ver"].as_string(); + std::string szHash = ver["hash"].as_string(); + JabberCapsBits jcbCaps = _atoi64(ver["caps"].as_string().c_str()); + + auto *res = pClient->SetPartialCaps(szHash.c_str(), szVer.c_str(), jcbCaps); + res->m_iTime = ver["time"].as_int(); + res->m_szOs = str2buf(ver["os"].as_string()); + res->m_szOsVer = str2buf(ver["osver"].as_string()); + res->m_szSoft = str2buf(ver["soft"].as_string()); + res->m_szSoftVer = str2buf(ver["softver"].as_string()); + res->m_szSoftMir = str2buf(ver["softmir"].as_string()); + } } +} - if (ppro->m_bUseOMEMO) - jcb |= JABBER_CAPS_OMEMO_DEVICELIST_NOTIFY; - - if (!ppro->m_bAllowVersionRequests) - jcb &= ~JABBER_CAPS_VERSION; - - XmlNodeIq iq("result", pInfo); - - TiXmlElement *query = iq << XQUERY(JABBER_FEAT_DISCO_INFO); - if (szNode) - query << XATTR("node", szNode); +void CJabberClientCapsManager::Save() +{ + JSONNode root(JSON_ARRAY); + int iFilterTime = time(0) - 30 * 86400; // month ago - CMStringA szName(FORMAT, "Miranda %d.%d.%d.%d", __MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM); - query << XCHILD("identity") << XATTR("category", "client") << XATTR("type", "pc") << XATTR("name", szName); + for (auto &it : m_arCaps) { + JSONNode versions(JSON_ARRAY); versions.set_name("versions"); + for (auto *p = it->GetFirst(); p != nullptr; p = p->GetNext()) { + if (p->m_iTime < iFilterTime) + continue; - for (auto &it : g_JabberFeatCapPairs) - if (jcb & it.jcbCap) - query << XCHILD("feature") << XATTR("var", it.szFeature); + JSONNode ver; + ver << CHAR_PARAM("hash", p->GetHash()) << INT64_PARAM("caps", p->GetCaps()) << INT_PARAM("time", p->m_iTime) + << CHAR_PARAM("os", p->GetOs()) << CHAR_PARAM("osver", p->GetOsVer()) + << CHAR_PARAM("soft", p->GetSoft()) << CHAR_PARAM("softver", p->GetSoftVer()) << CHAR_PARAM("softmir", p->GetSoftMir()); + versions.push_back(ver); + } - for (auto &it : ppro->m_lstJabberFeatCapPairsDynamic) - if (jcb & it->jcbCap) - query << XCHILD("feature") << XATTR("var", it->szFeature); + JSONNode node; node << CHAR_PARAM("node", it->GetNode()) << versions; + root << node; + } - if (ppro->m_bAllowVersionRequests && !szNode) { - TiXmlElement *form = query << XCHILDNS("x", JABBER_FEAT_DATA_FORMS) << XATTR("type", "result"); - form << XCHILD("field") << XATTR("var", "FORM_TYPE") << XATTR("type", "hidden") - << XCHILD("value", "urn:xmpp:dataforms:softwareinfo"); + std::string szBody = root.write_formatted(); - CJabberClientPartialCaps *pCaps = GetPartialCaps(JABBER_CAPS_MIRANDA_NODE, m_szFeaturesCrc); - if (pCaps) { - if (ppro->m_bShowOSVersion) { - form << XCHILD("field") << XATTR("var", "os") << XCHILD("value", pCaps->GetOs()); - form << XCHILD("field") << XATTR("var", "os_version") << XCHILD("value", pCaps->GetOsVer()); - } - form << XCHILD("field") << XATTR("var", "software") << XCHILD("value", pCaps->GetSoft()); - form << XCHILD("field") << XATTR("var", "software_version") << XCHILD("value", pCaps->GetSoftVer()); - form << XCHILD("field") << XATTR("var", "x-miranda-core-version") << XCHILD("value", pCaps->GetSoftMir()); - } + int fileId = _wopen(VARSW(L"%miranda_userdata%\\jabberCaps.json"), _O_CREAT | _O_TRUNC | _O_WRONLY, _S_IREAD | _S_IWRITE); + if (fileId != -1) { + _write(fileId, szBody.c_str(), (unsigned)szBody.length()); + _close(fileId); } - - ppro->m_ThreadInfo->send(iq); - return true; } diff --git a/protocols/JabberG/src/jabber_caps.h b/protocols/JabberG/src/jabber_caps.h index bc8e79bdb3..b78f64ebb9 100755 --- a/protocols/JabberG/src/jabber_caps.h +++ b/protocols/JabberG/src/jabber_caps.h @@ -261,14 +261,15 @@ typedef unsigned __int64 JabberCapsBits; class CJabberClientPartialCaps { friend struct CJabberProto; + friend class CJabberClientCapsManager; ptrA m_szHash, m_szOs, m_szOsVer, m_szSoft, m_szSoftVer, m_szSoftMir; - JabberCapsBits m_jcbCaps; - int m_nIqId; - DWORD m_dwRequestTime; + JabberCapsBits m_jcbCaps = JABBER_RESOURCE_CAPS_UNINIT; + int m_nIqId = -1, m_iTime; + DWORD m_dwRequestTime = 0; class CJabberClientCaps *m_parent; - CJabberClientPartialCaps *m_pNext; + CJabberClientPartialCaps *m_pNext = nullptr; public: CJabberClientPartialCaps(CJabberClientCaps *pParent, const char *szHash, const char *szVer); @@ -314,7 +315,8 @@ public: JabberCapsBits GetPartialCaps(const char *szVer); CJabberClientPartialCaps* SetPartialCaps(const char *szHash, const char *szVer, JabberCapsBits jcbCaps, int nIqId = -1); - __inline char* GetNode() const { return m_szNode; } + __inline char *GetNode() const { return m_szNode; } + __inline CJabberClientPartialCaps *GetFirst() const { return m_pCaps; } }; __inline const char* CJabberClientPartialCaps::GetNode() const { return m_parent->GetNode(); } @@ -324,29 +326,20 @@ class CJabberClientCapsManager mir_cs m_cs; OBJLIST m_arCaps; - CJabberProto *ppro; - CMStringA m_szFeaturesCrc; - protected: CJabberClientCaps* FindClient(const char *szNode); public: - CJabberClientCapsManager(CJabberProto *proto); + CJabberClientCapsManager(); ~CJabberClientCapsManager(); - const char* GetFeaturesCrc(); - void UpdateFeatHash(); + void Load(); + void Save(); JabberCapsBits GetClientCaps(const char *szNode, const char *szHash); CJabberClientPartialCaps* GetPartialCaps(const char *szNode, const char *szHash); CJabberClientPartialCaps* SetClientCaps(const char *szNode, const char *szHash, const char *szVer, JabberCapsBits jcbCaps, int nIqId = -1); - __inline CJabberClientPartialCaps* SetOwnCaps(const char *szNode, const char *szVer, JabberCapsBits jcbCaps, int nIqId = -1) - { - return SetClientCaps(szNode, m_szFeaturesCrc, szVer, jcbCaps, nIqId); - } - - bool HandleInfoRequest(const TiXmlElement *iqNode, CJabberIqInfo *pInfo, const char *szNode); }; struct JabberFeatCapPair diff --git a/protocols/JabberG/src/jabber_iq_handlers.cpp b/protocols/JabberG/src/jabber_iq_handlers.cpp index 56a1907668..692130c27b 100644 --- a/protocols/JabberG/src/jabber_iq_handlers.cpp +++ b/protocols/JabberG/src/jabber_iq_handlers.cpp @@ -352,7 +352,7 @@ bool CJabberProto::OnHandleDiscoInfoRequest(const TiXmlElement *iqNode, CJabberI const char *szNode = XmlGetAttr(pInfo->GetChildNode(), "node"); // caps hack - if (m_clientCapsManager.HandleInfoRequest(iqNode, pInfo, szNode)) + if (HandleCapsInfoRequest(iqNode, pInfo, szNode)) return true; // ad-hoc hack: diff --git a/protocols/JabberG/src/jabber_opt.cpp b/protocols/JabberG/src/jabber_opt.cpp index 09039d2989..509f4c94b5 100755 --- a/protocols/JabberG/src/jabber_opt.cpp +++ b/protocols/JabberG/src/jabber_opt.cpp @@ -830,7 +830,7 @@ public: m_proto->m_omemo.init(); else m_proto->m_omemo.deinit(); - m_proto->m_clientCapsManager.UpdateFeatHash(); + m_proto->UpdateFeatHash(); m_proto->SendPresence(m_proto->m_iStatus, true); return true; } diff --git a/protocols/JabberG/src/jabber_proto.cpp b/protocols/JabberG/src/jabber_proto.cpp index 57c31e7688..ddadc6eb34 100755 --- a/protocols/JabberG/src/jabber_proto.cpp +++ b/protocols/JabberG/src/jabber_proto.cpp @@ -64,7 +64,6 @@ CJabberProto::CJabberProto(const char *aProtoName, const wchar_t *aUserName) : m_presenceManager(this), m_sendManager(this), m_adhocManager(this), - m_clientCapsManager(this), m_privacyListManager(this), m_privacyMenuServiceAllocated(-1), m_priorityMenuVal(0), @@ -191,6 +190,7 @@ CJabberProto::CJabberProto(const char *aProtoName, const wchar_t *aUserName) : m_messageManager.FillPermanentHandlers(); m_adhocManager.FillDefaultNodes(); + UpdateFeatHash(); AddDefaultCaps(); IconsInit(); @@ -255,7 +255,6 @@ CJabberProto::~CJabberProto() mir_free(it->szDescription); delete it; } - } //////////////////////////////////////////////////////////////////////////////////////// diff --git a/protocols/JabberG/src/jabber_proto.h b/protocols/JabberG/src/jabber_proto.h index b7bd700ffb..5306832189 100755 --- a/protocols/JabberG/src/jabber_proto.h +++ b/protocols/JabberG/src/jabber_proto.h @@ -274,7 +274,6 @@ struct CJabberProto : public PROTO, public IJabberInterface CJabberPresenceManager m_presenceManager; // manager of stanzas and their handlers CJabberSendManager m_sendManager; // manager of outgoing stanza handlers CJabberAdhocManager m_adhocManager; - CJabberClientCapsManager m_clientCapsManager; CPrivacyListManager m_privacyListManager; CJabberSDManager m_SDManager; @@ -399,9 +398,12 @@ struct CJabberProto : public PROTO, public IJabberInterface //---- jabber_caps.cpp --------------------------------------------------------------- + CMStringA m_szFeaturesCrc; + void AddDefaultCaps(); + bool HandleCapsInfoRequest(const TiXmlElement *iqNode, CJabberIqInfo *pInfo, const char *szNode); void RequestOldCapsInfo(pResourceStatus &r, const char *fullJid); - void GetCachedCaps(const char *szNode, const char *szVer, class pResourceStatus &r); + void UpdateFeatHash(); JabberCapsBits GetTotalJidCapabilities(const char *jid); JabberCapsBits GetResourceCapabilities(const char *jid); diff --git a/protocols/JabberG/src/jabber_thread.cpp b/protocols/JabberG/src/jabber_thread.cpp index 432510910c..52d7a462f6 100755 --- a/protocols/JabberG/src/jabber_thread.cpp +++ b/protocols/JabberG/src/jabber_thread.cpp @@ -1432,14 +1432,11 @@ void CJabberProto::OnProcessPresenceCapabilites(const TiXmlElement *node, pResou if (szHash == nullptr) { // old version BYTE hashOut[MIR_SHA1_HASH_SIZE]; mir_sha1_hash((BYTE*)szVer, mir_strlen(szVer), hashOut); - char szHashOut[MIR_SHA1_HASH_SIZE * 2 + 1]; - bin2hex(hashOut, _countof(hashOut), szHashOut); - r->m_pCaps = m_clientCapsManager.GetPartialCaps(szNode, szHashOut); - if (r->m_pCaps == nullptr) - GetCachedCaps(szNode, szHashOut, r); + char szHashOut[MIR_SHA1_HASH_SIZE*2 + 1]; + r->m_pCaps = g_clientCapsManager.GetPartialCaps(szNode, bin2hex(hashOut, _countof(hashOut), szHashOut)); if (r->m_pCaps == nullptr) { - r->m_pCaps = m_clientCapsManager.SetClientCaps(szNode, szHashOut, szVer, JABBER_RESOURCE_CAPS_UNINIT); + r->m_pCaps = g_clientCapsManager.SetClientCaps(szNode, szHashOut, szVer, JABBER_RESOURCE_CAPS_UNINIT); RequestOldCapsInfo(r, from); } @@ -1448,12 +1445,9 @@ void CJabberProto::OnProcessPresenceCapabilites(const TiXmlElement *node, pResou UpdateMirVer(hContact, r); } else { - r->m_pCaps = m_clientCapsManager.GetPartialCaps(szNode, szVer); - if (r->m_pCaps == nullptr) - GetCachedCaps(szNode, szVer, r); - + r->m_pCaps = g_clientCapsManager.GetPartialCaps(szNode, szVer); if (r->m_pCaps == nullptr) { - r->m_pCaps = m_clientCapsManager.SetClientCaps(szNode, szVer, "", JABBER_RESOURCE_CAPS_UNINIT); + r->m_pCaps = g_clientCapsManager.SetClientCaps(szNode, szVer, "", JABBER_RESOURCE_CAPS_UNINIT); GetResourceCapabilities(from, r); } } diff --git a/protocols/JabberG/src/jabber_util.cpp b/protocols/JabberG/src/jabber_util.cpp index 5c8e945453..6e69251042 100755 --- a/protocols/JabberG/src/jabber_util.cpp +++ b/protocols/JabberG/src/jabber_util.cpp @@ -388,7 +388,7 @@ void CJabberProto::SendPresenceTo(int status, const char *to, const TiXmlElement // XEP-0115:Entity Capabilities if (m_bAllowVersionRequests) { TiXmlElement *c = p << XCHILDNS("c", JABBER_FEAT_ENTITY_CAPS) << XATTR("hash", "sha-1") - << XATTR("node", JABBER_CAPS_MIRANDA_NODE) << XATTR("ver", m_clientCapsManager.GetFeaturesCrc()); + << XATTR("node", JABBER_CAPS_MIRANDA_NODE) << XATTR("ver", m_szFeaturesCrc); LIST arrExtCaps(5); if (g_plugin.bSecureIM) diff --git a/protocols/JabberG/src/stdafx.h b/protocols/JabberG/src/stdafx.h index 51f577b5b9..78f7a10173 100755 --- a/protocols/JabberG/src/stdafx.h +++ b/protocols/JabberG/src/stdafx.h @@ -324,6 +324,8 @@ struct CJabberHttpAuthParams #include "jabber_caps.h" +extern CJabberClientCapsManager g_clientCapsManager; + #define JABBER_LOGIN_ROSTER 0x0001 #define JABBER_LOGIN_BOOKMARKS 0x0002 #define JABBER_LOGIN_SERVERINFO 0x0004 -- cgit v1.2.3