Merge branch '1035-bookmarks-state-machine' into 'master'

gbookmarkfile: Fix error reporting with unexpected nesting of elements

Closes #1035

See merge request GNOME/glib!207
diff --git a/glib/gbookmarkfile.c b/glib/gbookmarkfile.c
index 1636af7..e6f885e 100644
--- a/glib/gbookmarkfile.c
+++ b/glib/gbookmarkfile.c
@@ -210,7 +210,7 @@
 };
 
 /* parser state machine */
-enum
+typedef enum
 {
   STATE_STARTED        = 0,
   
@@ -228,7 +228,7 @@
   STATE_ICON,
   
   STATE_FINISHED
-};
+} ParserState;
 
 static void          g_bookmark_file_init        (GBookmarkFile  *bookmark);
 static void          g_bookmark_file_clear       (GBookmarkFile  *bookmark);
@@ -681,7 +681,7 @@
 
 struct _ParseData
 {
-  gint state;
+  ParserState state;
   
   GHashTable *namespaces;
   
@@ -1083,6 +1083,43 @@
 #define IS_ELEMENT(p,s,e)	(is_element_full ((p), (s), NULL, (e), '\0'))
 #define IS_ELEMENT_NS(p,s,n,e)	(is_element_full ((p), (s), (n), (e), '|'))
 
+static const gchar *
+parser_state_to_element_name (ParserState state)
+{
+  switch (state)
+    {
+    case STATE_STARTED:
+    case STATE_FINISHED:
+      return "(top-level)";
+    case STATE_ROOT:
+      return XBEL_ROOT_ELEMENT;
+    case STATE_BOOKMARK:
+      return XBEL_BOOKMARK_ELEMENT;
+    case STATE_TITLE:
+      return XBEL_TITLE_ELEMENT;
+    case STATE_DESC:
+      return XBEL_DESC_ELEMENT;
+    case STATE_INFO:
+      return XBEL_INFO_ELEMENT;
+    case STATE_METADATA:
+      return XBEL_METADATA_ELEMENT;
+    case STATE_APPLICATIONS:
+      return BOOKMARK_APPLICATIONS_ELEMENT;
+    case STATE_APPLICATION:
+      return BOOKMARK_APPLICATION_ELEMENT;
+    case STATE_GROUPS:
+      return BOOKMARK_GROUPS_ELEMENT;
+    case STATE_GROUP:
+      return BOOKMARK_GROUP_ELEMENT;
+    case STATE_MIME:
+      return MIME_TYPE_ELEMENT;
+    case STATE_ICON:
+      return BOOKMARK_ICON_ELEMENT;
+    default:
+      g_assert_not_reached ();
+    }
+}
+
 static void
 start_element_raw_cb (GMarkupParseContext *context,
                       const gchar         *element_name,
@@ -1263,8 +1300,23 @@
         	     element_name,
         	     BOOKMARK_GROUP_ELEMENT);
       break;
+
+    case STATE_TITLE:
+    case STATE_DESC:
+    case STATE_APPLICATION:
+    case STATE_GROUP:
+    case STATE_MIME:
+    case STATE_ICON:
+    case STATE_FINISHED:
+      g_set_error (error, G_MARKUP_ERROR,
+                   G_MARKUP_ERROR_INVALID_CONTENT,
+                   _("Unexpected tag “%s” inside “%s”"),
+                   element_name,
+                   parser_state_to_element_name (parse_data->state));
+      break;
+
     default:
-      g_warn_if_reached ();
+      g_assert_not_reached ();
       break;
     }
 }
diff --git a/glib/tests/Makefile.am b/glib/tests/Makefile.am
index 4c822bf..2a53ae6 100644
--- a/glib/tests/Makefile.am
+++ b/glib/tests/Makefile.am
@@ -143,6 +143,27 @@
 	bookmarks/fail-15.xbel \
 	bookmarks/fail-16.xbel \
 	bookmarks/fail-17.xbel \
+	bookmarks/fail-18.xbel \
+	bookmarks/fail-19.xbel \
+	bookmarks/fail-20.xbel \
+	bookmarks/fail-21.xbel \
+	bookmarks/fail-22.xbel \
+	bookmarks/fail-23.xbel \
+	bookmarks/fail-24.xbel \
+	bookmarks/fail-25.xbel \
+	bookmarks/fail-26.xbel \
+	bookmarks/fail-27.xbel \
+	bookmarks/fail-28.xbel \
+	bookmarks/fail-29.xbel \
+	bookmarks/fail-30.xbel \
+	bookmarks/fail-31.xbel \
+	bookmarks/fail-32.xbel \
+	bookmarks/fail-33.xbel \
+	bookmarks/fail-34.xbel \
+	bookmarks/fail-35.xbel \
+	bookmarks/fail-36.xbel \
+	bookmarks/fail-37.xbel \
+	bookmarks/fail-38.xbel \
 	bookmarks/valid-01.xbel \
 	bookmarks/valid-02.xbel \
 	bookmarks/valid-03.xbel \
diff --git a/glib/tests/bookmarks/fail-18.xbel b/glib/tests/bookmarks/fail-18.xbel
new file mode 100644
index 0000000..10f3d80
--- /dev/null
+++ b/glib/tests/bookmarks/fail-18.xbel
@@ -0,0 +1 @@
+<?><!DOCTYPE><xbel version="1.0"xmlns:bookmark="http://www.freedesktop.org/standards/desktop-bookmarks"><title><bookmark:application c=""/><bookmark:application name=""exec=""/
\ No newline at end of file
diff --git a/glib/tests/bookmarks/fail-19.xbel b/glib/tests/bookmarks/fail-19.xbel
new file mode 100644
index 0000000..ab4edbb
--- /dev/null
+++ b/glib/tests/bookmarks/fail-19.xbel
@@ -0,0 +1 @@
+<?><!DOCTYPE><xbel version="1.0"xmlns:mime="http://www.freedesktop.org/standards/shared-mime-info"xmlns:bookmark="http://www.freedesktop.org/standards/desktop-bookmarks"><title><mime:mime-type></mime:mime-type><bookmark:applications><bookmark:application name=""exec=""/
\ No newline at end of file
diff --git a/glib/tests/bookmarks/fail-20.xbel b/glib/tests/bookmarks/fail-20.xbel
new file mode 100644
index 0000000..a00e154
--- /dev/null
+++ b/glib/tests/bookmarks/fail-20.xbel
@@ -0,0 +1 @@
+<?><!DOCTYPE<<><>>></
\ No newline at end of file
diff --git a/glib/tests/bookmarks/fail-21.xbel b/glib/tests/bookmarks/fail-21.xbel
new file mode 100644
index 0000000..cf7fbf4
--- /dev/null
+++ b/glib/tests/bookmarks/fail-21.xbel
@@ -0,0 +1 @@
+<?><!DOCTYPE><xbel version="1.0"xmlns:bookmark="http://www.freedesktop.org/standards/desktop-bookmarks"><title><bookmark:application e=""/><bookmark:application name=""exec=""/
\ No newline at end of file
diff --git a/glib/tests/bookmarks/fail-22.xbel b/glib/tests/bookmarks/fail-22.xbel
new file mode 100644
index 0000000..abc4ceb
--- /dev/null
+++ b/glib/tests/bookmarks/fail-22.xbel
@@ -0,0 +1 @@
+<?><!DOCTYPE><xbel version="1.0"xmlns:bookmark="http://www.freedesktop.org/standards/desktop-bookmarks"><title><bookmark:application e=""/><bookmark:application name=""exec="">
\ No newline at end of file
diff --git a/glib/tests/bookmarks/fail-23.xbel b/glib/tests/bookmarks/fail-23.xbel
new file mode 100644
index 0000000..35324ad
--- /dev/null
+++ b/glib/tests/bookmarks/fail-23.xbel
@@ -0,0 +1 @@
+</
\ No newline at end of file
diff --git a/glib/tests/bookmarks/fail-24.xbel b/glib/tests/bookmarks/fail-24.xbel
new file mode 100644
index 0000000..a8726e6
--- /dev/null
+++ b/glib/tests/bookmarks/fail-24.xbel
@@ -0,0 +1 @@
+<?><!DOCTYPE><xbel version="1.0"xmlns:bookmark="http://www.freedesktop.org/standards/desktop-bookmarks"><title><bookmark:application n=""/><bookmark:application name=""exec="">
\ No newline at end of file
diff --git a/glib/tests/bookmarks/fail-25.xbel b/glib/tests/bookmarks/fail-25.xbel
new file mode 100644
index 0000000..e9bc439
--- /dev/null
+++ b/glib/tests/bookmarks/fail-25.xbel
@@ -0,0 +1 @@
+<?><!DOCTYPE><xbel version="1.0"xmlns:bookmark="http://www.freedesktop.org/standards/desktop-bookmarks"><title><bookmark:applications></bookmark:applications><bookmark:groups><bookmark:group><
\ No newline at end of file
diff --git a/glib/tests/bookmarks/fail-26.xbel b/glib/tests/bookmarks/fail-26.xbel
new file mode 100644
index 0000000..739aca2
--- /dev/null
+++ b/glib/tests/bookmarks/fail-26.xbel
@@ -0,0 +1 @@
+<?><!DOCTYPE<><>></
\ No newline at end of file
diff --git a/glib/tests/bookmarks/fail-27.xbel b/glib/tests/bookmarks/fail-27.xbel
new file mode 100644
index 0000000..e402095
--- /dev/null
+++ b/glib/tests/bookmarks/fail-27.xbel
@@ -0,0 +1 @@
+<?><!DOCTYPE><xbel version="1.0"xmlns:bookmark="http://www.freedesktop.org/standards/desktop-bookmarks"f=""><title><bookmark:application e=""/><bookmark:application name=""exec=""/
\ No newline at end of file
diff --git a/glib/tests/bookmarks/fail-28.xbel b/glib/tests/bookmarks/fail-28.xbel
new file mode 100644
index 0000000..131a97a
--- /dev/null
+++ b/glib/tests/bookmarks/fail-28.xbel
@@ -0,0 +1 @@
+<?><!DOCTYPE<><><>></
\ No newline at end of file
diff --git a/glib/tests/bookmarks/fail-29.xbel b/glib/tests/bookmarks/fail-29.xbel
new file mode 100644
index 0000000..2cdcf9f
--- /dev/null
+++ b/glib/tests/bookmarks/fail-29.xbel
@@ -0,0 +1 @@
+<?></
\ No newline at end of file
diff --git a/glib/tests/bookmarks/fail-30.xbel b/glib/tests/bookmarks/fail-30.xbel
new file mode 100644
index 0000000..982ea10
--- /dev/null
+++ b/glib/tests/bookmarks/fail-30.xbel
@@ -0,0 +1 @@
+<?><!DOCTYPE<><<>><>></
\ No newline at end of file
diff --git a/glib/tests/bookmarks/fail-31.xbel b/glib/tests/bookmarks/fail-31.xbel
new file mode 100644
index 0000000..4b46cba
--- /dev/null
+++ b/glib/tests/bookmarks/fail-31.xbel
@@ -0,0 +1 @@
+<?><!DOCTYPE<><<>>></
\ No newline at end of file
diff --git a/glib/tests/bookmarks/fail-32.xbel b/glib/tests/bookmarks/fail-32.xbel
new file mode 100644
index 0000000..d6de333
--- /dev/null
+++ b/glib/tests/bookmarks/fail-32.xbel
@@ -0,0 +1 @@
+<?><!DOCTYPE></
\ No newline at end of file
diff --git a/glib/tests/bookmarks/fail-33.xbel b/glib/tests/bookmarks/fail-33.xbel
new file mode 100644
index 0000000..a72c6ff
--- /dev/null
+++ b/glib/tests/bookmarks/fail-33.xbel
@@ -0,0 +1 @@
+<?><!DOCTYPE<><><><>></
\ No newline at end of file
diff --git a/glib/tests/bookmarks/fail-34.xbel b/glib/tests/bookmarks/fail-34.xbel
new file mode 100644
index 0000000..88214d9
--- /dev/null
+++ b/glib/tests/bookmarks/fail-34.xbel
@@ -0,0 +1 @@
+<?><!DOCTYPE<<>>></
\ No newline at end of file
diff --git a/glib/tests/bookmarks/fail-35.xbel b/glib/tests/bookmarks/fail-35.xbel
new file mode 100644
index 0000000..2f8fd10
--- /dev/null
+++ b/glib/tests/bookmarks/fail-35.xbel
@@ -0,0 +1 @@
+<?><!DOCTYPE><xbel version="1.0"xmlns:mime="http://www.freedesktop.org/standards/shared-mime-info"m=""><title><mime:mime-type></mime:mime-type><mime:mime-type>
\ No newline at end of file
diff --git a/glib/tests/bookmarks/fail-36.xbel b/glib/tests/bookmarks/fail-36.xbel
new file mode 100644
index 0000000..7949a3b
--- /dev/null
+++ b/glib/tests/bookmarks/fail-36.xbel
@@ -0,0 +1 @@
+<?><!DOCTYPE><xbel version="1.0"xmlns:mime="http://www.freedesktop.org/standards/shared-mime-info"xmlns:bookmark="http://www.freedesktop.org/standards/desktop-bookmarks"><title><mime:mime-type></mime:mime-type><bookmark:applications><application name=""exec="">
\ No newline at end of file
diff --git a/glib/tests/bookmarks/fail-37.xbel b/glib/tests/bookmarks/fail-37.xbel
new file mode 100644
index 0000000..785f3b1
--- /dev/null
+++ b/glib/tests/bookmarks/fail-37.xbel
@@ -0,0 +1 @@
+<?><!DOCTYPE><xbel version="1.0"xmlns:mime="http://www.freedesktop.org/standards/shared-mime-info"xmlns:bookmark="http://www.freedesktop.org/standards/desktop-bookmarks"><title><mime:mime-type></mime:mime-type><bookmark:applications><bookmark:application name=""exec="">
\ No newline at end of file
diff --git a/glib/tests/bookmarks/fail-38.xbel b/glib/tests/bookmarks/fail-38.xbel
new file mode 100644
index 0000000..9ef34f3
--- /dev/null
+++ b/glib/tests/bookmarks/fail-38.xbel
@@ -0,0 +1 @@
+<?><!DOCTYPE><xbel x=""/><o xmlns:bookmark="http://www.freedesktop.org/standards/desktop-bookmarks"><bookmark:application e=""/><bookmark:application name=""exec=""/
\ No newline at end of file