|
Packit |
712bc5 |
/*
|
|
Packit |
712bc5 |
* Copyright (C) 2006, 2007 OpenedHand Ltd.
|
|
Packit |
712bc5 |
* Copyright (C) 2007 Zeeshan Ali.
|
|
Packit |
712bc5 |
* Copyright (C) 2012 Intel Corporation
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* Author: Jorn Baayen <jorn@openedhand.com>
|
|
Packit |
712bc5 |
* Author: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
|
|
Packit |
712bc5 |
* Author: Krzesimir Nowak <krnowak@openismus.com>
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* This library is free software; you can redistribute it and/or
|
|
Packit |
712bc5 |
* modify it under the terms of the GNU Library General Public
|
|
Packit |
712bc5 |
* License as published by the Free Software Foundation; either
|
|
Packit |
712bc5 |
* version 2 of the License, or (at your option) any later version.
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
712bc5 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
712bc5 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
712bc5 |
* Library General Public License for more details.
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* You should have received a copy of the GNU Library General Public
|
|
Packit |
712bc5 |
* License along with this library; if not, write to the
|
|
Packit |
712bc5 |
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
Packit |
712bc5 |
* Boston, MA 02110-1301, USA.
|
|
Packit |
712bc5 |
*/
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
#include <string.h>
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
#include "xml-util.h"
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
typedef struct _GUPnPXMLNamespaceDescription
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
const char *uri;
|
|
Packit |
712bc5 |
const char *prefix;
|
|
Packit |
712bc5 |
} GUPnPXMLNamespaceDescription;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
static GUPnPXMLNamespaceDescription gupnp_xml_namespaces[] =
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
{ "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/", NULL },
|
|
Packit |
712bc5 |
{ "http://purl.org/dc/elements/1.1/", "dc" },
|
|
Packit |
712bc5 |
{ "urn:schemas-dlna-org:metadata-1-0/", "dlna" },
|
|
Packit |
712bc5 |
{ "http://www.pv.com/pvns/", "pv" },
|
|
Packit |
712bc5 |
{ "urn:schemas-upnp-org:metadata-1-0/upnp/", "upnp" },
|
|
Packit |
712bc5 |
{ NULL }
|
|
Packit |
712bc5 |
};
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
GUPnPAVXMLDoc *
|
|
Packit |
712bc5 |
xml_doc_new (xmlDoc *doc)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
GUPnPAVXMLDoc *ret = NULL;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
g_return_val_if_fail (doc, NULL);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
ret = g_new0 (GUPnPAVXMLDoc, 1);
|
|
Packit |
712bc5 |
ret->refcount = 1;
|
|
Packit |
712bc5 |
ret->doc = doc;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return ret;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
GUPnPAVXMLDoc *
|
|
Packit |
712bc5 |
xml_doc_ref (GUPnPAVXMLDoc *doc)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
g_return_val_if_fail (doc, NULL);
|
|
Packit |
712bc5 |
g_return_val_if_fail (doc->refcount > 0, NULL);
|
|
Packit |
712bc5 |
g_atomic_int_inc (&doc->refcount);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return doc;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
void
|
|
Packit |
712bc5 |
xml_doc_unref (GUPnPAVXMLDoc *doc)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
g_return_if_fail (doc);
|
|
Packit |
712bc5 |
g_return_if_fail (doc->refcount > 0);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
if (g_atomic_int_dec_and_test (&doc->refcount)) {
|
|
Packit |
712bc5 |
xmlFreeDoc (doc->doc);
|
|
Packit |
712bc5 |
doc->doc = NULL;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
xmlNode *
|
|
Packit |
712bc5 |
xml_util_get_element (xmlNode *node,
|
|
Packit |
712bc5 |
...)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
va_list var_args;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
va_start (var_args, node);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
while (TRUE) {
|
|
Packit |
712bc5 |
const char *arg;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
arg = va_arg (var_args, const char *);
|
|
Packit |
712bc5 |
if (!arg)
|
|
Packit |
712bc5 |
break;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
for (node = node->children; node; node = node->next) {
|
|
Packit |
712bc5 |
if (node->name == NULL)
|
|
Packit |
712bc5 |
continue;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
if (!g_ascii_strcasecmp (arg, (char *) node->name))
|
|
Packit |
712bc5 |
break;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
if (!node)
|
|
Packit |
712bc5 |
break;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
va_end (var_args);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return node;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
GList *
|
|
Packit |
712bc5 |
xml_util_get_child_elements_by_name (xmlNode *node, const char *name)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
GList *children = NULL;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
for (node = node->children; node; node = node->next) {
|
|
Packit |
712bc5 |
if (node->name == NULL)
|
|
Packit |
712bc5 |
continue;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
if (strcmp (name, (char *) node->name) == 0) {
|
|
Packit |
712bc5 |
children = g_list_append (children, node);
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return children;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
const char *
|
|
Packit |
712bc5 |
xml_util_get_child_element_content (xmlNode *node,
|
|
Packit |
712bc5 |
const char *child_name)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
xmlNode *child_node;
|
|
Packit |
712bc5 |
const char *content;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
child_node = xml_util_get_element (node, child_name, NULL);
|
|
Packit |
712bc5 |
if (!child_node || !(child_node->children))
|
|
Packit |
712bc5 |
return NULL;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
content = (const char *) child_node->children->content;
|
|
Packit |
712bc5 |
if (!content)
|
|
Packit |
712bc5 |
return NULL;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return content;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
guint
|
|
Packit |
712bc5 |
xml_util_get_uint_child_element (xmlNode *node,
|
|
Packit |
712bc5 |
const char *child_name,
|
|
Packit |
712bc5 |
guint default_value)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
const char *content;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
content = xml_util_get_child_element_content (node, child_name);
|
|
Packit |
712bc5 |
if (!content)
|
|
Packit |
712bc5 |
return default_value;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return strtoul (content, NULL, 0);
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
guint64
|
|
Packit |
712bc5 |
xml_util_get_uint64_child_element (xmlNode *node,
|
|
Packit |
712bc5 |
const char *child_name,
|
|
Packit |
712bc5 |
guint64 default_value)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
const char *content;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
content = xml_util_get_child_element_content (node, child_name);
|
|
Packit |
712bc5 |
if (!content)
|
|
Packit |
712bc5 |
return default_value;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return g_ascii_strtoull (content, NULL, 0);
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
const char *
|
|
Packit |
712bc5 |
xml_util_get_attribute_content (xmlNode *node,
|
|
Packit |
712bc5 |
const char *attribute_name)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
xmlAttr *attribute;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
for (attribute = node->properties;
|
|
Packit |
712bc5 |
attribute;
|
|
Packit |
712bc5 |
attribute = attribute->next) {
|
|
Packit |
712bc5 |
if (attribute->name == NULL)
|
|
Packit |
712bc5 |
continue;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
if (strcmp (attribute_name, (char *) attribute->name) == 0)
|
|
Packit |
712bc5 |
break;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
if (attribute)
|
|
Packit |
712bc5 |
return (const char *) attribute->children->content;
|
|
Packit |
712bc5 |
else
|
|
Packit |
712bc5 |
return NULL;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
gboolean
|
|
Packit |
712bc5 |
xml_util_get_boolean_attribute (xmlNode *node,
|
|
Packit |
712bc5 |
const char *attribute_name)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
const char *content;
|
|
Packit |
712bc5 |
gchar *str;
|
|
Packit |
712bc5 |
gboolean ret;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
content = xml_util_get_attribute_content (node, attribute_name);
|
|
Packit |
712bc5 |
if (!content)
|
|
Packit |
712bc5 |
return FALSE;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
str = (char *) content;
|
|
Packit |
712bc5 |
if (g_ascii_strcasecmp (str, "true") == 0 ||
|
|
Packit |
712bc5 |
g_ascii_strcasecmp (str, "yes") == 0)
|
|
Packit |
712bc5 |
ret = TRUE;
|
|
Packit |
712bc5 |
else if (g_ascii_strcasecmp (str, "false") == 0 ||
|
|
Packit |
712bc5 |
g_ascii_strcasecmp (str, "no") == 0)
|
|
Packit |
712bc5 |
ret = FALSE;
|
|
Packit |
712bc5 |
else {
|
|
Packit |
712bc5 |
int i;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
i = atoi (str);
|
|
Packit |
712bc5 |
ret = i ? TRUE : FALSE;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return ret;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
guint
|
|
Packit |
712bc5 |
xml_util_get_uint_attribute (xmlNode *node,
|
|
Packit |
712bc5 |
const char *attribute_name,
|
|
Packit |
712bc5 |
guint default_value)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
return (guint) xml_util_get_long_attribute (node,
|
|
Packit |
712bc5 |
attribute_name,
|
|
Packit |
712bc5 |
(glong) default_value);
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
gint
|
|
Packit |
712bc5 |
xml_util_get_int_attribute (xmlNode *node,
|
|
Packit |
712bc5 |
const char *attribute_name,
|
|
Packit |
712bc5 |
gint default_value)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
return (gint) xml_util_get_long_attribute (node,
|
|
Packit |
712bc5 |
attribute_name,
|
|
Packit |
712bc5 |
(glong) default_value);
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
glong
|
|
Packit |
712bc5 |
xml_util_get_long_attribute (xmlNode *node,
|
|
Packit |
712bc5 |
const char *attribute_name,
|
|
Packit |
712bc5 |
glong default_value)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
return (glong) xml_util_get_int64_attribute (node,
|
|
Packit |
712bc5 |
attribute_name,
|
|
Packit |
712bc5 |
(gint64) default_value);
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
gint64
|
|
Packit |
712bc5 |
xml_util_get_int64_attribute (xmlNode *node,
|
|
Packit |
712bc5 |
const char *attribute_name,
|
|
Packit |
712bc5 |
gint64 default_value)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
const char *content;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
content = xml_util_get_attribute_content (node, attribute_name);
|
|
Packit |
712bc5 |
if (!content)
|
|
Packit |
712bc5 |
return default_value;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return g_ascii_strtoll (content, NULL, 0);
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
xmlNode *
|
|
Packit |
712bc5 |
xml_util_set_child (xmlNode *parent_node,
|
|
Packit |
712bc5 |
GUPnPXMLNamespace ns,
|
|
Packit |
712bc5 |
xmlNsPtr *xmlns,
|
|
Packit |
712bc5 |
xmlDoc *doc,
|
|
Packit |
712bc5 |
const char *name,
|
|
Packit |
712bc5 |
const char *value)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
xmlNode *node;
|
|
Packit |
712bc5 |
xmlChar *escaped;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
node = xml_util_get_element (parent_node, name, NULL);
|
|
Packit |
712bc5 |
if (node == NULL) {
|
|
Packit |
712bc5 |
xmlNsPtr ns_ptr = NULL;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
ns_ptr = xml_util_get_ns (doc, ns, xmlns);
|
|
Packit |
712bc5 |
node = xmlNewChild (parent_node,
|
|
Packit |
712bc5 |
ns_ptr,
|
|
Packit |
712bc5 |
(unsigned char *) name,
|
|
Packit |
712bc5 |
NULL);
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
escaped = xmlEncodeSpecialChars (doc, (const unsigned char *) value);
|
|
Packit |
712bc5 |
xmlNodeSetContent (node, escaped);
|
|
Packit |
712bc5 |
xmlFree (escaped);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return node;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
void
|
|
Packit |
712bc5 |
xml_util_unset_child (xmlNode *parent_node,
|
|
Packit |
712bc5 |
const char *name)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
xmlNode *node;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
node = xml_util_get_element (parent_node, name, NULL);
|
|
Packit |
712bc5 |
if (node != NULL) {
|
|
Packit |
712bc5 |
xmlUnlinkNode (node);
|
|
Packit |
712bc5 |
xmlFreeNode (node);
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
gboolean
|
|
Packit |
712bc5 |
xml_util_verify_attribute_is_boolean (xmlNode *node,
|
|
Packit |
712bc5 |
const char *attribute_name)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
const char *content;
|
|
Packit |
712bc5 |
char *str;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
content = xml_util_get_attribute_content (node, attribute_name);
|
|
Packit |
712bc5 |
if (content == NULL)
|
|
Packit |
712bc5 |
return FALSE;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
str = (char *) content;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return g_ascii_strcasecmp (str, "true") == 0 ||
|
|
Packit |
712bc5 |
g_ascii_strcasecmp (str, "yes") == 0 ||
|
|
Packit |
712bc5 |
g_ascii_strcasecmp (str, "false") == 0 ||
|
|
Packit |
712bc5 |
g_ascii_strcasecmp (str, "no") == 0 ||
|
|
Packit |
712bc5 |
g_ascii_strcasecmp (str, "0") == 0 ||
|
|
Packit |
712bc5 |
g_ascii_strcasecmp (str, "1") == 0;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
char *
|
|
Packit |
712bc5 |
xml_util_get_child_string (xmlNode *parent_node,
|
|
Packit |
712bc5 |
xmlDoc *doc,
|
|
Packit |
712bc5 |
const char *name)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
xmlBuffer *buffer;
|
|
Packit |
712bc5 |
char *ret;
|
|
Packit |
712bc5 |
xmlNode *node;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
node = xml_util_get_element (parent_node, name, NULL);
|
|
Packit |
712bc5 |
if (!node)
|
|
Packit |
712bc5 |
return NULL;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
buffer = xmlBufferCreate ();
|
|
Packit |
712bc5 |
xmlNodeDump (buffer,
|
|
Packit |
712bc5 |
doc,
|
|
Packit |
712bc5 |
node,
|
|
Packit |
712bc5 |
0,
|
|
Packit |
712bc5 |
0);
|
|
Packit |
712bc5 |
ret = g_strndup ((char *) xmlBufferContent (buffer),
|
|
Packit |
712bc5 |
xmlBufferLength (buffer));
|
|
Packit |
712bc5 |
xmlBufferFree (buffer);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return ret;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
gboolean
|
|
Packit |
712bc5 |
xml_util_node_deep_equal (xmlNode *first,
|
|
Packit |
712bc5 |
xmlNode *second)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
GHashTable *first_attributes;
|
|
Packit |
712bc5 |
xmlAttr *attribute;
|
|
Packit |
712bc5 |
gboolean equal;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
if (first == NULL && second == NULL)
|
|
Packit |
712bc5 |
return TRUE;
|
|
Packit |
712bc5 |
if (first == NULL || second == NULL)
|
|
Packit |
712bc5 |
return FALSE;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
if (xmlStrcmp (first->name, second->name))
|
|
Packit |
712bc5 |
return FALSE;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
equal = FALSE;
|
|
Packit |
712bc5 |
first_attributes = xml_util_get_attributes_map (first);
|
|
Packit |
712bc5 |
/* compare attributes */
|
|
Packit |
712bc5 |
for (attribute = second->properties;
|
|
Packit |
712bc5 |
attribute != NULL;
|
|
Packit |
712bc5 |
attribute = attribute->next) {
|
|
Packit |
712bc5 |
const xmlChar *value = NULL;
|
|
Packit |
712bc5 |
const xmlChar *key = attribute->name;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
if (g_hash_table_lookup_extended (first_attributes,
|
|
Packit |
712bc5 |
key,
|
|
Packit |
712bc5 |
NULL,
|
|
Packit |
712bc5 |
(gpointer *) &value))
|
|
Packit |
712bc5 |
if (!xmlStrcmp (value, attribute->children->content)) {
|
|
Packit |
712bc5 |
g_hash_table_remove (first_attributes, key);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
continue;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
goto out;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
if (g_hash_table_size (first_attributes))
|
|
Packit |
712bc5 |
goto out;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/* compare content */
|
|
Packit |
712bc5 |
if (xmlStrcmp (first->content, second->content))
|
|
Packit |
712bc5 |
goto out;
|
|
Packit |
712bc5 |
equal = TRUE;
|
|
Packit |
712bc5 |
out:
|
|
Packit |
712bc5 |
g_hash_table_unref (first_attributes);
|
|
Packit |
712bc5 |
if (equal) {
|
|
Packit |
712bc5 |
xmlNode *first_child;
|
|
Packit |
712bc5 |
xmlNode *second_child;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
for (first_child = first->children,
|
|
Packit |
712bc5 |
second_child = second->children;
|
|
Packit |
712bc5 |
first_child != NULL && second_child != NULL;
|
|
Packit |
712bc5 |
first_child = first_child->next,
|
|
Packit |
712bc5 |
second_child = second_child->next)
|
|
Packit |
712bc5 |
if (!xml_util_node_deep_equal (first_child, second_child))
|
|
Packit |
712bc5 |
return FALSE;
|
|
Packit |
712bc5 |
if (first_child != NULL || second_child != NULL)
|
|
Packit |
712bc5 |
return FALSE;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return equal;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
xmlNode *
|
|
Packit |
712bc5 |
xml_util_find_node (xmlNode *haystack,
|
|
Packit |
712bc5 |
xmlNode *needle)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
xmlNodePtr iter;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
if (xml_util_node_deep_equal (haystack, needle))
|
|
Packit |
712bc5 |
return haystack;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
for (iter = haystack->children; iter != NULL; iter = iter->next) {
|
|
Packit |
712bc5 |
xmlNodePtr found_node = xml_util_find_node (iter, needle);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
if (found_node != NULL)
|
|
Packit |
712bc5 |
return found_node;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return NULL;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
xmlNode *
|
|
Packit |
712bc5 |
xml_util_copy_node (xmlNode *node)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
xmlNode *dup = xmlCopyNode (node, 1);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/* TODO: remove useless namespace definition. */
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return dup;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
GHashTable *
|
|
Packit |
712bc5 |
xml_util_get_attributes_map (xmlNode *node)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
xmlAttr *attribute;
|
|
Packit |
712bc5 |
GHashTable *attributes_map = g_hash_table_new (g_str_hash,
|
|
Packit |
712bc5 |
g_str_equal);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
for (attribute = node->properties;
|
|
Packit |
712bc5 |
attribute != NULL;
|
|
Packit |
712bc5 |
attribute = attribute->next)
|
|
Packit |
712bc5 |
g_hash_table_insert (attributes_map,
|
|
Packit |
712bc5 |
(gpointer) attribute->name,
|
|
Packit |
712bc5 |
(gpointer) attribute->children->content);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return attributes_map;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/**
|
|
Packit |
712bc5 |
* xml_util_create_namespace:
|
|
Packit |
712bc5 |
* @root: (allow-none): Document root node or %NULL for anonymous ns.
|
|
Packit |
712bc5 |
* @ns: Namespace
|
|
Packit |
712bc5 |
* @returns: Newly created namespace on root node
|
|
Packit |
712bc5 |
*/
|
|
Packit |
712bc5 |
xmlNsPtr
|
|
Packit |
712bc5 |
xml_util_create_namespace (xmlNodePtr root, GUPnPXMLNamespace ns)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
g_return_val_if_fail (ns < GUPNP_XML_NAMESPACE_COUNT, NULL);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return xmlNewNs (root,
|
|
Packit |
712bc5 |
(const xmlChar *) gupnp_xml_namespaces[ns].uri,
|
|
Packit |
712bc5 |
(const xmlChar *) gupnp_xml_namespaces[ns].prefix);
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/**
|
|
Packit |
712bc5 |
* xml_util_lookup_namespace:
|
|
Packit |
712bc5 |
* @doc: #xmlDoc
|
|
Packit |
712bc5 |
* @ns: namespace to look up (except DIDL-Lite, which doesn't have a prefix)
|
|
Packit |
712bc5 |
* @returns: %NULL if namespace does not exist, a pointer to the namespace
|
|
Packit |
712bc5 |
* otherwise.
|
|
Packit |
712bc5 |
*/
|
|
Packit |
712bc5 |
xmlNsPtr
|
|
Packit |
712bc5 |
xml_util_lookup_namespace (xmlDocPtr doc, GUPnPXMLNamespace ns)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
xmlNsPtr *ns_list, *it, retval = NULL;
|
|
Packit |
712bc5 |
const char *ns_prefix = NULL;
|
|
Packit |
712bc5 |
const char *ns_uri = NULL;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
g_return_val_if_fail (ns < GUPNP_XML_NAMESPACE_COUNT, NULL);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
ns_prefix = gupnp_xml_namespaces[ns].prefix;
|
|
Packit |
712bc5 |
ns_uri = gupnp_xml_namespaces[ns].uri;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
ns_list = xmlGetNsList (doc, xmlDocGetRootElement (doc));
|
|
Packit |
712bc5 |
if (ns_list == NULL)
|
|
Packit |
712bc5 |
return NULL;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
for (it = ns_list; *it != NULL; it++) {
|
|
Packit |
712bc5 |
const char *it_prefix = (const char *) (*it)->prefix;
|
|
Packit |
712bc5 |
const char *it_uri = (const char *) (*it)->href;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
if (it_prefix == NULL) {
|
|
Packit |
712bc5 |
if (ns_prefix != NULL)
|
|
Packit |
712bc5 |
continue;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
if (g_ascii_strcasecmp (it_uri, ns_uri) == 0) {
|
|
Packit |
712bc5 |
retval = *it;
|
|
Packit |
712bc5 |
break;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
continue;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
if (g_ascii_strcasecmp (it_prefix, ns_prefix) == 0) {
|
|
Packit |
712bc5 |
retval = *it;
|
|
Packit |
712bc5 |
break;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
xmlFree (ns_list);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return retval;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/**
|
|
Packit |
712bc5 |
* xml_util_get_ns:
|
|
Packit |
712bc5 |
* @doc: A #xmlDoc.
|
|
Packit |
712bc5 |
* @ns: A #GUPnPXMLNamespace.
|
|
Packit |
712bc5 |
* @ns_out: (out) (allow-none): return location for the namespace or %NULL.
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* Lazy-create a XML namespace on @doc.
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* If @ns_out is non-%NULL, the function will return @ns_out immediately.
|
|
Packit |
712bc5 |
* @returns: either the existing #xmlNsPtr or a newly created one.
|
|
Packit |
712bc5 |
*/
|
|
Packit |
712bc5 |
xmlNsPtr
|
|
Packit |
712bc5 |
xml_util_get_ns (xmlDocPtr doc, GUPnPXMLNamespace ns, xmlNsPtr *ns_out)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
xmlNsPtr tmp_ns;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/* User supplied namespace, just return that */
|
|
Packit |
712bc5 |
if (ns_out != NULL && *ns_out != NULL)
|
|
Packit |
712bc5 |
return *ns_out;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
tmp_ns = xml_util_lookup_namespace (doc, ns);
|
|
Packit |
712bc5 |
if (!tmp_ns)
|
|
Packit |
712bc5 |
tmp_ns = xml_util_create_namespace (xmlDocGetRootElement (doc),
|
|
Packit |
712bc5 |
ns);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
if (ns_out != NULL)
|
|
Packit |
712bc5 |
*ns_out = tmp_ns;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return tmp_ns;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
G_DEFINE_BOXED_TYPE (GUPnPAVXMLDoc, xml_doc, xml_doc_ref, xml_doc_unref)
|