summaryrefslogtreecommitdiff
path: root/protocols/JabberG/src
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2020-03-02 22:40:54 +0300
committerGeorge Hazan <ghazan@miranda.im>2020-03-02 22:41:01 +0300
commit5ce5965da1db4cfd5e39a89b0dd922e2fe6cf59e (patch)
tree4e21770091e68fdaf8a423546cae97579ab10585 /protocols/JabberG/src
parent5496a4810b112dfbb5acfdff08de685dbd48fd40 (diff)
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
Diffstat (limited to 'protocols/JabberG/src')
-rwxr-xr-xprotocols/JabberG/src/jabber.cpp9
-rw-r--r--protocols/JabberG/src/jabber_api.cpp2
-rwxr-xr-xprotocols/JabberG/src/jabber_caps.cpp344
-rwxr-xr-xprotocols/JabberG/src/jabber_caps.h27
-rw-r--r--protocols/JabberG/src/jabber_iq_handlers.cpp2
-rwxr-xr-xprotocols/JabberG/src/jabber_opt.cpp2
-rwxr-xr-xprotocols/JabberG/src/jabber_proto.cpp3
-rwxr-xr-xprotocols/JabberG/src/jabber_proto.h6
-rwxr-xr-xprotocols/JabberG/src/jabber_thread.cpp16
-rwxr-xr-xprotocols/JabberG/src/jabber_util.cpp2
-rwxr-xr-xprotocols/JabberG/src/stdafx.h2
11 files changed, 234 insertions, 181 deletions
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<CJabberClientCaps> 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<CJabberProto>, public IJabberInterface
CJabberPresenceManager m_presenceManager; // manager of <presence> 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<CJabberProto>, 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<char> 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