Fix up problems with escaping already-escaped text and not unescaping it. Ensure that icon names (icon attribute values) are properly escaped on saving. Don't escape text which is already escaped. Unescape names & commands for editing & re-escape them afterwards. (The GLib docs list only five character escapes, so this is easy...) Signed-off-by: Darren Salt Index: menueditor/utils.c =================================================================== --- menueditor/utils.c (revision 22279) +++ menueditor/utils.c (working copy) @@ -75,17 +75,24 @@ fprintf (state->file_menu, "%sfile_menu, " visible=\"no\""); - if (option_1 && strlen (option_1) > 0) - fprintf (state->file_menu, " icon=\"%s\"", option_1); - + if (option_1 && *option_1) + { + temp = g_markup_escape_text (option_1, -1); + fprintf (state->file_menu, " icon=\"%s\"", temp); + free (temp); + } fprintf (state->file_menu, "/>\n"); break; case MENU: fprintf (state->file_menu, "%s<menu name=\"%s\"", space, name); if (hidden) fprintf (state->file_menu, " visible=\"no\""); - if (option_1 && strlen (option_1) > 0) - fprintf (state->file_menu, " icon=\"%s\"", option_1); + if (option_1 && *option_1) + { + temp = g_markup_escape_text (option_1, -1); + fprintf (state->file_menu, " icon=\"%s\"", temp); + free (temp); + } if (gtk_tree_model_iter_has_child (model, iter)) fprintf (state->file_menu, ">\n"); else @@ -95,8 +102,12 @@ fprintf (state->file_menu, "%s<app name=\"%s\" cmd=\"%s\"", space, name, command); if (hidden) fprintf (state->file_menu, " visible=\"no\""); - if (option_1 && strlen (option_1) > 0) - fprintf (state->file_menu, " icon=\"%s\"", option_1); + if (option_1 && *option_1) + { + temp = g_markup_escape_text (option_1, -1); + fprintf (state->file_menu, " icon=\"%s\"", temp); + free (temp); + } if (option_2 && (strcmp (option_2, "true") == 0)) fprintf (state->file_menu, " term=\"%s\"", option_2); if (option_3 && (strcmp (option_3, "true") == 0)) @@ -107,9 +118,12 @@ fprintf (state->file_menu, "%s<builtin name=\"%s\" cmd=\"%s\"", space, name, command); if (hidden) fprintf (state->file_menu, " visible=\"no\""); - if (strlen (option_1) > 0) - fprintf (state->file_menu, " icon=\"%s\"", option_1); - + if (option_1 && *option_1) + { + temp = g_markup_escape_text (option_1, -1); + fprintf (state->file_menu, " icon=\"%s\"", temp); + free (temp); + } fprintf (state->file_menu, "/>\n"); break; case INCLUDE_FILE: @@ -120,8 +134,12 @@ break; case INCLUDE_SYSTEM: fprintf (state->file_menu, "%s<include type=\"system\"", space); - if (option_1 && strlen (option_1) > 0) - fprintf (state->file_menu, " style=\"%s\"", option_1); + if (option_1 && *option_1) + { + temp = g_markup_escape_text (option_1, -1); + fprintf (state->file_menu, " style=\"%s\"", temp); + free (temp); + } if (option_2 && (strcmp (option_2, "true") == 0)) fprintf (state->file_menu, " unique=\"%s\"", option_2); if (option_3 && (strcmp (option_3, "true") == 0)) @@ -265,12 +283,12 @@ i = _find_attribute (attribute_names, "name"); if (i == -1) return; - name = g_strdup_printf (NAME_FORMAT, attribute_values[i]); + name = g_markup_printf_escaped (NAME_FORMAT, attribute_values[i]); j = _find_attribute (attribute_names, "cmd"); if (j == -1) return; - command = g_strdup_printf (COMMAND_FORMAT, attribute_values[j]); + command = g_markup_printf_escaped (COMMAND_FORMAT, attribute_values[j]); k = _find_attribute (attribute_names, "term"); l = _find_attribute (attribute_names, "snotify"); @@ -304,7 +322,7 @@ i = _find_attribute (attribute_names, "name"); if (i == -1) return; - name = g_strdup_printf (MENU_FORMAT, attribute_values[i]); + name = g_markup_printf_escaped (MENU_FORMAT, attribute_values[i]); j = _find_attribute (attribute_names, "icon"); if (j != -1 && *attribute_values[j]) @@ -325,7 +343,7 @@ g_queue_push_tail (state->parents, state->cur_parent); } else if (!strcmp (element_name, "separator")) { - name = g_strdup_printf (SEPARATOR_FORMAT, _("--- separator ---")); + name = g_markup_printf_escaped (SEPARATOR_FORMAT, _("--- separator ---")); gtk_tree_store_append (treestore, &iter, iter_parent); gtk_tree_store_set (treestore, &iter, @@ -335,12 +353,12 @@ i = _find_attribute (attribute_names, "name"); if (i == -1) return; - name = g_strdup_printf (NAME_FORMAT, attribute_values[i]); + name = g_markup_printf_escaped (NAME_FORMAT, attribute_values[i]); j = _find_attribute (attribute_names, "cmd"); if (j == -1) return; - command = g_strdup_printf (COMMAND_FORMAT, attribute_values[j]); + command = g_markup_printf_escaped (COMMAND_FORMAT, attribute_values[j]); k = _find_attribute (attribute_names, "icon"); if (k != -1 && *attribute_values[k]) @@ -361,7 +379,7 @@ i = _find_attribute (attribute_names, "name"); if (i == -1) return; - name = g_strdup_printf (TITLE_FORMAT, attribute_values[i]); + name = g_markup_printf_escaped (TITLE_FORMAT, attribute_values[i]); j = _find_attribute (attribute_names, "icon"); if (j != -1 && *attribute_values[j]) @@ -379,12 +397,12 @@ i = _find_attribute (attribute_names, "type"); if (i == -1) return; - name = g_strdup_printf (INCLUDE_FORMAT, _("--- include ---")); + name = g_markup_printf_escaped (INCLUDE_FORMAT, _("--- include ---")); if (!strcmp (attribute_values[i], "file")) { j = _find_attribute (attribute_names, "src"); if (j != -1) { - command = g_strdup_printf (INCLUDE_PATH_FORMAT, attribute_values[j]); + command = g_markup_printf_escaped (INCLUDE_PATH_FORMAT, attribute_values[j]); gtk_tree_store_append (treestore, &iter, iter_parent); gtk_tree_store_set (treestore, &iter, @@ -396,7 +414,7 @@ else if (!strcmp (attribute_values[i], "system")) { gboolean do_legacy = TRUE, only_unique = TRUE; - command = g_strdup_printf (INCLUDE_FORMAT, _("system")); + command = g_markup_printf_escaped (INCLUDE_FORMAT, _("system")); j = _find_attribute (attribute_names, "style"); k = _find_attribute (attribute_names, "unique"); @@ -732,11 +750,55 @@ temp_set = set; while (*temp_set) { if (strlen (*temp_set) > 0 && !g_strrstr (*temp_set, "span")) { - text = g_markup_escape_text (*temp_set, strlen (*temp_set) * sizeof (gchar)); + text = *temp_set; /* already escaped */ } temp_set++; } + text = g_strdup (text); g_strfreev (set); return text; } + +gchar * +unescape_text (const gchar *markup) +{ + gchar *text, *ptr, c; + + if (markup == NULL) + return NULL; + + ptr = text = g_malloc (strlen (markup) + 1); + + while ((c = *markup++)) + { + if (G_UNLIKELY (c == '&')) + { + if (!memcmp (markup, "amp;", 4)) { + *ptr++ = '&'; + markup += 4; + } + else if (!memcmp (markup, "lt;", 3)) { + *ptr++ = '<'; + markup += 3; + } + else if (!memcmp (markup, "gt;", 3)) { + *ptr++ = '>'; + markup += 3; + } + else if (!memcmp (markup, "quot;", 5)) { + *ptr++ = '"'; + markup += 5; + } + else if (!memcmp (markup, "apos;", 5)) { + *ptr++ = '\''; + markup += 5; + } + } + else + *ptr++ = c; + } + *ptr = 0; + + return text; +} Index: menueditor/edit_dialog.c =================================================================== --- menueditor/edit_dialog.c (revision 22279) +++ menueditor/edit_dialog.c (working copy) @@ -176,10 +176,16 @@ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (edit_dialog->dialog)->vbox), table, FALSE, FALSE, 0); /* Get the current values */ - if (name) - gtk_entry_set_text (GTK_ENTRY (entry_name), name); - if (command) - gtk_entry_set_text (GTK_ENTRY (edit_dialog->entry_command), command); + if (name) { + temp = unescape_text (name); + gtk_entry_set_text (GTK_ENTRY (entry_name), temp); + g_free (temp); + } + if (command) { + temp = unescape_text (command); + gtk_entry_set_text (GTK_ENTRY (edit_dialog->entry_command), temp); + g_free (temp); + } if (option_1) gtk_entry_set_text (GTK_ENTRY (edit_dialog->entry_icon), option_1); if (option_2 && strcmp (option_2, "true") == 0) @@ -217,8 +223,11 @@ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (edit_dialog->dialog)->vbox), table, FALSE, FALSE, 0); /* Get the current values */ - if (name) - gtk_entry_set_text (GTK_ENTRY (entry_name), name); + if (name) { + temp = unescape_text (name); + gtk_entry_set_text (GTK_ENTRY (entry_name), temp); + g_free (temp); + } if (option_1) gtk_entry_set_text (GTK_ENTRY (edit_dialog->entry_icon), option_1); Index: menueditor/utils.h =================================================================== --- menueditor/utils.h (revision 22279) +++ menueditor/utils.h (working copy) @@ -53,6 +53,7 @@ #include "menueditor.h" gchar *extract_text_from_markup (const gchar *markup); +gchar *unescape_text (const gchar *markup); gboolean command_exists (const gchar * command); void browse_file (GtkEntry * entry, GtkWindow * parent); void browse_icon (GtkEntry * entry, GtkWindow * parent);