aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2014-01-22 08:44:04 +0100
committerMax Kellermann <max@duempel.org>2014-01-22 08:44:35 +0100
commitb7738e7af342a07f3bf0620d1424313a71c859dd (patch)
tree3a918c41d1567c48377a2b0ace34f98f7308bd00 /src
parent99bebabac97b24e94cad026422e663e97492894b (diff)
downloadmpd-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.cxx54
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 &current = 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 &current = m_path.back();
+ std::string str = trimstring(s, len);
+
switch (current[0]) {
case 'r':
if (!current.compare("res")) {