From b7738e7af342a07f3bf0620d1424313a71c859dd Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 22 Jan 2014 08:44:04 +0100 Subject: db/upnp/Directory: join all CDATA nodes for tag values Expat can call CharacterData() multiple times if the CDATA contains entity references. We need to collect all of them in one large string. --- src/db/upnp/Directory.cxx | 54 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/src/db/upnp/Directory.cxx b/src/db/upnp/Directory.cxx index ada50d052..1108d9878 100644 --- a/src/db/upnp/Directory.cxx +++ b/src/db/upnp/Directory.cxx @@ -89,12 +89,26 @@ class UPnPDirParser final : public CommonExpatParser { UPnPDirContent &m_dir; std::vector m_path; + + /** + * If not equal to #TAG_NUM_OF_ITEM_TYPES, then we're + * currently reading an element containing a tag value. The + * value is being constructed in #value. + */ + TagType tag_type; + + /** + * The text inside the current element. + */ + std::string value; + UPnPDirObject m_tobj; TagBuilder tag; public: UPnPDirParser(UPnPDirContent& dir) - :m_dir(dir) + :m_dir(dir), + tag_type(TAG_NUM_OF_ITEM_TYPES) { } @@ -103,6 +117,15 @@ protected: { m_path.push_back(name); + if (m_tobj.type != UPnPDirObject::Type::UNKNOWN && + tag_type == TAG_NUM_OF_ITEM_TYPES) { + tag_type = tag_table_lookup(upnp_tags, name); + if (tag_type != TAG_NUM_OF_ITEM_TYPES) + return; + } else { + assert(tag_type == TAG_NUM_OF_ITEM_TYPES); + } + switch (name[0]) { case 'c': if (!strcmp(name, "container")) { @@ -162,6 +185,19 @@ protected: virtual void EndElement(const XML_Char *name) { + if (tag_type != TAG_NUM_OF_ITEM_TYPES) { + assert(m_tobj.type != UPnPDirObject::Type::UNKNOWN); + + tag.AddItem(tag_type, value.c_str()); + + if (tag_type == TAG_TITLE) + m_tobj.name = titleToPathElt(std::move(value)); + + value.clear(); + tag_type = TAG_NUM_OF_ITEM_TYPES; + return; + } + if ((!strcmp(name, "container") || !strcmp(name, "item")) && checkobjok()) { tag.Commit(m_tobj.tag); @@ -173,20 +209,16 @@ protected: virtual void CharacterData(const XML_Char *s, int len) { - const auto ¤t = m_path.back(); - std::string str = trimstring(s, len); - - TagType type = tag_table_lookup(upnp_tags, - current.c_str()); - if (type != TAG_NUM_OF_ITEM_TYPES) { - tag.AddItem(type, str.c_str()); - - if (type == TAG_TITLE) - m_tobj.name = titleToPathElt(std::move(str)); + if (tag_type != TAG_NUM_OF_ITEM_TYPES) { + assert(m_tobj.type != UPnPDirObject::Type::UNKNOWN); + value.append(s, len); return; } + const auto ¤t = m_path.back(); + std::string str = trimstring(s, len); + switch (current[0]) { case 'r': if (!current.compare("res")) { -- cgit v1.2.3