diff options
| author | George Hazan <ghazan@miranda.im> | 2019-02-25 15:16:23 +0300 | 
|---|---|---|
| committer | George Hazan <ghazan@miranda.im> | 2019-02-25 15:16:23 +0300 | 
| commit | 899e841aea8e54721ce9771780b05a07de05ce71 (patch) | |
| tree | a8d87fb94ccb1534a41fbb711053b5e70bdec420 /protocols/JabberG | |
| parent | 94cf6af342027cfaf486eefaad9f6f1450ecb8f0 (diff) | |
Jabber:
- obsolete class Xpath removed, its functionality replaced with helpers & iterators;
- JABBER_FEAT_BIND added to enchance code reading & understanding;
- unused function CNoteItem::AddNote removed;
- fix for improper jabber:x:last behavior
Diffstat (limited to 'protocols/JabberG')
| -rwxr-xr-x | protocols/JabberG/src/jabber_caps.cpp | 41 | ||||
| -rwxr-xr-x | protocols/JabberG/src/jabber_caps.h | 1 | ||||
| -rwxr-xr-x | protocols/JabberG/src/jabber_iqid.cpp | 75 | ||||
| -rw-r--r-- | protocols/JabberG/src/jabber_notes.cpp | 14 | ||||
| -rw-r--r-- | protocols/JabberG/src/jabber_notes.h | 1 | ||||
| -rwxr-xr-x | protocols/JabberG/src/jabber_strm_mgmt.cpp | 2 | ||||
| -rwxr-xr-x | protocols/JabberG/src/jabber_thread.cpp | 10 | ||||
| -rw-r--r-- | protocols/JabberG/src/jabber_xml.cpp | 188 | ||||
| -rw-r--r-- | protocols/JabberG/src/jabber_xml.h | 133 | ||||
| -rw-r--r-- | protocols/JabberG/src/jabber_xstatus.cpp | 2 | 
10 files changed, 74 insertions, 393 deletions
| diff --git a/protocols/JabberG/src/jabber_caps.cpp b/protocols/JabberG/src/jabber_caps.cpp index 305cf845eb..94e949cbbf 100755 --- a/protocols/JabberG/src/jabber_caps.cpp +++ b/protocols/JabberG/src/jabber_caps.cpp @@ -161,25 +161,30 @@ void CJabberProto::OnIqResultCapsDiscoInfo(const TiXmlElement*, CJabberIqInfo *p  		}
  		for (auto *xform : TiXmlFilter(query, "x")) {
 -			const char *szFormTypeValue = XPath(xform, "field[@var='FORM_TYPE']/value");
 -			if (!mir_strcmp(szFormTypeValue, "urn:xmpp:dataforms:softwareinfo")) {
 -				JSONNode root;
 -				if (pCaps->m_szOs = mir_strdup(XPath(xform, "field[@var='os']/value")))
 -					root.push_back(JSONNode("o", pCaps->m_szOs.get()));
 -				if (pCaps->m_szOsVer = mir_strdup(XPath(xform, "field[@var='os_version']/value")))
 -					root.push_back(JSONNode("ov", pCaps->m_szOsVer.get()));
 -				if (pCaps->m_szSoft = mir_strdup(XPath(xform, "field[@var='software']/value")))
 -					root.push_back(JSONNode("s", pCaps->m_szSoft.get()));
 -				if (pCaps->m_szSoftVer = mir_strdup(XPath(xform, "field[@var='software_version']/value")))
 -					root.push_back(JSONNode("sv", pCaps->m_szSoftVer.get()));
 -				if (pCaps->m_szSoftMir = mir_strdup(XPath(xform, "field[@var='x-miranda-core-version']/value")))
 -					root.push_back(JSONNode("sm", pCaps->m_szSoftMir.get()));
 -				root.push_back(JSONNode("c", CMStringA(FORMAT, "%lld", jcbCaps)));
 -
 -				CMStringA szName(FORMAT, "%s#%s", pCaps->GetNode(), pCaps->GetHash());
 -				json_string szValue = root.write();
 -				db_set_s(0, "JabberCaps", szName, szValue.c_str());
 +			// check that this is a form of required type
 +			auto *formType = XmlGetChildText(XmlGetChildByTag(xform, "field", "var", "FORM_TYPE"), "value");
 +			if (!formType || mir_strcmp(formType, "urn:xmpp:dataforms:softwareinfo"))
 +				continue;
 +
 +			JSONNode root;
 +			for (auto *field : TiXmlFilter(xform, "field")) {
 +				const char *fieldName = field->Attribute("var"), *fieldValue = XmlGetChildText(field, "value");
 +				if (!mir_strcmp(fieldName, "os"))
 +					root.push_back(JSONNode("o", pCaps->m_szOs = mir_strdup(fieldValue)));
 +				else if (!mir_strcmp(fieldName, "os_version"))
 +					root.push_back(JSONNode("ov", pCaps->m_szOsVer = mir_strdup(fieldValue)));
 +				else if (!mir_strcmp(fieldName, "software"))
 +					root.push_back(JSONNode("s", pCaps->m_szSoft = mir_strdup(fieldValue)));
 +				else if (!mir_strcmp(fieldName, "software_version"))
 +					root.push_back(JSONNode("sv", pCaps->m_szSoftVer = mir_strdup(fieldValue)));
 +				else if (!mir_strcmp(fieldName, "x-miranda-core-version"))
 +					root.push_back(JSONNode("sm", pCaps->m_szSoftMir = mir_strdup(fieldValue)));
  			}
 +			root.push_back(JSONNode("c", CMStringA(FORMAT, "%lld", jcbCaps)));
 +
 +			CMStringA szName(FORMAT, "%s#%s", pCaps->GetNode(), pCaps->GetHash());
 +			json_string szValue = root.write();
 +			db_set_s(0, "JabberCaps", szName, szValue.c_str());
  		}
  		pCaps->SetCaps(jcbCaps, pInfo->GetIqId());
 diff --git a/protocols/JabberG/src/jabber_caps.h b/protocols/JabberG/src/jabber_caps.h index 4c8e985990..683b44b897 100755 --- a/protocols/JabberG/src/jabber_caps.h +++ b/protocols/JabberG/src/jabber_caps.h @@ -132,6 +132,7 @@ typedef unsigned __int64 JabberCapsBits;  #define JABBER_CAPS_ARCHIVE_MANAGE              ((JabberCapsBits)1<<35)
  #define JABBER_FEAT_CAPTCHA                     "urn:xmpp:captcha"
 +#define JABBER_FEAT_BIND                        "urn:ietf:params:xml:ns:xmpp-bind"
  #define JABBER_FEAT_ATTENTION                   "urn:xmpp:attention:0"
  #define JABBER_CAPS_ATTENTION                   ((JabberCapsBits)1<<36)
 diff --git a/protocols/JabberG/src/jabber_iqid.cpp b/protocols/JabberG/src/jabber_iqid.cpp index 627f404a8a..ad5b04c556 100755 --- a/protocols/JabberG/src/jabber_iqid.cpp +++ b/protocols/JabberG/src/jabber_iqid.cpp @@ -82,14 +82,14 @@ void CJabberProto::OnIqResultServerDiscoInfo(const TiXmlElement *iqNode, CJabber  void CJabberProto::OnIqResultNestedRosterGroups(const TiXmlElement *iqNode, CJabberIqInfo *pInfo)
  {
 -	const char *szGroupDelimeter = nullptr;
 +	const char *szGroupDelimiter = nullptr;
  	bool bPrivateStorageSupport = false;
  	if (iqNode && pInfo->GetIqType() == JABBER_IQ_TYPE_RESULT) {
  		bPrivateStorageSupport = true;
 -		szGroupDelimeter = XPathFmt(iqNode, "query[@xmlns='%s']/roster[@xmlns='%s']", JABBER_FEAT_PRIVATE_STORAGE, JABBER_FEAT_NESTED_ROSTER_GROUPS);
 -		if (szGroupDelimeter && !szGroupDelimeter[0])
 -			szGroupDelimeter = nullptr; // "" as roster delimeter is not supported :)
 +		auto *xmlDelimiter = XmlGetChildByTag(XmlGetChildByTag(iqNode, "query", "xmlns", JABBER_FEAT_PRIVATE_STORAGE), "roster", "xmlns", JABBER_FEAT_NESTED_ROSTER_GROUPS);
 +		if (xmlDelimiter)
 +			szGroupDelimiter = xmlDelimiter->GetText();
  	}
  	// global fuckup
 @@ -97,13 +97,13 @@ void CJabberProto::OnIqResultNestedRosterGroups(const TiXmlElement *iqNode, CJab  		return;
  	// is our default delimiter?
 -	if ((!szGroupDelimeter && bPrivateStorageSupport) || (szGroupDelimeter && mir_strcmp(szGroupDelimeter, "\\")))
 +	if ((!szGroupDelimiter && bPrivateStorageSupport) || (szGroupDelimiter && mir_strcmp(szGroupDelimiter, "\\")))
  		m_ThreadInfo->send(
  			XmlNodeIq("set", SerialNext()) << XQUERY(JABBER_FEAT_PRIVATE_STORAGE)
  				<< XCHILD("roster", "\\") << XATTR("xmlns", JABBER_FEAT_NESTED_ROSTER_GROUPS));
  	// roster request
 -	char *szUserData = mir_strdup(szGroupDelimeter ? szGroupDelimeter : "\\");
 +	char *szUserData = mir_strdup(szGroupDelimiter ? szGroupDelimiter : "\\");
  	m_ThreadInfo->send(
  		XmlNodeIq(AddIQ(&CJabberProto::OnIqResultGetRoster, JABBER_IQ_TYPE_GET, nullptr, 0, -1, (void*)szUserData))
  			<< XCHILDNS("query", JABBER_FEAT_IQ_ROSTER));
 @@ -293,7 +293,7 @@ void CJabberProto::OnIqResultBind(const TiXmlElement *iqNode, CJabberIqInfo *pIn  	if (!m_ThreadInfo || !iqNode)
  		return;
  	if (pInfo->GetIqType() == JABBER_IQ_TYPE_RESULT) {
 -		const char *szJid = XPath(iqNode, "bind[@xmlns='urn:ietf:params:xml:ns:xmpp-bind']/jid");
 +		const char *szJid = XmlGetChildText(XmlGetChildByTag(iqNode, "bind", "xmlns", JABBER_FEAT_BIND), "jid");
  		if (szJid) {
  			if (!strncmp(m_ThreadInfo->fullJID, szJid, _countof(m_ThreadInfo->fullJID)))
  				debugLogA("Result Bind: %s confirmed ", m_ThreadInfo->fullJID);
 @@ -351,7 +351,7 @@ void CJabberProto::GroupchatJoinByHContact(MCONTACT hContact, bool autojoin)  void CJabberProto::OnIqResultGetRoster(const TiXmlElement *iqNode, CJabberIqInfo *pInfo)
  {
  	debugLogA("<iq/> iqIdGetRoster");
 -	ptrA szGroupDelimeter((char *)pInfo->GetUserData());
 +	ptrA szGroupDelimiter((char *)pInfo->GetUserData());
  	if (pInfo->GetIqType() != JABBER_IQ_TYPE_RESULT)
  		return;
 @@ -362,8 +362,8 @@ void CJabberProto::OnIqResultGetRoster(const TiXmlElement *iqNode, CJabberIqInfo  	if (mir_strcmp(queryNode->Attribute("xmlns"), JABBER_FEAT_IQ_ROSTER))
  		return;
 -	if (!mir_strcmp(szGroupDelimeter, "\\"))
 -		szGroupDelimeter = nullptr;
 +	if (!mir_strcmp(szGroupDelimiter, "\\"))
 +		szGroupDelimiter = nullptr;
  	LIST<void> chatRooms(10);
  	OBJLIST<JABBER_HTTP_AVATARS> *httpavatars = new OBJLIST<JABBER_HTTP_AVATARS>(20, JABBER_HTTP_AVATARS::compare);
 @@ -402,10 +402,10 @@ void CJabberProto::OnIqResultGetRoster(const TiXmlElement *iqNode, CJabberIqInfo  		replaceStr(item->group, XmlGetChildText(itemNode, "group"));
  		// check group delimiters
 -		if (item->group && szGroupDelimeter) {
 -			while (char *szPos = strstr(item->group, szGroupDelimeter)) {
 +		if (item->group && szGroupDelimiter) {
 +			while (char *szPos = strstr(item->group, szGroupDelimiter)) {
  				*szPos = 0;
 -				szPos += mir_strlen(szGroupDelimeter);
 +				szPos += mir_strlen(szGroupDelimiter);
  				CMStringA szNewGroup(FORMAT, "%s\\%s", item->group, szPos);
  				replaceStr(item->group, szNewGroup.Detach());
  			}
 @@ -491,8 +491,8 @@ void CJabberProto::OnIqResultGetRoster(const TiXmlElement *iqNode, CJabberIqInfo  	UI_SAFE_NOTIFY(m_pDlgServiceDiscovery, WM_JABBER_TRANSPORT_REFRESH);
 -	if (szGroupDelimeter)
 -		mir_free(szGroupDelimeter);
 +	if (szGroupDelimiter)
 +		mir_free(szGroupDelimiter);
  	OnProcessLoginRq(m_ThreadInfo, JABBER_LOGIN_ROSTER);
  	RebuildInfoFrame();
 @@ -1424,8 +1424,8 @@ void CJabberProto::OnIqResultDiscoBookmarks(const TiXmlElement *iqNode, CJabberI  						item->name = mir_utf8decodeW(itemNode->Attribute("name"));
  						item->type = mir_strdup("conference");
  						item->bUseResource = true;
 -						item->nick = mir_strdup(XPath(itemNode, "nick"));
 -						item->password = mir_strdup(XPath(itemNode, "password"));
 +						item->nick = mir_strdup(XmlGetChildText(itemNode, "nick"));
 +						item->password = mir_strdup(XmlGetChildText(itemNode, "password"));
  						const char *autoJ = itemNode->Attribute("autojoin");
  						if (autoJ != nullptr)
 @@ -1515,7 +1515,7 @@ void CJabberProto::OnIqResultLastActivity(const TiXmlElement *iqNode, CJabberIqI  	time_t lastActivity = -1;
  	if (pInfo->m_nIqType == JABBER_IQ_TYPE_RESULT) {
  		if (auto *xmlLast = XmlGetChildByTag(iqNode, "query", "xmlns", JABBER_FEAT_LAST_ACTIVITY)) {
 -			int nSeconds = XmlGetChildInt(xmlLast, "seconds");
 +			int nSeconds = xmlLast->IntAttribute("seconds");
  			if (nSeconds > 0)
  				lastActivity = time(0) - nSeconds;
 @@ -1536,24 +1536,27 @@ void CJabberProto::OnIqResultEntityTime(const TiXmlElement *pIqNode, CJabberIqIn  		return;
  	if (pInfo->m_nIqType == JABBER_IQ_TYPE_RESULT) {
 -		const char *szTzo = XPathFmt(pIqNode, "time[@xmlns='%s']/tzo", JABBER_FEAT_ENTITY_TIME);
 -		if (szTzo && szTzo[0]) {
 -			const char *szMin = strchr(szTzo, ':');
 -			int nTz = atoi(szTzo) * -2;
 -			nTz += (nTz < 0 ? -1 : 1) * (szMin ? atoi(szMin + 1) / 30 : 0);
 -
 -			TIME_ZONE_INFORMATION tzinfo;
 -			if (GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_DAYLIGHT)
 -				nTz -= tzinfo.DaylightBias / 30;
 -
 -			setByte(pInfo->m_hContact, "Timezone", (signed char)nTz);
 -
 -			const char *szTz = XPathFmt(pIqNode, "time[@xmlns='%s']/tz", JABBER_FEAT_ENTITY_TIME);
 -			if (szTz)
 -				setUString(pInfo->m_hContact, "TzName", szTz);
 -			else
 -				delSetting(pInfo->m_hContact, "TzName");
 -			return;
 +		auto *xmlTime = XmlGetChildByTag(pIqNode, "time", "xmlns", JABBER_FEAT_ENTITY_TIME);
 +		if (xmlTime) {
 +			const char *szTzo = XmlGetChildText(xmlTime, "tzo");
 +			if (szTzo && szTzo[0]) {
 +				const char *szMin = strchr(szTzo, ':');
 +				int nTz = atoi(szTzo) * -2;
 +				nTz += (nTz < 0 ? -1 : 1) * (szMin ? atoi(szMin + 1) / 30 : 0);
 +
 +				TIME_ZONE_INFORMATION tzinfo;
 +				if (GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_DAYLIGHT)
 +					nTz -= tzinfo.DaylightBias / 30;
 +
 +				setByte(pInfo->m_hContact, "Timezone", (signed char)nTz);
 +
 +				const char *szTz = XmlGetChildText(xmlTime, "tz");
 +				if (szTz)
 +					setUString(pInfo->m_hContact, "TzName", szTz);
 +				else
 +					delSetting(pInfo->m_hContact, "TzName");
 +				return;
 +			}
  		}
  	}
  	else if (pInfo->m_nIqType == JABBER_IQ_TYPE_ERROR) {
 diff --git a/protocols/JabberG/src/jabber_notes.cpp b/protocols/JabberG/src/jabber_notes.cpp index 67678f107c..3b346ff64c 100644 --- a/protocols/JabberG/src/jabber_notes.cpp +++ b/protocols/JabberG/src/jabber_notes.cpp @@ -38,10 +38,10 @@ CNoteItem::CNoteItem()  CNoteItem::CNoteItem(const TiXmlElement *hXml, const char *szFrom)
  {
  	SetData(
 -		XPath(hXml, "title"),
 -		szFrom ? szFrom : XPath(hXml, "@from"),
 -		Utf2T(XPath(hXml, "text")),
 -		XPath(hXml, "@tags"));
 +		XmlGetChildText(hXml, "title"),
 +		szFrom ? szFrom : hXml->Attribute("from"),
 +		Utf2T(XmlGetChildText(hXml, "text")),
 +		hXml->Attribute("tags"));
  }
  CNoteItem::~CNoteItem()
 @@ -107,12 +107,6 @@ int CNoteItem::cmp(const CNoteItem *p1, const CNoteItem *p2)  	return 0;
  }
 -void CNoteList::AddNote(TiXmlElement *hXml, const char *szFrom)
 -{
 -	m_bIsModified = true;
 -	insert(new CNoteItem(hXml, szFrom));
 -}
 -
  void CNoteList::LoadXml(const TiXmlElement *hXml)
  {
  	destroy();
 diff --git a/protocols/JabberG/src/jabber_notes.h b/protocols/JabberG/src/jabber_notes.h index c2867970b3..3f0613a044 100644 --- a/protocols/JabberG/src/jabber_notes.h +++ b/protocols/JabberG/src/jabber_notes.h @@ -77,7 +77,6 @@ public:  		OBJLIST<CNoteItem>::remove(p);
  	}
 -	void AddNote(TiXmlElement *hXml, const char *szFrom = nullptr);
  	void LoadXml(const TiXmlElement *hXml);
  	void SaveXml(TiXmlElement *hXmlParent);
 diff --git a/protocols/JabberG/src/jabber_strm_mgmt.cpp b/protocols/JabberG/src/jabber_strm_mgmt.cpp index 9a61f66c63..b7682364aa 100755 --- a/protocols/JabberG/src/jabber_strm_mgmt.cpp +++ b/protocols/JabberG/src/jabber_strm_mgmt.cpp @@ -272,7 +272,7 @@ void strm_mgmt::FinishLoginProcess(ThreadData *info)  	if (info->auth) { //We are already logged-in
  		info->send(
  			XmlNodeIq(proto->AddIQ(&CJabberProto::OnIqResultBind, JABBER_IQ_TYPE_SET))
 -			<< XCHILDNS("bind", "urn:ietf:params:xml:ns:xmpp-bind")
 +			<< XCHILDNS("bind", JABBER_FEAT_BIND)
  			<< XCHILD("resource", info->resource));
  		if (proto->m_AuthMechs.isSessionAvailable)
 diff --git a/protocols/JabberG/src/jabber_thread.cpp b/protocols/JabberG/src/jabber_thread.cpp index 439ed33d69..fa9ea84c14 100755 --- a/protocols/JabberG/src/jabber_thread.cpp +++ b/protocols/JabberG/src/jabber_thread.cpp @@ -760,7 +760,7 @@ void CJabberProto::OnProcessFeatures(const TiXmlElement *node, ThreadData *info)  		if (info->auth) { //We are already logged-in
  			info->send(
  				XmlNodeIq(AddIQ(&CJabberProto::OnIqResultBind, JABBER_IQ_TYPE_SET))
 -				<< XCHILDNS("bind", "urn:ietf:params:xml:ns:xmpp-bind")
 +				<< XCHILDNS("bind", JABBER_FEAT_BIND)
  				<< XCHILD("resource", info->resource));
  			if (m_AuthMechs.isSessionAvailable)
 @@ -989,10 +989,10 @@ void CJabberProto::OnProcessPubsubEvent(const TiXmlElement *node)  		if (!tuneNode)
  			return;
 -		const char *szArtist = XPath(tuneNode, "artist");
 -		const char *szSource = XPath(tuneNode, "source");
 -		const char *szTitle = XPath(tuneNode, "title");
 -		const char *szTrack = XPath(tuneNode, "track");
 +		const char *szArtist = XmlGetChildText(tuneNode, "artist");
 +		const char *szSource = XmlGetChildText(tuneNode, "source");
 +		const char *szTitle = XmlGetChildText(tuneNode, "title");
 +		const char *szTrack = XmlGetChildText(tuneNode, "track");
  		wchar_t szLengthInTime[20];
  		int nLength = XmlGetChildInt(tuneNode, "length");
 diff --git a/protocols/JabberG/src/jabber_xml.cpp b/protocols/JabberG/src/jabber_xml.cpp index bd0fbe08eb..f2336123c7 100644 --- a/protocols/JabberG/src/jabber_xml.cpp +++ b/protocols/JabberG/src/jabber_xml.cpp @@ -199,191 +199,3 @@ int XmlGetChildCount(const TiXmlElement *hXml)  	}
  	return iCount;
  }
 -
 -/////////////////////////////////////////////////////////////////////////////////////////
 -
 -void XPath::ProcessPath(LookupInfo &info)
 -{
 -	if (!info.nodeName) return;
 -
 -	char *nodeName = (char *)alloca(sizeof(char) * (info.nodeName.length+1));
 -	mir_strncpy(nodeName, info.nodeName.p, info.nodeName.length+1);
 -
 -	if (info.attrName && info.attrValue) {
 -		char *attrName = (char *)alloca(sizeof(char)* (info.attrName.length + 1));
 -		mir_strncpy(attrName, info.attrName.p, info.attrName.length + 1);
 -		char *attrValue = (char *)alloca(sizeof(char)* (info.attrValue.length + 1));
 -		mir_strncpy(attrValue, info.attrValue.p, info.attrValue.length + 1);
 -		m_hXml = XmlGetChildByTag(m_hXml, nodeName, attrName, attrValue);
 -	}
 -	else m_hXml = m_hXml->FirstChildElement(nodeName);
 -
 -	info.Reset();
 -}
 -
 -XPath::PathType XPath::LookupImpl()
 -{
 -	LookupState state = S_START;
 -	LookupInfo info = {};
 -
 -	for (const char *p = m_szPath; state < S_FINAL; ++p) {
 -		switch (state) {
 -		case S_START:
 -			ProcessPath(info);
 -			if (!m_hXml) {
 -				state = S_FINAL_ERROR;
 -				break;
 -			}
 -
 -			switch (*p) {
 -			case 0:
 -				state = S_FINAL_ERROR;
 -				break;
 -			case '@':
 -				info.attrName.Begin(p + 1);
 -				state = S_ATTR_STEP;
 -				break;
 -			case '/':
 -				break;
 -			default:
 -				info.nodeName.Begin(p);
 -				state = S_NODE_NAME;
 -				break;
 -			};
 -			break;
 -
 -		case S_ATTR_STEP:
 -			switch (*p) {
 -			case 0:
 -				info.attrName.End(p);
 -				state = S_FINAL_ATTR;
 -				break;
 -			default:
 -				break;
 -			};
 -			break;
 -
 -		case S_NODE_NAME:
 -			switch (*p) {
 -			case 0:
 -				info.nodeName.End(p);
 -				state = S_FINAL_NODESET;
 -				break;
 -			case '[':
 -				info.nodeName.End(p);
 -				state = S_NODE_OPENBRACKET;
 -				break;
 -			case '/':
 -				info.nodeName.End(p);
 -				state = S_START;
 -				break;
 -			default:
 -				break;
 -			};
 -			break;
 -
 -		case S_NODE_OPENBRACKET:
 -			switch (*p) {
 -			case 0:
 -				state = S_FINAL_ERROR;
 -				break;
 -			case '@':
 -				info.attrName.Begin(p + 1);
 -				state = S_NODE_ATTRNAME;
 -				break;
 -			default:
 -				state = S_FINAL_ERROR;
 -				break;
 -			};
 -			break;
 -
 -		case S_NODE_ATTRNAME:
 -			switch (*p) {
 -			case 0:
 -				state = S_FINAL_ERROR;
 -				break;
 -			case '=':
 -				info.attrName.End(p);
 -				state = S_NODE_ATTREQUALS;
 -				break;
 -			default:
 -				break;
 -			};
 -			break;
 -
 -		case S_NODE_ATTREQUALS:
 -			switch (*p) {
 -			case 0:
 -				state = S_FINAL_ERROR;
 -				break;
 -			case '\'':
 -				info.attrValue.Begin(p + 1);
 -				state = S_NODE_ATTRVALUE;
 -				break;
 -			default:
 -				state = S_FINAL_ERROR;
 -				break;
 -			};
 -			break;
 -
 -		case S_NODE_ATTRVALUE:
 -			switch (*p) {
 -			case 0:
 -				state = S_FINAL_ERROR;
 -				break;
 -			case '\'':
 -				info.attrValue.End(p);
 -				state = S_NODE_ATTRCLOSEVALUE;
 -				break;
 -			default:
 -				break;
 -			};
 -			break;
 -
 -		case S_NODE_ATTRCLOSEVALUE:
 -			switch (*p) {
 -			case 0:
 -				state = S_FINAL_ERROR;
 -				break;
 -			case ']':
 -				state = S_NODE_CLOSEBRACKET;
 -				break;
 -			default:
 -				state = S_FINAL_ERROR;
 -				break;
 -			};
 -			break;
 -
 -		case S_NODE_CLOSEBRACKET:
 -			switch (*p) {
 -			case 0:
 -				state = S_FINAL_NODE;
 -				break;
 -			case '/':
 -				state = S_START;
 -				break;
 -			default:
 -				state = S_FINAL_ERROR;
 -				break;
 -			};
 -			break;
 -		}
 -
 -		if (!*p && (state < S_FINAL))
 -			state = S_FINAL_ERROR;
 -	}
 -
 -	switch (state) {
 -	case S_FINAL_ATTR:
 -		m_szParam = info.attrName.p;
 -		return T_ATTRIBUTE;
 -	case S_FINAL_NODE:
 -		ProcessPath(info);
 -		return T_NODE;
 -	case S_FINAL_NODESET:
 -		m_szParam = info.nodeName.p;
 -		return T_NODESET;
 -	}
 -
 -	return T_ERROR;
 -}
 diff --git a/protocols/JabberG/src/jabber_xml.h b/protocols/JabberG/src/jabber_xml.h index 84be255ba5..098e8ae346 100644 --- a/protocols/JabberG/src/jabber_xml.h +++ b/protocols/JabberG/src/jabber_xml.h @@ -188,137 +188,4 @@ struct XQUERY  TiXmlElement* __fastcall operator<<(TiXmlElement *node, const XQUERY& child);
 -/////////////////////////////////////////////////////////////////////////////////////////
 -// Limited XPath support
 -//     path should look like: "node-spec/node-spec/.../result-spec"
 -//     where "node-spec" can be "node-name", "node-name[@attr-name='attr-value']" or "node-name[node-index]"
 -//     result may be either "node-spec", or "@attr-name"
 -//
 -// Samples:
 -//    const char *s = XPath(node, "child/subchild[@attr='value']");          // get node text
 -//    XPath(node, "child/subchild[@name='test']/@attr") = L"Hello";   // create path if needed and set attribute value
 -//
 -//    XPath(node, "child/subchild[@name='test']") = L"Hello";         // TODO: create path if needed and set node text
 -
 -class XPath
 -{
 -public:
 -	__forceinline XPath(const TiXmlElement *hXml, char *path):
 -		m_type(T_UNKNOWN),
 -		m_szPath(path),
 -		m_hXml(hXml),
 -		m_szParam(nullptr)
 -	{}
 -
 -	// Read data
 -	operator const TiXmlElement*()
 -	{
 -		switch (Lookup())
 -		{
 -			case T_NODE:    return m_hXml;
 -			case T_NODESET: return m_hXml->FirstChildElement(m_szParam);
 -		}
 -		return nullptr;
 -	}
 -	operator LPCSTR()
 -	{
 -		switch (Lookup())
 -		{
 -			case T_ATTRIBUTE: return m_hXml->Attribute(m_szParam);
 -			case T_NODE:      return m_hXml->GetText();
 -			case T_NODESET:   return (m_hXml->FirstChildElement()) ? m_hXml->FirstChildElement()->GetText() : 0;
 -		}
 -		return nullptr;
 -	}
 -	__forceinline bool operator== (char *str)
 -	{
 -		return !mir_strcmp(*this, str);
 -	}
 -	__forceinline bool operator!= (char *str)
 -	{
 -		return mir_strcmp(*this, str) ? true : false;
 -	}
 -
 -private:
 -	enum PathType
 -	{
 -		T_UNKNOWN,
 -		T_ERROR,
 -		T_NODE,
 -		T_ATTRIBUTE,
 -		T_NODESET
 -	};
 -
 -	__forceinline PathType Lookup()
 -	{
 -		return (m_type == T_UNKNOWN) ? LookupImpl() : m_type;
 -	}
 -
 -	enum LookupState
 -	{
 -		S_START,
 -		S_ATTR_STEP,
 -		S_NODE_NAME,
 -		S_NODE_OPENBRACKET,
 -		S_NODE_ATTRNAME,
 -		S_NODE_ATTREQUALS,
 -		S_NODE_ATTRVALUE,
 -		S_NODE_ATTRCLOSEVALUE,
 -		S_NODE_CLOSEBRACKET,
 -
 -		S_FINAL,
 -		S_FINAL_ERROR,
 -		S_FINAL_ATTR,
 -		S_FINAL_NODESET,
 -		S_FINAL_NODE
 -	};
 -
 -	struct LookupString
 -	{
 -		void Begin(const char *p_) { p = p_; }
 -		void End(const char *p_) { length = p_ - p; }
 -		operator bool() { return p ? true : false; }
 -
 -		const char *p;
 -		int length;
 -
 -	};
 -
 -	struct LookupInfo
 -	{
 -		void Reset() { memset(this, 0, sizeof(*this)); }
 -		LookupString nodeName;
 -		LookupString attrName;
 -		LookupString attrValue;
 -	};
 -
 -	void ProcessPath(LookupInfo &info);
 -	PathType LookupImpl();
 -
 -	PathType m_type;
 -	const TiXmlElement *m_hXml;
 -	const char *m_szPath;
 -	const char *m_szParam;
 -};
 -
 -class XPathFmt: public XPath
 -{
 -public:
 -	enum { BUFSIZE = 512 };
 -	XPathFmt(const TiXmlElement *hXml, char *path, ...): XPath(hXml, m_buf)
 -	{
 -		*m_buf = 0;
 -		char buf[BUFSIZE];
 -
 -		va_list args;
 -		va_start(args, path);
 -		mir_vsnprintf(buf, BUFSIZE, path, args);
 -		buf[BUFSIZE-1] = 0;
 -		va_end(args);
 -	}
 -
 -private:
 -	char m_buf[BUFSIZE];
 -};
 -
  #endif
 diff --git a/protocols/JabberG/src/jabber_xstatus.cpp b/protocols/JabberG/src/jabber_xstatus.cpp index 70fad9c365..7909374f13 100644 --- a/protocols/JabberG/src/jabber_xstatus.cpp +++ b/protocols/JabberG/src/jabber_xstatus.cpp @@ -1003,7 +1003,7 @@ void CPepActivity::ProcessItems(const char *from, const TiXmlElement *itemsNode)  	if (!actNode)
  		return;
 -	const char *szText = XPath(actNode, "text");
 +	const char *szText = XmlGetChildText(actNode, "text");
  	const char *szFirstNode = nullptr, *szSecondNode = nullptr;
  	for (auto *n : TiXmlFilter(actNode, "text")) {
 | 
