keyfile: fix reading/writing SSIDs for all cases (bgo #660232)

Even with the previous fix some cases were still undistinguishable. For example,SSID like '11;12;' is both valid an intlist and a string.
So this commit:
- escapes ';' character with '\' when writing, and removes '\' while reading
  This clearly differentiates between intlist x strings.
- changes regex pattern to allow spaces before ';' in intlist format
This commit is contained in:
Jiří Klimeš 2011-10-18 16:13:39 +02:00
parent 965d5860ab
commit 50e329a92f
2 changed files with 38 additions and 6 deletions

View file

@ -730,11 +730,27 @@ read_hash_of_string (GKeyFile *file, NMSetting *setting, const char *key)
g_strfreev (keys);
}
static void
unescape_semicolons (char *str)
{
int i;
gsize len = strlen (str);
for (i = 0; i < len; i++) {
if (str[i] == '\\' && str[i+1] == ';') {
memmove(str + i, str + i + 1, len - (i + 1));
len--;
}
str[len] = '\0';
}
}
static GByteArray *
get_uchar_array (GKeyFile *keyfile,
const char *setting_name,
const char *key,
gboolean zero_terminate)
gboolean zero_terminate,
gboolean unescape_semicolon)
{
GByteArray *array = NULL;
char *tmp_string;
@ -749,12 +765,14 @@ get_uchar_array (GKeyFile *keyfile,
if (tmp_string) {
GRegex *regex;
GMatchInfo *match_info;
const char *pattern = "^[[:space:]]*[[:digit:]]{1,3};[[:space:]]*([[:space:]]*[[:digit:]]{1,3};[[:space:]]*)*([[:space:]]*)?$";
const char *pattern = "^[[:space:]]*[[:digit:]]{1,3}[[:space:]]*;([[:space:]]*[[:digit:]]{1,3}[[:space:]]*;)*([[:space:]]*)?$";
regex = g_regex_new (pattern, 0, 0, NULL);
g_regex_match (regex, tmp_string, 0, &match_info);
if (!g_match_info_matches (match_info)) {
/* Handle as a simple string (ie, new format) */
if (unescape_semicolon)
unescape_semicolons (tmp_string);
length = strlen (tmp_string);
if (zero_terminate)
length++;
@ -797,7 +815,7 @@ ssid_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, const char
const char *setting_name = nm_setting_get_name (setting);
GByteArray *array;
array = get_uchar_array (keyfile, setting_name, key, FALSE);
array = get_uchar_array (keyfile, setting_name, key, FALSE, TRUE);
if (array) {
g_object_set (setting, key, array, NULL);
g_byte_array_free (array, TRUE);
@ -918,7 +936,7 @@ cert_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, const char
GByteArray *array;
gboolean success = FALSE;
array = get_uchar_array (keyfile, setting_name, key, TRUE);
array = get_uchar_array (keyfile, setting_name, key, TRUE, FALSE);
if (array && array->len > 0) {
/* Try as a path + scheme (ie, starts with "file://") */
success = handle_as_scheme (array, setting, key);

View file

@ -483,6 +483,7 @@ ssid_writer (GKeyFile *file,
GByteArray *array;
const char *setting_name = nm_setting_get_name (setting);
gboolean new_format = TRUE;
unsigned int semicolons = 0;
int i, *tmp_array;
char *ssid;
@ -501,11 +502,24 @@ ssid_writer (GKeyFile *file,
new_format = FALSE;
break;
}
if (c == ';')
semicolons++;
}
if (new_format) {
ssid = g_malloc0 (array->len + 1);
memcpy (ssid, array->data, array->len);
ssid = g_malloc0 (array->len + semicolons + 1);
if (semicolons == 0)
memcpy (ssid, array->data, array->len);
else {
/* Escape semicolons with backslashes to make strings
* containing ';', such as '16;17;' unambiguous */
int j = 0;
for (i = 0; i < array->len; i++) {
if (array->data[i] == ';')
ssid[j++] = '\\';
ssid[j++] = array->data[i];
}
}
g_key_file_set_string (file, setting_name, key, ssid);
g_free (ssid);
} else {