|
Packit |
29108b |
/*
|
|
Packit |
29108b |
| Copyright (C) 2008 Christophe Fergeau <teuf@gnome.org>
|
|
Packit |
29108b |
| Part of the gtkpod project.
|
|
Packit |
29108b |
|
|
|
Packit |
29108b |
| URL: http://www.gtkpod.org/
|
|
Packit |
29108b |
| URL: http://gtkpod.sourceforge.net/
|
|
Packit |
29108b |
|
|
|
Packit |
29108b |
| The code contained in this file is free software; you can redistribute
|
|
Packit |
29108b |
| it and/or modify it under the terms of the GNU Lesser General Public
|
|
Packit |
29108b |
| License as published by the Free Software Foundation; either version
|
|
Packit |
29108b |
| 2.1 of the License, or (at your option) any later version.
|
|
Packit |
29108b |
|
|
|
Packit |
29108b |
| This file is distributed in the hope that it will be useful,
|
|
Packit |
29108b |
| but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
29108b |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
29108b |
| Lesser General Public License for more details.
|
|
Packit |
29108b |
|
|
|
Packit |
29108b |
| You should have received a copy of the GNU Lesser General Public
|
|
Packit |
29108b |
| License along with this code; if not, write to the Free Software
|
|
Packit |
29108b |
| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
Packit |
29108b |
|
|
|
Packit |
29108b |
| iTunes and iPod are trademarks of Apple
|
|
Packit |
29108b |
|
|
|
Packit |
29108b |
| This product is not supported/written/published by Apple!
|
|
Packit |
29108b |
|
|
|
Packit |
29108b |
| $Id$
|
|
Packit |
29108b |
*/
|
|
Packit |
29108b |
|
|
Packit |
29108b |
/* This file implements a generic plist parser. A plist file is an
|
|
Packit |
29108b |
* Apple-specific XML format which is used to serialize (simple) data
|
|
Packit |
29108b |
* structures to disk, see http://en.wikipedia.org/wiki/Property_list
|
|
Packit |
29108b |
*
|
|
Packit |
29108b |
* This parser should handle most plist files, with those limitations :
|
|
Packit |
29108b |
* - no support for <date> tags
|
|
Packit |
29108b |
*
|
|
Packit |
29108b |
* The plist file is parsed using libxml, and the parsed result is stored
|
|
Packit |
29108b |
* in GValue. The types are mapped in the following way:
|
|
Packit |
29108b |
* - <string> => G_TYPE_STRING (char*)
|
|
Packit |
29108b |
* - <real> => G_TYPE_DOUBLE (double)
|
|
Packit |
29108b |
* - <integer> => G_TYPE_INT64 (gint64)
|
|
Packit |
29108b |
* - <true/>, <false/> => G_TYPE_BOOLEAN (gboolean)
|
|
Packit |
29108b |
* - <data> => G_TYPE_GSTRING (GString *)
|
|
Packit |
29108b |
* - <array> => G_TYPE_ARRAY (GArray *)
|
|
Packit |
29108b |
* - <dict> => G_TYPE_HASH_TABLE (GHashTable *)
|
|
Packit |
29108b |
*/
|
|
Packit |
29108b |
#ifdef HAVE_CONFIG_H
|
|
Packit |
29108b |
#include <config.h>
|
|
Packit |
29108b |
#endif
|
|
Packit |
29108b |
|
|
Packit |
29108b |
#ifdef HAVE_LIBXML
|
|
Packit |
29108b |
|
|
Packit |
29108b |
#include <stdio.h>
|
|
Packit |
29108b |
#include <string.h>
|
|
Packit |
29108b |
#include <libxml/parser.h>
|
|
Packit |
29108b |
#include <libxml/tree.h>
|
|
Packit |
29108b |
#include <glib.h>
|
|
Packit |
29108b |
#include <glib-object.h>
|
|
Packit |
29108b |
|
|
Packit |
29108b |
#include "itdb_plist.h"
|
|
Packit |
29108b |
|
|
Packit |
29108b |
#ifdef DEBUG_SYSINFO_PARSING
|
|
Packit |
29108b |
#define DEBUG g_print
|
|
Packit |
29108b |
#else
|
|
Packit |
29108b |
#define DEBUG(...)
|
|
Packit |
29108b |
#endif
|
|
Packit |
29108b |
|
|
Packit |
29108b |
/* Error domain */
|
|
Packit |
29108b |
#define ITDB_DEVICE_ERROR itdb_device_error_quark ()
|
|
Packit |
29108b |
extern GQuark itdb_device_error_quark (void);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
static GValue *parse_node (xmlNode *a_node, GError **error);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
static void
|
|
Packit |
29108b |
value_free (GValue *val)
|
|
Packit |
29108b |
{
|
|
Packit |
29108b |
g_value_unset (val);
|
|
Packit |
29108b |
g_free (val);
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
|
|
Packit |
29108b |
static GValue *
|
|
Packit |
29108b |
parse_integer(xmlNode *a_node, GError **error)
|
|
Packit |
29108b |
{
|
|
Packit |
29108b |
char *str_val;
|
|
Packit |
29108b |
char *end_ptr;
|
|
Packit |
29108b |
gint64 int_val;
|
|
Packit |
29108b |
GValue *value;
|
|
Packit |
29108b |
|
|
Packit |
29108b |
str_val = (char *)xmlNodeGetContent(a_node);
|
|
Packit |
29108b |
int_val = strtoll (str_val, &end_ptr, 0);
|
|
Packit |
29108b |
if (*end_ptr != '\0') {
|
|
Packit |
29108b |
g_set_error (error, ITDB_DEVICE_ERROR, ITDB_DEVICE_ERROR_XML_PARSING,
|
|
Packit |
29108b |
"invalid integer value: %s", str_val);
|
|
Packit |
29108b |
xmlFree (str_val);
|
|
Packit |
29108b |
return NULL;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
xmlFree (str_val);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
value = g_new0(GValue, 1);
|
|
Packit |
29108b |
g_value_init(value, G_TYPE_INT64);
|
|
Packit |
29108b |
g_value_set_int64 (value, int_val);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
return value;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
|
|
Packit |
29108b |
static GValue *
|
|
Packit |
29108b |
parse_string(xmlNode *a_node, G_GNUC_UNUSED GError **error)
|
|
Packit |
29108b |
{
|
|
Packit |
29108b |
char *str_val;
|
|
Packit |
29108b |
GValue *value;
|
|
Packit |
29108b |
|
|
Packit |
29108b |
str_val = (char *)xmlNodeGetContent(a_node);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
value = g_new0(GValue, 1);
|
|
Packit |
29108b |
g_value_init(value, G_TYPE_STRING);
|
|
Packit |
29108b |
g_value_set_string (value, str_val);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
xmlFree (str_val);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
return value;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
|
|
Packit |
29108b |
static GValue *
|
|
Packit |
29108b |
parse_real(xmlNode *a_node, GError **error)
|
|
Packit |
29108b |
{
|
|
Packit |
29108b |
char *str_val;
|
|
Packit |
29108b |
char *end_ptr;
|
|
Packit |
29108b |
gfloat double_val;
|
|
Packit |
29108b |
GValue *value;
|
|
Packit |
29108b |
|
|
Packit |
29108b |
str_val = (char *)xmlNodeGetContent(a_node);
|
|
Packit |
29108b |
double_val = g_ascii_strtod (str_val, &end_ptr);
|
|
Packit |
29108b |
if (*end_ptr != '\0') {
|
|
Packit |
29108b |
g_set_error (error, ITDB_DEVICE_ERROR, ITDB_DEVICE_ERROR_XML_PARSING,
|
|
Packit |
29108b |
"invalid real value: %s", str_val);
|
|
Packit |
29108b |
xmlFree (str_val);
|
|
Packit |
29108b |
return NULL;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
xmlFree (str_val);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
value = g_new0(GValue, 1);
|
|
Packit |
29108b |
g_value_init(value, G_TYPE_DOUBLE);
|
|
Packit |
29108b |
g_value_set_double (value, double_val);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
return value;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
|
|
Packit |
29108b |
static GValue *
|
|
Packit |
29108b |
parse_boolean (xmlNode *a_node, GError **error)
|
|
Packit |
29108b |
{
|
|
Packit |
29108b |
gboolean bool_val;
|
|
Packit |
29108b |
GValue *value;
|
|
Packit |
29108b |
|
|
Packit |
29108b |
if (strcmp ((char *)a_node->name, "true") == 0) {
|
|
Packit |
29108b |
bool_val = TRUE;
|
|
Packit |
29108b |
} else if (strcmp ((char *)a_node->name, "false") == 0) {
|
|
Packit |
29108b |
bool_val = FALSE;
|
|
Packit |
29108b |
} else {
|
|
Packit |
29108b |
g_set_error (error, ITDB_DEVICE_ERROR, ITDB_DEVICE_ERROR_XML_PARSING,
|
|
Packit |
29108b |
"unexpected boolean value: %s", a_node->name);
|
|
Packit |
29108b |
return NULL;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
|
|
Packit |
29108b |
value = g_new0 (GValue, 1);
|
|
Packit |
29108b |
g_value_init (value, G_TYPE_BOOLEAN);
|
|
Packit |
29108b |
g_value_set_boolean (value, bool_val);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
return value;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
|
|
Packit |
29108b |
static GValue *
|
|
Packit |
29108b |
parse_data (xmlNode *a_node, G_GNUC_UNUSED GError **error)
|
|
Packit |
29108b |
{
|
|
Packit |
29108b |
char *str_val;
|
|
Packit |
29108b |
guchar *raw_data;
|
|
Packit |
29108b |
gsize len;
|
|
Packit |
29108b |
GString *data_val;
|
|
Packit |
29108b |
GValue *value;
|
|
Packit |
29108b |
|
|
Packit |
29108b |
str_val = (char *)xmlNodeGetContent(a_node);
|
|
Packit |
29108b |
#if GLIB_CHECK_VERSION(2,12,0)
|
|
Packit |
29108b |
/* base64 support only after GLib 2.12 */
|
|
Packit |
29108b |
raw_data = g_base64_decode (str_val, &len;;
|
|
Packit |
29108b |
#else
|
|
Packit |
29108b |
#warning GLib > 2.12 required for g_base64_decode(). Working around this problem.
|
|
Packit |
29108b |
raw_data = g_strdup ("");
|
|
Packit |
29108b |
len = 0;
|
|
Packit |
29108b |
#endif
|
|
Packit |
29108b |
xmlFree (str_val);
|
|
Packit |
29108b |
data_val = g_string_new_len ((char *)raw_data, len);
|
|
Packit |
29108b |
g_free (raw_data);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
value = g_new0(GValue, 1);
|
|
Packit |
29108b |
g_value_init(value, G_TYPE_GSTRING);
|
|
Packit |
29108b |
g_value_take_boxed (value, data_val);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
return value;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
|
|
Packit |
29108b |
static xmlNode *
|
|
Packit |
29108b |
parse_one_dict_entry (xmlNode *a_node, GHashTable *dict, GError **error)
|
|
Packit |
29108b |
{
|
|
Packit |
29108b |
xmlNode *cur_node = a_node;
|
|
Packit |
29108b |
xmlChar *key_name;
|
|
Packit |
29108b |
GValue *value;
|
|
Packit |
29108b |
|
|
Packit |
29108b |
while ((cur_node != NULL) && (xmlStrcmp(cur_node->name, (xmlChar *)"key") != 0)) {
|
|
Packit |
29108b |
if (!xmlIsBlankNode (cur_node)) {
|
|
Packit |
29108b |
DEBUG ("skipping %s\n", cur_node->name);
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
cur_node = cur_node->next;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
if (cur_node == NULL) {
|
|
Packit |
29108b |
g_set_error (error, ITDB_DEVICE_ERROR, ITDB_DEVICE_ERROR_XML_PARSING,
|
|
Packit |
29108b |
"Dict entry contains no <key> node");
|
|
Packit |
29108b |
return NULL;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
key_name = xmlNodeGetContent (cur_node);
|
|
Packit |
29108b |
cur_node = cur_node->next;
|
|
Packit |
29108b |
while ((cur_node != NULL) && xmlIsBlankNode (cur_node)) {
|
|
Packit |
29108b |
cur_node = cur_node->next;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
if (cur_node == NULL) {
|
|
Packit |
29108b |
g_set_error (error, ITDB_DEVICE_ERROR, ITDB_DEVICE_ERROR_XML_PARSING,
|
|
Packit |
29108b |
"<key> %s with no corresponding value node", key_name);
|
|
Packit |
29108b |
xmlFree (key_name);
|
|
Packit |
29108b |
return NULL;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
|
|
Packit |
29108b |
value = parse_node (cur_node, error);
|
|
Packit |
29108b |
if (value != NULL) {
|
|
Packit |
29108b |
g_hash_table_insert (dict, g_strdup ((char *)key_name), value);
|
|
Packit |
29108b |
} else {
|
|
Packit |
29108b |
g_warning ("Couldn't parse value for %s: %s",
|
|
Packit |
29108b |
key_name, (*error)->message);
|
|
Packit |
29108b |
g_clear_error (error);
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
xmlFree (key_name);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
return cur_node->next;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
|
|
Packit |
29108b |
static GValue *
|
|
Packit |
29108b |
parse_dict (xmlNode *a_node, GError **error)
|
|
Packit |
29108b |
{
|
|
Packit |
29108b |
xmlNode *cur_node = a_node->children;
|
|
Packit |
29108b |
GValue *value;
|
|
Packit |
29108b |
GHashTable *dict;
|
|
Packit |
29108b |
|
|
Packit |
29108b |
dict = g_hash_table_new_full (g_str_hash, g_str_equal,
|
|
Packit |
29108b |
g_free, (GDestroyNotify)value_free);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
while (cur_node != NULL) {
|
|
Packit |
29108b |
if (xmlIsBlankNode (cur_node)) {
|
|
Packit |
29108b |
cur_node = cur_node->next;
|
|
Packit |
29108b |
} else {
|
|
Packit |
29108b |
cur_node = parse_one_dict_entry (cur_node, dict, error);
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
if ((error != NULL) && (*error != NULL)) {
|
|
Packit |
29108b |
g_hash_table_destroy (dict);
|
|
Packit |
29108b |
return NULL;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
value = g_new0 (GValue, 1);
|
|
Packit |
29108b |
value = g_value_init (value, G_TYPE_HASH_TABLE);
|
|
Packit |
29108b |
g_value_take_boxed (value, dict);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
return value;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
|
|
Packit |
29108b |
typedef GValue *(*ParseCallback) (xmlNode *, GError **);
|
|
Packit |
29108b |
static ParseCallback get_parser_for_type (const xmlChar *type);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
static GValue *
|
|
Packit |
29108b |
parse_array (xmlNode *a_node, GError **error)
|
|
Packit |
29108b |
{
|
|
Packit |
29108b |
xmlNode *cur_node = a_node->children;
|
|
Packit |
29108b |
GValue *value;
|
|
Packit |
29108b |
GArray *array;
|
|
Packit |
29108b |
|
|
Packit |
29108b |
array = g_array_new (FALSE, TRUE, sizeof(GValue));
|
|
Packit |
29108b |
g_array_set_clear_func (array, (GDestroyNotify)g_value_unset);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
while (cur_node != NULL) {
|
|
Packit |
29108b |
if (get_parser_for_type (cur_node->name) != NULL) {
|
|
Packit |
29108b |
GValue *cur_value;
|
|
Packit |
29108b |
cur_value = parse_node (cur_node, error);
|
|
Packit |
29108b |
if (cur_value != NULL) {
|
|
Packit |
29108b |
array = g_array_append_vals (array, cur_value, 1);
|
|
Packit |
29108b |
g_free (cur_value);
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
/* When an array contains an element enclosed in "unknown" tags (ie
|
|
Packit |
29108b |
* non-type ones), we silently skip them since early
|
|
Packit |
29108b |
* SysInfoExtended files used to have <key> values enclosed within
|
|
Packit |
29108b |
* <array> tags.
|
|
Packit |
29108b |
*/
|
|
Packit |
29108b |
cur_node = cur_node->next;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
|
|
Packit |
29108b |
if ((error != NULL) && (*error != NULL)) {
|
|
Packit |
29108b |
g_array_unref (array);
|
|
Packit |
29108b |
return NULL;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
value = g_new0 (GValue, 1);
|
|
Packit |
29108b |
value = g_value_init (value, G_TYPE_ARRAY);
|
|
Packit |
29108b |
g_value_take_boxed (value, array);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
return value;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
|
|
Packit |
29108b |
struct Parser {
|
|
Packit |
29108b |
const char * const type_name;
|
|
Packit |
29108b |
ParseCallback parser;
|
|
Packit |
29108b |
};
|
|
Packit |
29108b |
|
|
Packit |
29108b |
static const struct Parser parsers[] = { {"integer", parse_integer},
|
|
Packit |
29108b |
{"real", parse_real},
|
|
Packit |
29108b |
{"string", parse_string},
|
|
Packit |
29108b |
{"true", parse_boolean},
|
|
Packit |
29108b |
{"false", parse_boolean},
|
|
Packit |
29108b |
{"data", parse_data},
|
|
Packit |
29108b |
{"dict", parse_dict},
|
|
Packit |
29108b |
{"array", parse_array},
|
|
Packit |
29108b |
{NULL, NULL} };
|
|
Packit |
29108b |
|
|
Packit |
29108b |
static ParseCallback get_parser_for_type (const xmlChar *type)
|
|
Packit |
29108b |
{
|
|
Packit |
29108b |
guint i = 0;
|
|
Packit |
29108b |
|
|
Packit |
29108b |
while (parsers[i].type_name != NULL) {
|
|
Packit |
29108b |
if (xmlStrcmp (type, (xmlChar *)parsers[i].type_name) == 0) {
|
|
Packit |
29108b |
if (parsers[i].parser != NULL) {
|
|
Packit |
29108b |
return parsers[i].parser;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
i++;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
return NULL;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
|
|
Packit |
29108b |
static GValue *parse_node (xmlNode *a_node, GError **error)
|
|
Packit |
29108b |
{
|
|
Packit |
29108b |
ParseCallback parser;
|
|
Packit |
29108b |
|
|
Packit |
29108b |
g_return_val_if_fail (a_node != NULL, NULL);
|
|
Packit |
29108b |
parser = get_parser_for_type (a_node->name);
|
|
Packit |
29108b |
if (parser != NULL) {
|
|
Packit |
29108b |
return parser (a_node, error);
|
|
Packit |
29108b |
} else {
|
|
Packit |
29108b |
DEBUG ("no parser for <%s>\n", a_node->name);
|
|
Packit |
29108b |
return NULL;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
|
|
Packit |
29108b |
static GValue *
|
|
Packit |
29108b |
itdb_plist_parse (xmlNode * a_node, GError **error)
|
|
Packit |
29108b |
{
|
|
Packit |
29108b |
xmlNode *cur_node;
|
|
Packit |
29108b |
if (a_node == NULL) {
|
|
Packit |
29108b |
g_set_error (error, ITDB_DEVICE_ERROR, ITDB_DEVICE_ERROR_XML_PARSING,
|
|
Packit |
29108b |
"Empty XML document");
|
|
Packit |
29108b |
return NULL;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
if (xmlStrcmp (a_node->name, (xmlChar *)"plist") != 0) {
|
|
Packit |
29108b |
g_set_error (error, ITDB_DEVICE_ERROR, ITDB_DEVICE_ERROR_XML_PARSING,
|
|
Packit |
29108b |
"XML document does not seem to be a plist document");
|
|
Packit |
29108b |
return NULL;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
cur_node = a_node->xmlChildrenNode;
|
|
Packit |
29108b |
while ((cur_node != NULL) && (xmlIsBlankNode (cur_node))) {
|
|
Packit |
29108b |
cur_node = cur_node->next;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
if (cur_node != NULL) {
|
|
Packit |
29108b |
return parse_node (cur_node, error);
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
g_set_error (error, ITDB_DEVICE_ERROR, ITDB_DEVICE_ERROR_XML_PARSING,
|
|
Packit |
29108b |
"Empty XML document");
|
|
Packit |
29108b |
return NULL;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
|
|
Packit |
29108b |
/**
|
|
Packit |
29108b |
* itdb_plist_parse:
|
|
Packit |
29108b |
* @filename: name of the XML plist file to parse
|
|
Packit |
29108b |
* @error: return location for a #GError
|
|
Packit |
29108b |
*
|
|
Packit |
29108b |
* Parses the XML plist file stored in @filename. If an error occurs
|
|
Packit |
29108b |
* during the parsing, itdb_plist_parse will return NULL and @error
|
|
Packit |
29108b |
* will be set
|
|
Packit |
29108b |
*
|
|
Packit |
29108b |
* Returns: NULL on error (@error will be set), a newly allocated
|
|
Packit |
29108b |
* #GValue containing a #GHashTable otherwise.
|
|
Packit |
29108b |
*/
|
|
Packit |
29108b |
GValue *
|
|
Packit |
29108b |
itdb_plist_parse_from_file (const char *filename, GError **error)
|
|
Packit |
29108b |
{
|
|
Packit |
29108b |
xmlDoc *doc = NULL;
|
|
Packit |
29108b |
xmlNode *root_element = NULL;
|
|
Packit |
29108b |
GValue *parsed_doc;
|
|
Packit |
29108b |
|
|
Packit |
29108b |
doc = xmlReadFile(filename, NULL, 0);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
if (doc == NULL) {
|
|
Packit |
29108b |
g_set_error (error, ITDB_DEVICE_ERROR, ITDB_DEVICE_ERROR_XML_PARSING,
|
|
Packit |
29108b |
"Error during XML parsing of file %s", filename);
|
|
Packit |
29108b |
return NULL;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
|
|
Packit |
29108b |
root_element = xmlDocGetRootElement(doc);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
parsed_doc = itdb_plist_parse (root_element, error);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
xmlFreeDoc(doc);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
return parsed_doc;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
|
|
Packit |
29108b |
/**
|
|
Packit |
29108b |
* itdb_plist_parse_from_memory:
|
|
Packit |
29108b |
* @data: memory location containing XML plist data to parse
|
|
Packit |
29108b |
* @len: length in bytes of the string to parse
|
|
Packit |
29108b |
* @error: return location for a #GError
|
|
Packit |
29108b |
*
|
|
Packit |
29108b |
* Parses the XML plist file stored in @data which length is @len
|
|
Packit |
29108b |
* bytes. If an error occurs during the parsing,
|
|
Packit |
29108b |
* itdb_plist_parse_from_memory() will return NULL and @error will be
|
|
Packit |
29108b |
* set.
|
|
Packit |
29108b |
*
|
|
Packit |
29108b |
* Returns: NULL on error (@error will be set), a newly allocated
|
|
Packit |
29108b |
* #GValue containing a #GHashTable otherwise.
|
|
Packit |
29108b |
*/
|
|
Packit |
29108b |
GValue *
|
|
Packit |
29108b |
itdb_plist_parse_from_memory (const char *data, gsize len, GError **error)
|
|
Packit |
29108b |
{
|
|
Packit |
29108b |
xmlDoc *doc = NULL;
|
|
Packit |
29108b |
xmlNode *root_element = NULL;
|
|
Packit |
29108b |
GValue *parsed_doc;
|
|
Packit |
29108b |
|
|
Packit |
29108b |
doc = xmlReadMemory(data, len, "noname.xml", NULL, 0);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
if (doc == NULL) {
|
|
Packit |
29108b |
g_set_error (error, ITDB_DEVICE_ERROR, ITDB_DEVICE_ERROR_XML_PARSING,
|
|
Packit |
29108b |
"Error during XML parsing of in-memory data");
|
|
Packit |
29108b |
return NULL;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
|
|
Packit |
29108b |
root_element = xmlDocGetRootElement(doc);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
parsed_doc = itdb_plist_parse (root_element, error);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
xmlFreeDoc(doc);
|
|
Packit |
29108b |
|
|
Packit |
29108b |
return parsed_doc;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
#else
|
|
Packit |
29108b |
#include <glib-object.h>
|
|
Packit |
29108b |
#include "itdb_plist.h"
|
|
Packit |
29108b |
|
|
Packit |
29108b |
GValue *itdb_plist_parse_from_file (G_GNUC_UNUSED const char *filename,
|
|
Packit |
29108b |
G_GNUC_UNUSED GError **error)
|
|
Packit |
29108b |
{
|
|
Packit |
29108b |
return NULL;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
|
|
Packit |
29108b |
GValue *itdb_plist_parse_from_memory (G_GNUC_UNUSED const char *data,
|
|
Packit |
29108b |
G_GNUC_UNUSED gsize len,
|
|
Packit |
29108b |
G_GNUC_UNUSED GError **error)
|
|
Packit |
29108b |
{
|
|
Packit |
29108b |
return NULL;
|
|
Packit |
29108b |
}
|
|
Packit |
29108b |
#endif
|