const gchar *value);
static void g_key_file_add_group (GKeyFile *key_file,
const gchar *group_name);
+static gboolean g_key_file_is_group_name (const gchar *name);
+static gboolean g_key_file_is_key_name (const gchar *name);
static void g_key_file_key_value_pair_free (GKeyFileKeyValuePair *pair);
static gboolean g_key_file_line_is_comment (const gchar *line);
static gboolean g_key_file_line_is_group (const gchar *line);
g_key_file_set_list_separator (GKeyFile *key_file,
gchar separator)
{
+ g_return_if_fail (key_file != NULL);
+
key_file->list_separator = separator;
}
group_name = g_strndup (group_name_start,
group_name_end - group_name_start);
+ if (!g_key_file_is_group_name (group_name))
+ {
+ g_set_error (error, G_KEY_FILE_ERROR,
+ G_KEY_FILE_ERROR_PARSE,
+ _("Invalid group name: %s"), group_name);
+ g_free (group_name);
+ return;
+ }
+
g_key_file_add_group (key_file, group_name);
g_free (group_name);
}
key = g_strndup (line, key_len - 1);
+ if (!g_key_file_is_key_name (key))
+ {
+ g_set_error (error, G_KEY_FILE_ERROR,
+ G_KEY_FILE_ERROR_PARSE,
+ _("Invalid key name: %s"), key);
+ g_free (key);
+ return;
+ }
+
/* Pull the value from the line (chugging leading whitespace)
*/
while (g_ascii_isspace (*value_start))
GKeyFileKeyValuePair *pair;
g_return_if_fail (key_file != NULL);
- g_return_if_fail (group_name != NULL);
- g_return_if_fail (key != NULL);
+ g_return_if_fail (g_key_file_is_group_name (group_name));
+ g_return_if_fail (g_key_file_is_key_name (key));
g_return_if_fail (value != NULL);
group = g_key_file_lookup_group (key_file, group_name);
gchar *value;
g_return_if_fail (key_file != NULL);
- g_return_if_fail (group_name != NULL);
- g_return_if_fail (key != NULL);
g_return_if_fail (string != NULL);
value = g_key_file_parse_string_as_value (key_file, string, FALSE);
gsize i;
g_return_if_fail (key_file != NULL);
- g_return_if_fail (group_name != NULL);
- g_return_if_fail (key != NULL);
g_return_if_fail (list != NULL);
value_list = g_string_sized_new (length * 128);
gchar *full_key, *value;
g_return_if_fail (key_file != NULL);
- g_return_if_fail (group_name != NULL);
g_return_if_fail (key != NULL);
g_return_if_fail (locale != NULL);
g_return_if_fail (string != NULL);
gsize i;
g_return_if_fail (key_file != NULL);
- g_return_if_fail (group_name != NULL);
g_return_if_fail (key != NULL);
g_return_if_fail (locale != NULL);
g_return_if_fail (length != 0);
gchar *result;
g_return_if_fail (key_file != NULL);
- g_return_if_fail (group_name != NULL);
- g_return_if_fail (key != NULL);
result = g_key_file_parse_boolean_as_value (key_file, value);
g_key_file_set_value (key_file, group_name, key, result);
gsize i;
g_return_if_fail (key_file != NULL);
- g_return_if_fail (group_name != NULL);
- g_return_if_fail (key != NULL);
g_return_if_fail (list != NULL);
value_list = g_string_sized_new (length * 8);
gchar *result;
g_return_if_fail (key_file != NULL);
- g_return_if_fail (group_name != NULL);
- g_return_if_fail (key != NULL);
result = g_key_file_parse_integer_as_value (key_file, value);
g_key_file_set_value (key_file, group_name, key, result);
gsize i;
g_return_if_fail (key_file != NULL);
- g_return_if_fail (group_name != NULL);
- g_return_if_fail (key != NULL);
g_return_if_fail (list != NULL);
values = g_string_sized_new (length * 16);
gchar result[G_ASCII_DTOSTR_BUF_SIZE];
g_return_if_fail (key_file != NULL);
- g_return_if_fail (group_name != NULL);
- g_return_if_fail (key != NULL);
- g_ascii_dtostr ( result, sizeof (result), value );
+ g_ascii_dtostr (result, sizeof (result), value);
g_key_file_set_value (key_file, group_name, key, result);
}
gsize i;
g_return_if_fail (key_file != NULL);
- g_return_if_fail (group_name != NULL);
- g_return_if_fail (key != NULL);
g_return_if_fail (list != NULL);
values = g_string_sized_new (length * 16);
{
GKeyFileGroup *group;
+ g_return_if_fail (g_key_file_is_group_name (group_name));
+
group = g_key_file_lookup_group (key_file, group_name);
if (!group)
{
GString *string;
gchar *comment;
+ g_return_val_if_fail (g_key_file_is_group_name (group_name), NULL);
+
group = g_key_file_lookup_group (key_file, group_name);
if (!group)
{
GKeyFileGroup *group;
g_return_if_fail (key_file != NULL);
- g_return_if_fail (group_name != NULL);
+ g_return_if_fail (g_key_file_is_group_name (group_name));
group = g_key_file_lookup_group (key_file, group_name);
if (group != NULL)
return (*line == '#' || *line == '\0' || *line == '\n');
}
+static gboolean
+g_key_file_is_group_name (const gchar *name)
+{
+ gchar *p, *q;
+
+ if (name == NULL)
+ return FALSE;
+
+ p = q = (gchar *) name;
+ while (*q && *q != ']' && *q != '[' && !g_ascii_iscntrl (*q))
+ q = g_utf8_next_char (q);
+
+ if (*q != '\0' || q == p)
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+g_key_file_is_key_name (const gchar *name)
+{
+ gchar *p, *q;
+
+ if (name == NULL)
+ return FALSE;
+
+ p = q = (gchar *) name;
+ while (*q && (g_unichar_isalnum (g_utf8_get_char (q)) || *q == '-'))
+ q = g_utf8_next_char (q);
+
+ if (*q == '[')
+ {
+ q++;
+ while (*q && (g_unichar_isalnum (g_utf8_get_char (q)) || *q == '-' || *q == '_' || *q == '.'))
+ q = g_utf8_next_char (q);
+
+ if (*q != ']')
+ return FALSE;
+
+ q++;
+ }
+
+ if (*q != '\0' || q == p)
+ return FALSE;
+
+ return TRUE;
+}
+
/* A group in a key file is made up of a starting '[' followed by one
* or more letters making up the group name followed by ']'.
*/
if (*p != '[')
return FALSE;
- p = g_utf8_next_char (p);
-
- /* Group name must be non-empty
- */
- if (!*p || *p == ']')
- return FALSE;
+ p++;
while (*p && *p != ']')
p = g_utf8_next_char (p);
test_locale_string (void)
{
GKeyFile *keyfile;
- GError *error = NULL;
- gchar *value;
const gchar *data =
"[valid]\n"
"key1[de_DE]=v1-de_DE\n"
"key1[de_DE.UTF8]=v1-de_DE.UTF8\n"
"key1[fr]=v1-fr\n"
- "key1[en] =v1-en\n"
- "[invalid]\n"
- "key1[de=v1\n"
- "key1[fr]]=v2\n"
- "key1 [en]=v3\n";
+ "key1[en] =v1-en\n";
keyfile = load_data (data, G_KEY_FILE_KEEP_TRANSLATIONS);
check_locale_string_value (keyfile, "valid", "key1", "fr_FR", "v1-fr");
check_locale_string_value (keyfile, "valid", "key1", "en", "v1-en");
- value = g_key_file_get_locale_string (keyfile, "invalid", "key1", "de", &error);
- check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND);
- g_free (value);
-
- value = g_key_file_get_locale_string (keyfile, "invalid", "key1", "fr", &error);
- check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND);
- g_free (value);
-
- value = g_key_file_get_locale_string (keyfile, "invalid", "key1", "en", &error);
- check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND);
- g_free (value);
-
g_key_file_free (keyfile);
/* now test that translations are thrown away */
}
static void
+test_group_names (void)
+{
+ GKeyFile *keyfile;
+ GError *error = NULL;
+ const gchar *data;
+ gchar *value;
+
+ /* [ in group name */
+ data = "[a[b]\n"
+ "key1=123\n";
+ keyfile = g_key_file_new ();
+ g_key_file_load_from_data (keyfile, data, -1, 0, &error);
+ g_key_file_free (keyfile);
+ check_error (&error,
+ G_KEY_FILE_ERROR,
+ G_KEY_FILE_ERROR_PARSE);
+
+ /* ] in group name */
+ data = "[a]b]\n"
+ "key1=123\n";
+ keyfile = g_key_file_new ();
+ g_key_file_load_from_data (keyfile, data, -1, 0, &error);
+ g_key_file_free (keyfile);
+ check_error (&error,
+ G_KEY_FILE_ERROR,
+ G_KEY_FILE_ERROR_PARSE);
+
+ /* control char in group name */
+ data = "[a\tb]\n"
+ "key1=123\n";
+ keyfile = g_key_file_new ();
+ g_key_file_load_from_data (keyfile, data, -1, 0, &error);
+ g_key_file_free (keyfile);
+ check_error (&error,
+ G_KEY_FILE_ERROR,
+ G_KEY_FILE_ERROR_PARSE);
+
+ /* Unicode in group name */
+ data = "[\xc2\xbd]\n"
+ "key1=123\n";
+ keyfile = g_key_file_new ();
+ g_key_file_load_from_data (keyfile, data, -1, 0, &error);
+ g_key_file_free (keyfile);
+ check_no_error (&error);
+
+ keyfile = g_key_file_new ();
+ g_key_file_set_string (keyfile, "a[b", "key1", "123");
+ value = g_key_file_get_string (keyfile, "a[b", "key1", &error);
+ check_error (&error,
+ G_KEY_FILE_ERROR,
+ G_KEY_FILE_ERROR_GROUP_NOT_FOUND);
+ g_key_file_free (keyfile);
+
+ keyfile = g_key_file_new ();
+ g_key_file_set_string (keyfile, "a]b", "key1", "123");
+ value = g_key_file_get_string (keyfile, "a]b", "key1", &error);
+ check_error (&error,
+ G_KEY_FILE_ERROR,
+ G_KEY_FILE_ERROR_GROUP_NOT_FOUND);
+ g_key_file_free (keyfile);
+
+ keyfile = g_key_file_new ();
+ g_key_file_set_string (keyfile, "a\tb", "key1", "123");
+ value = g_key_file_get_string (keyfile, "a\tb", "key1", &error);
+ check_error (&error,
+ G_KEY_FILE_ERROR,
+ G_KEY_FILE_ERROR_GROUP_NOT_FOUND);
+ g_key_file_free (keyfile);
+
+ keyfile = g_key_file_new ();
+ g_key_file_set_string (keyfile, "\xc2\xbd", "key1", "123");
+ check_string_value (keyfile, "\xc2\xbd", "key1", "123");
+ g_key_file_free (keyfile);
+}
+
+static void
+test_key_names (void)
+{
+ GKeyFile *keyfile;
+ GError *error = NULL;
+ const gchar *data;
+ gchar *value;
+
+ /* [ in key name */
+ data = "[a]\n"
+ "key[=123\n";
+ keyfile = g_key_file_new ();
+ g_key_file_load_from_data (keyfile, data, -1, 0, &error);
+ g_key_file_free (keyfile);
+ check_error (&error,
+ G_KEY_FILE_ERROR,
+ G_KEY_FILE_ERROR_PARSE);
+
+ /* + in key name */
+ data = "[a]\n"
+ "key+foo=123\n";
+ keyfile = g_key_file_new ();
+ g_key_file_load_from_data (keyfile, data, -1, 0, &error);
+ g_key_file_free (keyfile);
+ check_error (&error,
+ G_KEY_FILE_ERROR,
+ G_KEY_FILE_ERROR_PARSE);
+
+ /* control char in key name */
+ data = "[a]\n"
+ "key\tfoo=123\n";
+ keyfile = g_key_file_new ();
+ g_key_file_load_from_data (keyfile, data, -1, 0, &error);
+ g_key_file_free (keyfile);
+ check_error (&error,
+ G_KEY_FILE_ERROR,
+ G_KEY_FILE_ERROR_PARSE);
+
+ /* Unicode in key name */
+ data = "[a]\n"
+ "\xc2\xbd=123\n";
+ keyfile = g_key_file_new ();
+ g_key_file_load_from_data (keyfile, data, -1, 0, &error);
+ g_key_file_free (keyfile);
+ check_no_error (&error);
+
+ keyfile = g_key_file_new ();
+ g_key_file_set_string (keyfile, "a", "x", "123");
+ g_key_file_set_string (keyfile, "a", "key=", "123");
+ value = g_key_file_get_string (keyfile, "a", "key=", &error);
+ check_error (&error,
+ G_KEY_FILE_ERROR,
+ G_KEY_FILE_ERROR_KEY_NOT_FOUND);
+ g_key_file_free (keyfile);
+
+ keyfile = g_key_file_new ();
+ g_key_file_set_string (keyfile, "a", "x", "123");
+ g_key_file_set_string (keyfile, "a", "key[", "123");
+ value = g_key_file_get_string (keyfile, "a", "key[", &error);
+ check_error (&error,
+ G_KEY_FILE_ERROR,
+ G_KEY_FILE_ERROR_KEY_NOT_FOUND);
+ g_key_file_free (keyfile);
+
+ keyfile = g_key_file_new ();
+ g_key_file_set_string (keyfile, "a", "x", "123");
+ g_key_file_set_string (keyfile, "a", "key+foo", "123");
+ value = g_key_file_get_string (keyfile, "a", "key+foo", &error);
+ check_error (&error,
+ G_KEY_FILE_ERROR,
+ G_KEY_FILE_ERROR_KEY_NOT_FOUND);
+ g_key_file_free (keyfile);
+
+ keyfile = g_key_file_new ();
+ g_key_file_set_string (keyfile, "a", "x", "123");
+ g_key_file_set_string (keyfile, "a", "key\tfoo", "123");
+ value = g_key_file_get_string (keyfile, "a", "key\tfoo", &error);
+ check_error (&error,
+ G_KEY_FILE_ERROR,
+ G_KEY_FILE_ERROR_KEY_NOT_FOUND);
+ g_key_file_free (keyfile);
+
+ keyfile = g_key_file_new ();
+ g_key_file_set_string (keyfile, "a", "x", "123");
+ g_key_file_set_string (keyfile, "a", " key", "123");
+ value = g_key_file_get_string (keyfile, "a", " key", &error);
+ check_error (&error,
+ G_KEY_FILE_ERROR,
+ G_KEY_FILE_ERROR_KEY_NOT_FOUND);
+ g_key_file_free (keyfile);
+
+ keyfile = g_key_file_new ();
+ g_key_file_set_string (keyfile, "a", "x", "123");
+ g_key_file_set_string (keyfile, "a", "\xc2\xbd", "123");
+ check_string_value (keyfile, "a", "\xc2\xbd", "123");
+ g_key_file_free (keyfile);
+}
+
+static void
test_duplicate_keys (void)
{
GKeyFile *keyfile;
g_key_file_free (keyfile);
}
+static void
+log_func (const gchar *log_domain,
+ GLogLevelFlags log_level,
+ const gchar *message,
+ gpointer user_data)
+{
+}
+
int
main (int argc, char *argv[])
{
+ g_log_set_default_handler (log_func, NULL);
+
test_line_ends ();
test_whitespace ();
test_comments ();
test_duplicate_keys ();
test_duplicate_groups ();
test_duplicate_groups2 ();
+ test_group_names ();
+ test_key_names ();
return 0;
}