Revision: 2066
          http://gtkpod.svn.sourceforge.net/gtkpod/?rev=2066&view=rev
Author:   teuf
Date:     2008-07-29 20:09:30 +0000 (Tue, 29 Jul 2008)

Log Message:
-----------
Add error handling to the plist XML parser

Modified Paths:
--------------
    libgpod/trunk/ChangeLog
    libgpod/trunk/src/itdb_device.c
    libgpod/trunk/src/itdb_plist.c
    libgpod/trunk/src/itdb_plist.h
    libgpod/trunk/src/itdb_sysinfo_extended_parser.c

Modified: libgpod/trunk/ChangeLog
===================================================================
--- libgpod/trunk/ChangeLog     2008-07-27 18:15:24 UTC (rev 2065)
+++ libgpod/trunk/ChangeLog     2008-07-29 20:09:30 UTC (rev 2066)
@@ -1,3 +1,12 @@
+2008-07-27  Christophe Fergeau  <[EMAIL PROTECTED]>
+
+       * src/itdb_device.c: add itdb_device_error_quark()
+       * src/itdb_plist.h:
+       * src/itdb_plist.c: add error handling to XML parsing (using
+       GError)
+       * src/itdb_sysinfo_extended_parser.c: pass a NULL GError to call to
+       plist parsing function
+
 2008-07-26  Christophe Fergeau  <[EMAIL PROTECTED]>
 
        * tests/test-fw-id.c: (main): add missing call to g_type_init

Modified: libgpod/trunk/src/itdb_device.c
===================================================================
--- libgpod/trunk/src/itdb_device.c     2008-07-27 18:15:24 UTC (rev 2065)
+++ libgpod/trunk/src/itdb_device.c     2008-07-29 20:09:30 UTC (rev 2066)
@@ -1691,3 +1691,12 @@
      */
     return g_hash_table_lookup (model_table->serial_hash, serial+len-3);
 }
+
+GQuark itdb_device_error_quark (void)
+{
+    static GQuark quark = 0;
+    if (!quark) {
+        quark = g_quark_from_static_string ("itdb-device-error-quark");
+    }
+    return quark;
+}

Modified: libgpod/trunk/src/itdb_plist.c
===================================================================
--- libgpod/trunk/src/itdb_plist.c      2008-07-27 18:15:24 UTC (rev 2065)
+++ libgpod/trunk/src/itdb_plist.c      2008-07-29 20:09:30 UTC (rev 2066)
@@ -66,7 +66,7 @@
 #define DEBUG(...)
 #endif
 
-static GValue *parse_node (xmlNode *a_node);
+static GValue *parse_node (xmlNode *a_node, GError **error);
 
 static void 
 value_free (GValue *val)
@@ -76,14 +76,21 @@
 }
 
 static GValue * 
-parse_integer(xmlNode *a_node)
+parse_integer(xmlNode *a_node, GError **error)
 {
     char *str_val;
+    char *end_ptr;
     gint int_val;
     GValue *value;
 
     str_val = (char *)xmlNodeGetContent(a_node);
-    int_val = strtol (str_val, NULL, 0);
+    int_val = strtol (str_val, &end_ptr, 0);
+    if (*end_ptr != '\0') {
+        g_set_error (error, ITDB_DEVICE_ERROR, ITDB_DEVICE_ERROR_XML_PARSING,
+                     "invalid integer value: %s", str_val);
+        xmlFree (str_val);
+        return NULL;
+    }
     xmlFree (str_val);
 
     value = g_new0(GValue, 1);
@@ -94,7 +101,7 @@
 }
 
 static GValue * 
-parse_string(xmlNode *a_node)
+parse_string(xmlNode *a_node, G_GNUC_UNUSED GError **error)
 {
     char *str_val;
     GValue *value;
@@ -111,14 +118,21 @@
 }
 
 static GValue *
-parse_real(xmlNode *a_node)
+parse_real(xmlNode *a_node, GError **error)
 {
     char *str_val;
+    char *end_ptr;
     gfloat double_val;
     GValue *value;
 
     str_val = (char *)xmlNodeGetContent(a_node);
-    double_val = g_ascii_strtod (str_val, NULL);
+    double_val = g_ascii_strtod (str_val, &end_ptr);
+    if (*end_ptr != '\0') {
+        g_set_error (error, ITDB_DEVICE_ERROR, ITDB_DEVICE_ERROR_XML_PARSING,
+                     "invalid real value: %s", str_val);
+        xmlFree (str_val);
+        return NULL;
+    }
     xmlFree (str_val);
 
     value = g_new0(GValue, 1);
@@ -129,7 +143,7 @@
 }
 
 static GValue *
-parse_boolean (xmlNode *a_node)
+parse_boolean (xmlNode *a_node, GError **error)
 {
     gboolean bool_val;
     GValue *value;
@@ -139,7 +153,8 @@
     } else if (strcmp ((char *)a_node->name, "false") == 0) {
         bool_val = FALSE;
     } else {
-        DEBUG ("unexpected boolean value\n");
+        g_set_error (error, ITDB_DEVICE_ERROR, ITDB_DEVICE_ERROR_XML_PARSING,
+                     "unexpected boolean value: %s", a_node->name);
         return NULL;
     }
 
@@ -151,7 +166,7 @@
 }
 
 static GValue *
-parse_data (xmlNode *a_node)
+parse_data (xmlNode *a_node, G_GNUC_UNUSED GError **error)
 {
     char *str_val;
     guchar *raw_data;
@@ -173,7 +188,7 @@
 }
 
 static xmlNode *
-parse_one_dict_entry (xmlNode *a_node, GHashTable *dict)
+parse_one_dict_entry (xmlNode *a_node, GHashTable *dict, GError **error)
 {
     xmlNode *cur_node = a_node;
     xmlChar *key_name;
@@ -186,6 +201,8 @@
         cur_node = cur_node->next;
     }
     if (cur_node == NULL) {
+        g_set_error (error, ITDB_DEVICE_ERROR, ITDB_DEVICE_ERROR_XML_PARSING,
+                     "Dict entry contains no <key> node");
         return NULL;
     }
     key_name = xmlNodeGetContent(cur_node);
@@ -194,14 +211,19 @@
         cur_node = cur_node->next;
     }
     if (cur_node == NULL) {
-        DEBUG ("<key> %s with no corresponding value node", key_name);
+        g_set_error (error, ITDB_DEVICE_ERROR, ITDB_DEVICE_ERROR_XML_PARSING,
+                     "<key> %s with no corresponding value node", key_name);
         xmlFree (key_name);
         return NULL;
     }
 
-    value = parse_node (cur_node);
+    value = parse_node (cur_node, error);
     if (value != NULL) {
         g_hash_table_insert (dict, g_strdup ((char *)key_name), value);
+    } else {
+        g_warning ("Couldn't parse value for %s: %s",
+                   key_name, (*error)->message);
+        g_clear_error (error);
     }
     xmlFree (key_name);
 
@@ -209,7 +231,7 @@
 }
 
 static GValue * 
-parse_dict (xmlNode *a_node)
+parse_dict (xmlNode *a_node, GError **error)
 {
     xmlNode *cur_node = a_node->children;
     GValue *value;
@@ -219,9 +241,11 @@
                                   g_free, (GDestroyNotify)value_free);
 
     while (cur_node != NULL) {
-        cur_node = parse_one_dict_entry (cur_node, dict);
+        cur_node = parse_one_dict_entry (cur_node, dict, error);
     }
-
+    if ((error != NULL) && (*error != NULL)) {
+        return NULL;
+    }
     value = g_new0 (GValue, 1);
     value = g_value_init (value, G_TYPE_HASH_TABLE);
     g_value_take_boxed (value, dict);
@@ -229,7 +253,7 @@
     return value;
 }
 
-typedef GValue *(*ParseCallback) (xmlNode *);
+typedef GValue *(*ParseCallback) (xmlNode *, GError **);
 struct Parser {
     const char * const type_name;
     ParseCallback parser;
@@ -245,14 +269,14 @@
                                    {"array",   parse_dict},
                                    {NULL,      NULL} };
 
-static GValue *parse_node (xmlNode *a_node)
+static GValue *parse_node (xmlNode *a_node, GError **error)
 {
     guint i = 0;
     g_return_val_if_fail (a_node != NULL, FALSE);
     while (parsers[i].type_name != NULL) {        
         if (xmlStrcmp (a_node->name, (xmlChar *)parsers[i].type_name) == 0) {
             if (parsers[i].parser != NULL) {
-                return parsers[i].parser (a_node);
+                return parsers[i].parser (a_node, error);
             }
         }
         i++;
@@ -262,15 +286,17 @@
 }
 
 static GValue *
-itdb_plist_parse (xmlNode * a_node)
+itdb_plist_parse (xmlNode * a_node, GError **error)
 {
     xmlNode *cur_node;
     if (a_node == NULL) {
-        DEBUG ("empty file\n");
+        g_set_error (error, ITDB_DEVICE_ERROR, ITDB_DEVICE_ERROR_XML_PARSING,
+                     "Empty XML document");
         return NULL;
     }
     if (xmlStrcmp (a_node->name, (xmlChar *)"plist") != 0) {
-        DEBUG ("not a plist file\n");
+        g_set_error (error, ITDB_DEVICE_ERROR, ITDB_DEVICE_ERROR_XML_PARSING,
+                     "XML document does not seem to be a plist document");
         return NULL;
     }
     cur_node = a_node->xmlChildrenNode;
@@ -278,13 +304,15 @@
         cur_node = cur_node->next;
     }
     if (cur_node != NULL) {
-        return parse_node (cur_node);
+        return parse_node (cur_node, error);
     }
+    g_set_error (error, ITDB_DEVICE_ERROR, ITDB_DEVICE_ERROR_XML_PARSING,
+                 "Empty XML document");
     return NULL;
 }
 
 GValue *
-itdb_plist_parse_from_file (const char *filename)
+itdb_plist_parse_from_file (const char *filename, GError **error)
 {
     xmlDoc *doc = NULL;
     xmlNode *root_element = NULL;
@@ -293,13 +321,14 @@
     doc = xmlReadFile(filename, NULL, 0);
 
     if (doc == NULL) {
-        printf("error: could not parse file %s\n", filename);
+        g_set_error (error, ITDB_DEVICE_ERROR, ITDB_DEVICE_ERROR_XML_PARSING,
+                     "Error during XML parsing of file %s", filename);
         return NULL;
     }
 
     root_element = xmlDocGetRootElement(doc);
 
-    parsed_doc = itdb_plist_parse (root_element);
+    parsed_doc = itdb_plist_parse (root_element, error);
 
     xmlFreeDoc(doc);
     xmlCleanupParser();
@@ -308,7 +337,7 @@
 }
 
 GValue *
-itdb_plist_parse_from_memory (const char *data, gsize len)
+itdb_plist_parse_from_memory (const char *data, gsize len, GError **error)
 {
     xmlDoc *doc = NULL;
     xmlNode *root_element = NULL;
@@ -317,13 +346,14 @@
     doc = xmlReadMemory(data, len, "noname.xml", NULL, 0);
 
     if (doc == NULL) {
-        printf("error: could not parse data from memory\n");
+        g_set_error (error, ITDB_DEVICE_ERROR, ITDB_DEVICE_ERROR_XML_PARSING,
+                     "Error during XML parsing of in-memory data");
         return NULL;
     }
 
     root_element = xmlDocGetRootElement(doc);
 
-    parsed_doc = itdb_plist_parse (root_element);
+    parsed_doc = itdb_plist_parse (root_element, error);
 
     xmlFreeDoc(doc);
     xmlCleanupParser();
@@ -334,13 +364,15 @@
 #include <glib-object.h>
 #include "itdb_plist.h"
 
-GValue *itdb_plist_parse_from_file (G_GNUC_UNUSED const char *filename)
+GValue *itdb_plist_parse_from_file (G_GNUC_UNUSED const char *filename,
+                                    G_GNUC_UNUSED GError **error)
 {
     return NULL;
 }
 
 GValue *itdb_plist_parse_from_memory (G_GNUC_UNUSED const char *data, 
-                                      G_GNUC_UNUSED gsize len)
+                                      G_GNUC_UNUSED gsize len,
+                                      G_GNUC_UNUSED GError **error)
 {
     return NULL;
 }

Modified: libgpod/trunk/src/itdb_plist.h
===================================================================
--- libgpod/trunk/src/itdb_plist.h      2008-07-27 18:15:24 UTC (rev 2065)
+++ libgpod/trunk/src/itdb_plist.h      2008-07-29 20:09:30 UTC (rev 2066)
@@ -33,9 +33,21 @@
 
 G_BEGIN_DECLS
 
-G_GNUC_INTERNAL GValue *itdb_plist_parse_from_file (const char *filename);
+typedef enum {
+       ITDB_DEVICE_ERROR_XML_PARSING
+} ItdbDeviceError;
+
+/* Error domain */
+#define ITDB_DEVICE_ERROR itdb_device_error_quark ()
+GQuark     itdb_device_error_quark      (void);
+
+
+
+G_GNUC_INTERNAL GValue *itdb_plist_parse_from_file (const char *filename,
+                                                   GError **error);
 G_GNUC_INTERNAL GValue *itdb_plist_parse_from_memory (const char *data, 
-                                                      gsize len); 
+                                                      gsize len,
+                                                     GError **error); 
 
 G_END_DECLS
 

Modified: libgpod/trunk/src/itdb_sysinfo_extended_parser.c
===================================================================
--- libgpod/trunk/src/itdb_sysinfo_extended_parser.c    2008-07-27 18:15:24 UTC 
(rev 2065)
+++ libgpod/trunk/src/itdb_sysinfo_extended_parser.c    2008-07-29 20:09:30 UTC 
(rev 2066)
@@ -507,7 +507,7 @@
 
     g_return_val_if_fail (filename != NULL, NULL);
 
-    parsed_doc = itdb_plist_parse_from_file (filename);
+    parsed_doc = itdb_plist_parse_from_file (filename, NULL);
     if (parsed_doc == NULL) {
         return NULL;
     }


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
gtkpod-cvs2 mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/gtkpod-cvs2

Reply via email to