Commit b7738e7a authored by Max Kellermann's avatar Max Kellermann

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.
parent 99bebaba
......@@ -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")) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment