diff options
author | Max Kellermann <max@duempel.org> | 2014-01-22 08:44:04 +0100 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2014-01-22 08:44:35 +0100 |
commit | b7738e7af342a07f3bf0620d1424313a71c859dd (patch) | |
tree | 3a918c41d1567c48377a2b0ace34f98f7308bd00 /src | |
parent | 99bebabac97b24e94cad026422e663e97492894b (diff) | |
download | mpd-b7738e7af342a07f3bf0620d1424313a71c859dd.tar.gz mpd-b7738e7af342a07f3bf0620d1424313a71c859dd.tar.xz mpd-b7738e7af342a07f3bf0620d1424313a71c859dd.zip |
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.
Diffstat (limited to '')
-rw-r--r-- | src/db/upnp/Directory.cxx | 54 |
1 files 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<std::string> 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")) { |