diff options
Diffstat (limited to 'protocols/JabberG/src')
| -rwxr-xr-x | protocols/JabberG/src/jabber.cpp | 9 | ||||
| -rw-r--r-- | protocols/JabberG/src/jabber_api.cpp | 2 | ||||
| -rwxr-xr-x | protocols/JabberG/src/jabber_caps.cpp | 344 | ||||
| -rwxr-xr-x | protocols/JabberG/src/jabber_caps.h | 27 | ||||
| -rw-r--r-- | protocols/JabberG/src/jabber_iq_handlers.cpp | 2 | ||||
| -rwxr-xr-x | protocols/JabberG/src/jabber_opt.cpp | 2 | ||||
| -rwxr-xr-x | protocols/JabberG/src/jabber_proto.cpp | 3 | ||||
| -rwxr-xr-x | protocols/JabberG/src/jabber_proto.h | 6 | ||||
| -rwxr-xr-x | protocols/JabberG/src/jabber_thread.cpp | 16 | ||||
| -rwxr-xr-x | protocols/JabberG/src/jabber_util.cpp | 2 | ||||
| -rwxr-xr-x | protocols/JabberG/src/stdafx.h | 2 | 
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
  | 
