aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBurt P <pburt0@gmail.com>2019-07-21 12:45:56 -0500
committerLeandro A. F. Pereira <leandro@hardinfo.org>2019-08-10 16:46:31 -0700
commit9c478d2a23fac7a2b0d7aa41981571d27631134e (patch)
treebb69cf49e9d6bfebe180f0b2f1798c764a266fa1
parentff8078c66110e8ea36240c47bc1f069b44d3ab99 (diff)
shell/info: allow newlines in values
Also fixed a FIXME: use g_key_file_get_string_list(). Signed-off-by: Burt P <pburt0@gmail.com>
-rw-r--r--hardinfo/gg_key_file_parse_string_as_value.c109
-rw-r--r--hardinfo/info.c10
-rw-r--r--shell/shell.c106
3 files changed, 170 insertions, 55 deletions
diff --git a/hardinfo/gg_key_file_parse_string_as_value.c b/hardinfo/gg_key_file_parse_string_as_value.c
new file mode 100644
index 00000000..496b1d35
--- /dev/null
+++ b/hardinfo/gg_key_file_parse_string_as_value.c
@@ -0,0 +1,109 @@
+/* From: gkeyfile.c - key file parser
+ *
+ * Copyright 2004 Red Hat, Inc.
+ * Copyright 2009-2010 Collabora Ltd.
+ * Copyright 2009 Nokia Corporation
+ *
+ * Written by Ray Strode <rstrode@redhat.com>
+ * Matthias Clasen <mclasen@redhat.com>
+ *
+ * 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.1 of the License, 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, see <http://www.gnu.org/licenses/>.
+ */
+
+static gchar *
+gg_key_file_parse_string_as_value (const gchar *string, const gchar list_separator)
+{
+ gchar *value, *p, *q;
+ gsize length;
+ gboolean parsing_leading_space;
+
+ length = strlen (string) + 1;
+
+ /* Worst case would be that every character needs to be escaped.
+ * In other words every character turns to two characters. */
+ value = g_new (gchar, 2 * length);
+
+ p = (gchar *) string;
+ q = value;
+ parsing_leading_space = TRUE;
+ while (p < (string + length - 1))
+ {
+ gchar escaped_character[3] = { '\\', 0, 0 };
+
+ switch (*p)
+ {
+ case ' ':
+ if (parsing_leading_space)
+ {
+ escaped_character[1] = 's';
+ strcpy (q, escaped_character);
+ q += 2;
+ }
+ else
+ {
+ *q = *p;
+ q++;
+ }
+ break;
+ case '\t':
+ if (parsing_leading_space)
+ {
+ escaped_character[1] = 't';
+ strcpy (q, escaped_character);
+ q += 2;
+ }
+ else
+ {
+ *q = *p;
+ q++;
+ }
+ break;
+ case '\n':
+ escaped_character[1] = 'n';
+ strcpy (q, escaped_character);
+ q += 2;
+ break;
+ case '\r':
+ escaped_character[1] = 'r';
+ strcpy (q, escaped_character);
+ q += 2;
+ break;
+ case '\\':
+ escaped_character[1] = '\\';
+ strcpy (q, escaped_character);
+ q += 2;
+ parsing_leading_space = FALSE;
+ break;
+ default:
+ if (list_separator && *p == list_separator)
+ {
+ escaped_character[1] = list_separator;
+ strcpy (q, escaped_character);
+ q += 2;
+ parsing_leading_space = TRUE;
+ }
+ else
+ {
+ *q = *p;
+ q++;
+ parsing_leading_space = FALSE;
+ }
+ break;
+ }
+ p++;
+ }
+ *q = '\0';
+
+ return value;
+}
diff --git a/hardinfo/info.c b/hardinfo/info.c
index bfc11fc2..ac18e0d9 100644
--- a/hardinfo/info.c
+++ b/hardinfo/info.c
@@ -18,6 +18,12 @@
#include "hardinfo.h"
+/* Using a slightly modified gg_key_file_parse_string_as_value()
+ * from GLib in flatten(), to escape characters and the separator.
+ * The function is not public in GLib and we don't have a GKeyFile
+ * to pass it anyway. */
+#include "gg_key_file_parse_string_as_value.c"
+
static const gchar *info_column_titles[] = {
"TextValue", "Value", "Progress", "Extra1", "Extra2"
};
@@ -267,7 +273,9 @@ static void flatten_group(GString *output, const struct InfoGroup *group, guint
tp);
}
- g_string_append_printf(output, "%s=%s\n", field->name, field->value);
+ gchar *escaped_value = gg_key_file_parse_string_as_value(field->value, '|');
+ g_string_append_printf(output, "%s=%s\n", field->name, escaped_value);
+ g_free(escaped_value);
}
} else if (group->computed) {
g_string_append_printf(output, "%s\n", group->computed);
diff --git a/shell/shell.c b/shell/shell.c
index 31836d62..106f6722 100644
--- a/shell/shell.c
+++ b/shell/shell.c
@@ -1271,70 +1271,68 @@ static void group_handle_normal(GKeyFile *key_file,
g_free(tmp);
}
+ g_key_file_set_list_separator(key_file, '|');
+
for (i = 0; keys[i]; i++) {
gchar *key = keys[i];
- gchar *value;
+ gchar **values;
+ gsize vcount = 0;
GtkTreeIter child;
- value = g_key_file_get_value(key_file, group, key, NULL);
- if (entry->fieldfunc && value && g_str_equal(value, "...")) {
- g_free(value);
- value = entry->fieldfunc(key);
- }
-
- if ((key && value) && g_utf8_validate(key, -1, NULL) &&
- g_utf8_validate(value, -1, NULL)) {
- if (ngroups == 1) {
- gtk_tree_store_append(store, &child, NULL);
- } else {
- gtk_tree_store_append(store, &child, &parent);
- }
-
- /* FIXME: use g_key_file_get_string_list? */
- if (g_utf8_strchr(value, -1, '|')) {
- gchar **columns = g_strsplit(value, "|", 0);
-
- gtk_tree_store_set(store, &child, INFO_TREE_COL_VALUE,
- columns[0], -1);
- if (columns[1]) {
- gtk_tree_store_set(store, &child, INFO_TREE_COL_EXTRA1,
- columns[1], -1);
- if (columns[2]) {
- gtk_tree_store_set(store, &child, INFO_TREE_COL_EXTRA2,
- columns[2], -1);
- }
- }
-
- g_strfreev(columns);
+ values = g_key_file_get_string_list(key_file, group, key, &vcount, NULL);
+ if (!vcount) {
+ /* Check for empty value */
+ values = g_new0(gchar*, 2);
+ values[0] = g_key_file_get_string(key_file, group, key, NULL);
+ if (values[0]) {
+ vcount = 1;
} else {
- gtk_tree_store_set(store, &child, INFO_TREE_COL_VALUE, value,
- -1);
+ g_strfreev(values);
+ continue;
}
+ }
- strend(key, '#');
-
- struct UpdateTableItem *item = g_new0(struct UpdateTableItem, 1);
- item->is_iter = TRUE;
- item->iter = gtk_tree_iter_copy(&child);
- gchar *flags, *tag, *name;
- key_get_components(key, &flags, &tag, &name, NULL, NULL, TRUE);
+ if (entry->fieldfunc && values[0] && g_str_equal(values[0], "...")) {
+ g_free(values[0]);
+ values[0] = entry->fieldfunc(key);
+ }
- if (flags) {
- gtk_tree_store_set(store, &child, INFO_TREE_COL_NAME, name,
- INFO_TREE_COL_DATA, flags, -1);
- g_hash_table_insert(update_tbl, tag, item);
- g_free(name);
- } else {
- gtk_tree_store_set(store, &child, INFO_TREE_COL_NAME, key,
- INFO_TREE_COL_DATA, NULL, -1);
- g_hash_table_insert(update_tbl, name, item);
- g_free(tag);
- }
- g_free(flags);
+ if (ngroups == 1) {
+ gtk_tree_store_append(store, &child, NULL);
+ } else {
+ gtk_tree_store_append(store, &child, &parent);
+ }
+ if (vcount > 0)
+ gtk_tree_store_set(store, &child, INFO_TREE_COL_VALUE,
+ values[0], -1);
+ if (vcount > 1)
+ gtk_tree_store_set(store, &child, INFO_TREE_COL_EXTRA1,
+ values[1], -1);
+ if (vcount > 2)
+ gtk_tree_store_set(store, &child, INFO_TREE_COL_EXTRA2,
+ values[2], -1);
+
+ struct UpdateTableItem *item = g_new0(struct UpdateTableItem, 1);
+ item->is_iter = TRUE;
+ item->iter = gtk_tree_iter_copy(&child);
+ gchar *flags, *tag, *name;
+ key_get_components(key, &flags, &tag, &name, NULL, NULL, TRUE);
+
+ if (flags) {
+ gtk_tree_store_set(store, &child, INFO_TREE_COL_NAME, name,
+ INFO_TREE_COL_DATA, flags, -1);
+ g_hash_table_insert(update_tbl, tag, item);
+ g_free(name);
+ } else {
+ gtk_tree_store_set(store, &child, INFO_TREE_COL_NAME, key,
+ INFO_TREE_COL_DATA, NULL, -1);
+ g_hash_table_insert(update_tbl, name, item);
+ g_free(tag);
}
+ g_free(flags);
- g_free(value);
+ g_strfreev(values);
}
}
@@ -1564,7 +1562,7 @@ static void module_selected_show_info_detail(GKeyFile *key_file,
gchar *name, *label, *tag;
key_get_components(keys[j], NULL, &tag, &name, &label, NULL, TRUE);
- value = g_key_file_get_value(key_file, groups[i], keys[j], NULL);
+ value = g_key_file_get_string(key_file, groups[i], keys[j], NULL);
if (entry && entry->fieldfunc && value && g_str_equal(value, "...")) {
g_free(value);