[glib/new-gsettings] clean up schema compiler



commit a3f3392d7206c66f0252cff51d21bcc1bc46e3bd
Author: Ryan Lortie <desrt desrt ca>
Date:   Thu Apr 15 23:31:24 2010 -0400

    clean up schema compiler
    
    enforce key name restrictions

 gio/gschema-compile.c          |  132 +++++++++++++++++++++++++++++++++++-----
 gio/tests/gsettings.c          |   88 +++++++++++++-------------
 gio/tests/org.gtk.test.gschema |   32 +++++-----
 3 files changed, 176 insertions(+), 76 deletions(-)
---
diff --git a/gio/gschema-compile.c b/gio/gschema-compile.c
index 49eda8d..c074c4a 100644
--- a/gio/gschema-compile.c
+++ b/gio/gschema-compile.c
@@ -1,3 +1,24 @@
+/*
+ * Copyright © 2010 Codethink Limited
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the licence, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Ryan Lortie <desrt desrt ca>
+ */
+
 #include <string.h>
 #include <unistd.h>
 #include <stdio.h>
@@ -28,6 +49,67 @@ typedef struct
   GVariantType *type;
 } ParseState;
 
+static gboolean
+is_valid_keyname (const gchar  *key,
+                  GError      **error)
+{
+  gint i;
+
+  if (key[0] == '\0')
+    {
+      g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+                   "empty names are not permitted");
+      return FALSE;
+    }
+
+  if (!g_ascii_islower (key[0]))
+    {
+      g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+                   "invalid name '%s': names must begin "
+                   "with a lowercase letter", key);
+      return FALSE;
+    }
+
+  for (i = 1; key[i]; i++)
+    {
+      if (key[i] != '-' &&
+          !g_ascii_islower (key[i]) &&
+          !g_ascii_isdigit (key[i]))
+        {
+          g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+                       "invalid name '%s': invalid character '%c'; "
+                       "only lowercase letters, numbers and dash ('-') "
+                       "are permitted.", key, key[i]);
+          return FALSE;
+        }
+
+      if (key[i] == '-' && key[i + 1] == '-')
+        {
+          g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+                       "invalid name '%s': two successive dashes ('--') are "
+                       "not permitted.", key);
+          return FALSE;
+        }
+    }
+
+  if (key[i - 1] == '-')
+    {
+      g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+                   "invalid name '%s': the last character may not be a "
+                   "dash ('-').", key);
+      return FALSE;
+    }
+
+  if (i > 32)
+    {
+      g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+                   "invalid name '%s': maximum length is 32", key);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
 static void
 start_element (GMarkupParseContext  *context,
                const gchar          *element_name,
@@ -98,22 +180,31 @@ start_element (GMarkupParseContext  *context,
 
           if (COLLECT (STRING, "name", &name, STRING, "type", &type))
             {
+              if (!is_valid_keyname (name, error))
+                return;
+
               if (!g_hash_table_lookup (state->schema, name))
                 {
                   state->key = gvdb_hash_table_insert (state->schema, name);
                   gvdb_item_set_parent (state->key, state->schema_root);
                 }
               else
-                g_set_error (error, G_MARKUP_ERROR,
-                             G_MARKUP_ERROR_INVALID_CONTENT,
-                             "<key name='%s'> already specified", name);
+                {
+                  g_set_error (error, G_MARKUP_ERROR,
+                               G_MARKUP_ERROR_INVALID_CONTENT,
+                               "<key name='%s'> already specified", name);
+                  return;
+                }
 
               if (g_variant_type_string_is_valid (type))
                 state->type = g_variant_type_new (type);
               else
-                g_set_error (error, G_MARKUP_ERROR,
-                             G_MARKUP_ERROR_INVALID_CONTENT,
-                             "invalid GVariant type string");
+                {
+                  g_set_error (error, G_MARKUP_ERROR,
+                               G_MARKUP_ERROR_INVALID_CONTENT,
+                               "invalid GVariant type string '%s'", type);
+                  return;
+                }
 
               g_variant_builder_init (&state->key_options,
                                       G_VARIANT_TYPE ("a{sv}"));
@@ -129,6 +220,9 @@ start_element (GMarkupParseContext  *context,
             {
               gchar *childname;
 
+              if (!is_valid_keyname (name, error))
+                return;
+
               childname = g_strconcat (name, "/", NULL);
 
               if (!g_hash_table_lookup (state->schema, childname))
@@ -178,20 +272,26 @@ start_element (GMarkupParseContext  *context,
                       else if (strcmp (l10n, "time") == 0)
                         state->l10n = 't';
                       else
-                        g_set_error (error, G_MARKUP_ERROR,
-                                     G_MARKUP_ERROR_INVALID_CONTENT,
-                                     "unsupported l10n category: %s", l10n);
+                        {
+                          g_set_error (error, G_MARKUP_ERROR,
+                                       G_MARKUP_ERROR_INVALID_CONTENT,
+                                       "unsupported l10n category: %s", l10n);
+                          return;
+                        }
                     }
                 }
               else
                 {
                   state->l10n = '\0';
 
-                   if (state->context != NULL)
-                     g_set_error (error, G_MARKUP_ERROR,
-                                  G_MARKUP_ERROR_INVALID_CONTENT,
-                                  "translation context given for "
-                                  " value without l10n enabled");
+                  if (state->context != NULL)
+                    {
+                      g_set_error (error, G_MARKUP_ERROR,
+                                   G_MARKUP_ERROR_INVALID_CONTENT,
+                                   "translation context given for "
+                                   " value without l10n enabled");
+                      return;
+                    }
                 }
 
               state->string = g_string_new (NULL);
@@ -240,11 +340,11 @@ start_element (GMarkupParseContext  *context,
     }
 
   if (container)
-    g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, 
+    g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
                  "Element <%s> not allowed inside <%s>\n",
                  element_name, container);
   else
-    g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, 
+    g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
                  "Element <%s> not allowed at toplevel\n", element_name);
 }
 
diff --git a/gio/tests/gsettings.c b/gio/tests/gsettings.c
index 065deac..981e0d4 100644
--- a/gio/tests/gsettings.c
+++ b/gio/tests/gsettings.c
@@ -119,91 +119,91 @@ test_basic_types (void)
 
   settings = g_settings_new ("org.gtk.test.basic-types");
 
-  g_settings_get (settings, "test_boolean", "b", &b);
+  g_settings_get (settings, "test-boolean", "b", &b);
   g_assert_cmpint (b, ==, 1);
 
-  g_settings_set (settings, "test_boolean", "b", 0);
-  g_settings_get (settings, "test_boolean", "b", &b);
+  g_settings_set (settings, "test-boolean", "b", 0);
+  g_settings_get (settings, "test-boolean", "b", &b);
   g_assert_cmpint (b, ==, 0);
 
-  g_settings_get (settings, "test_byte", "y", &byte);
+  g_settings_get (settings, "test-byte", "y", &byte);
   g_assert_cmpint (byte, ==, 25);
 
-  g_settings_set (settings, "test_byte", "y", G_MAXUINT8);
-  g_settings_get (settings, "test_byte", "y", &byte);
+  g_settings_set (settings, "test-byte", "y", G_MAXUINT8);
+  g_settings_get (settings, "test-byte", "y", &byte);
   g_assert_cmpint (byte, ==, G_MAXUINT8);
 
-  g_settings_get (settings, "test_int16", "n", &i16);
+  g_settings_get (settings, "test-int16", "n", &i16);
   g_assert_cmpint (i16, ==, -1234);
 
-  g_settings_set (settings, "test_int16", "n", G_MININT16);
-  g_settings_get (settings, "test_int16", "n", &i16);
+  g_settings_set (settings, "test-int16", "n", G_MININT16);
+  g_settings_get (settings, "test-int16", "n", &i16);
   g_assert_cmpint (i16, ==, G_MININT16);
 
-  g_settings_set (settings, "test_int16", "n", G_MAXINT16);
-  g_settings_get (settings, "test_int16", "n", &i16);
+  g_settings_set (settings, "test-int16", "n", G_MAXINT16);
+  g_settings_get (settings, "test-int16", "n", &i16);
   g_assert_cmpint (i16, ==, G_MAXINT16);
 
-  g_settings_get (settings, "test_uint16", "q", &u16);
+  g_settings_get (settings, "test-uint16", "q", &u16);
   g_assert_cmpuint (u16, ==, 1234);
 
-  g_settings_set (settings, "test_uint16", "q", G_MAXUINT16);
-  g_settings_get (settings, "test_uint16", "q", &u16);
+  g_settings_set (settings, "test-uint16", "q", G_MAXUINT16);
+  g_settings_get (settings, "test-uint16", "q", &u16);
   g_assert_cmpuint (u16, ==, G_MAXUINT16);
 
-  g_settings_get (settings, "test_int32", "i", &i32);
+  g_settings_get (settings, "test-int32", "i", &i32);
   g_assert_cmpint (i32, ==, -123456);
 
-  g_settings_set (settings, "test_int32", "i", G_MININT32);
-  g_settings_get (settings, "test_int32", "i", &i32);
+  g_settings_set (settings, "test-int32", "i", G_MININT32);
+  g_settings_get (settings, "test-int32", "i", &i32);
   g_assert_cmpint (i32, ==, G_MININT32);
 
-  g_settings_set (settings, "test_int32", "i", G_MAXINT32);
-  g_settings_get (settings, "test_int32", "i", &i32);
+  g_settings_set (settings, "test-int32", "i", G_MAXINT32);
+  g_settings_get (settings, "test-int32", "i", &i32);
   g_assert_cmpint (i32, ==, G_MAXINT32);
 
-  g_settings_get (settings, "test_uint32", "u", &u32);
+  g_settings_get (settings, "test-uint32", "u", &u32);
   g_assert_cmpuint (u32, ==, 123456);
 
-  g_settings_set (settings, "test_uint32", "u", G_MAXUINT32);
-  g_settings_get (settings, "test_uint32", "u", &u32);
+  g_settings_set (settings, "test-uint32", "u", G_MAXUINT32);
+  g_settings_get (settings, "test-uint32", "u", &u32);
   g_assert_cmpuint (u32, ==, G_MAXUINT32);
 
-  g_settings_get (settings, "test_int64", "x", &i64);
+  g_settings_get (settings, "test-int64", "x", &i64);
   g_assert_cmpuint (i64, ==, -123456789);
 
-  g_settings_set (settings, "test_int64", "x", G_MININT64);
-  g_settings_get (settings, "test_int64", "x", &i64);
+  g_settings_set (settings, "test-int64", "x", G_MININT64);
+  g_settings_get (settings, "test-int64", "x", &i64);
   g_assert_cmpuint (i64, ==, G_MININT64);
 
-  g_settings_set (settings, "test_int64", "x", G_MAXINT64);
-  g_settings_get (settings, "test_int64", "x", &i64);
+  g_settings_set (settings, "test-int64", "x", G_MAXINT64);
+  g_settings_get (settings, "test-int64", "x", &i64);
   g_assert_cmpuint (i64, ==, G_MAXINT64);
 
-  g_settings_get (settings, "test_uint64", "t", &u64);
+  g_settings_get (settings, "test-uint64", "t", &u64);
   g_assert_cmpuint (u64, ==, 123456789);
 
-  g_settings_set (settings, "test_uint64", "t", G_MAXUINT64);
-  g_settings_get (settings, "test_uint64", "t", &u64);
+  g_settings_set (settings, "test-uint64", "t", G_MAXUINT64);
+  g_settings_get (settings, "test-uint64", "t", &u64);
   g_assert_cmpuint (u64, ==, G_MAXUINT64);
 
-  g_settings_get (settings, "test_double", "d", &d);
+  g_settings_get (settings, "test-double", "d", &d);
   g_assert_cmpfloat (d, ==, 123.456);
 
-  g_settings_set (settings, "test_double", "d", G_MINDOUBLE);
-  g_settings_get (settings, "test_double", "d", &d);
+  g_settings_set (settings, "test-double", "d", G_MINDOUBLE);
+  g_settings_get (settings, "test-double", "d", &d);
   g_assert_cmpfloat (d, ==, G_MINDOUBLE);
 
-  g_settings_set (settings, "test_double", "d", G_MAXDOUBLE);
-  g_settings_get (settings, "test_double", "d", &d);
+  g_settings_set (settings, "test-double", "d", G_MAXDOUBLE);
+  g_settings_get (settings, "test-double", "d", &d);
   g_assert_cmpfloat (d, ==, G_MAXDOUBLE);
 
-  g_settings_get (settings, "test_string", "s", &str);
+  g_settings_get (settings, "test-string", "s", &str);
   g_assert_cmpstr (str, ==, "a string, it seems");
   g_free (str);
   str = NULL;
 
-  g_settings_get (settings, "test_objectpath", "o", &str);
+  g_settings_get (settings, "test-objectpath", "o", &str);
   g_assert_cmpstr (str, ==, "/a/object/path");
   g_free (str);
   str = NULL;
@@ -219,22 +219,22 @@ test_complex_types (void)
 
   settings = g_settings_new ("org.gtk.test.complex-types");
 
-  g_settings_get (settings, "test_tuple", "(s(ii))", &s, &i1, &i2);
+  g_settings_get (settings, "test-tuple", "(s(ii))", &s, &i1, &i2);
   g_assert_cmpstr (s, ==, "one");
   g_assert_cmpint (i1,==, 2);
   g_assert_cmpint (i2,==, 3);
-  g_free (s);
+  g_free (s) ;
   s = NULL;
 
-  g_settings_set (settings, "test_tuple", "(s(ii))", "none", 0, 0);
-  g_settings_get (settings, "test_tuple", "(s(ii))", &s, &i1, &i2);
+  g_settings_set (settings, "test-tuple", "(s(ii))", "none", 0, 0);
+  g_settings_get (settings, "test-tuple", "(s(ii))", &s, &i1, &i2);
   g_assert_cmpstr (s, ==, "none");
   g_assert_cmpint (i1,==, 0);
   g_assert_cmpint (i2,==, 0);
   g_free (s);
   s = NULL;
 
-  g_settings_get (settings, "test_array", "ai", &iter);
+  g_settings_get (settings, "test-array", "ai", &iter);
   g_assert_cmpint (g_variant_iter_n_children (iter), ==, 6);
   g_assert (g_variant_iter_next (iter, "i", &i1));
   g_assert_cmpint (i1, ==, 0);
@@ -513,7 +513,7 @@ test_l10n (void)
   settings = g_settings_new ("org.gtk.test.localized");
 
   setlocale (LC_MESSAGES, "C");
-  g_settings_get (settings, "error_message", "s", &str);
+  g_settings_get (settings, "error-message", "s", &str);
   setlocale (LC_MESSAGES, locale);
 
   g_assert_cmpstr (str, ==, "Unnamed");
@@ -521,7 +521,7 @@ test_l10n (void)
   str = NULL;
 
   setlocale (LC_MESSAGES, "de_DE");
-  g_settings_get (settings, "error_message", "s", &str);
+  g_settings_get (settings, "error-message", "s", &str);
   setlocale (LC_MESSAGES, locale);
 
   g_assert_cmpstr (str, ==, "Unbenannt");
diff --git a/gio/tests/org.gtk.test.gschema b/gio/tests/org.gtk.test.gschema
index b893988..f657a04 100644
--- a/gio/tests/org.gtk.test.gschema
+++ b/gio/tests/org.gtk.test.gschema
@@ -15,51 +15,51 @@
     <child name='complex-types' schema='org.gtk.test.complex-types'/>
     <child name='localized' schema='org.gtk.test.localized'/>
   </schema>
-  <schema id="org.gtk.test.basic-types" path="/tests/basic_types/">
-    <key name="test_boolean" type="b">
+  <schema id="org.gtk.test.basic-types" path="/tests/basic-types/">
+    <key name="test-boolean" type="b">
       <default>true</default>
     </key>
-    <key name="test_byte" type="y">
+    <key name="test-byte" type="y">
       <default>25</default>
     </key>
-    <key name="test_int16" type="n">
+    <key name="test-int16" type="n">
       <default>-1234</default>
     </key>
-    <key name="test_uint16" type="q">
+    <key name="test-uint16" type="q">
       <default>1234</default>
     </key>
-    <key name="test_int32" type="i">
+    <key name="test-int32" type="i">
       <default>-123456</default>
     </key>
-    <key name="test_uint32" type="u">
+    <key name="test-uint32" type="u">
       <default>123456</default>
     </key>
-    <key name="test_int64" type="x">
+    <key name="test-int64" type="x">
       <default>-123456789</default>
     </key>
-    <key name="test_uint64" type="t">
+    <key name="test-uint64" type="t">
       <default>123456789</default>
     </key>
-    <key name="test_double" type="d">
+    <key name="test-double" type="d">
       <default>123.456</default>
     </key>
-    <key name="test_string" type="s">
+    <key name="test-string" type="s">
       <default>"a string, it seems"</default>
     </key>
-    <key name="test_objectpath" type="o">
+    <key name="test-objectpath" type="o">
       <default>"/a/object/path"</default>
     </key>
   </schema>
-  <schema id="org.gtk.test.complex-types" path="/tests/complex_types/">
-    <key name="test_tuple" type="(s(ii))">
+  <schema id="org.gtk.test.complex-types" path="/tests/complex-types/">
+    <key name="test-tuple" type="(s(ii))">
       <default>("one",(2,3))</default>
     </key>
-    <key name="test_array" type="ai">
+    <key name="test-array" type="ai">
       <default>[0,1,2,3,4,5]</default>
     </key>
   </schema>
   <schema id="org.gtk.test.localized" path="/tests/localized/" gettext-domain="glib20">
-    <key name="error_message" type="s">
+    <key name="error-message" type="s">
       <default l10n="messages">"Unnamed"</default>
     </key>
   </schema>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]