From 40f51114b53be67f8962fc0ba61938fc2b990bfa Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Mon, 2 May 2011 14:38:13 -0400 Subject: [PATCH] meta_show_dialog: fix encoding of command line arguments Command line arguments are supposed to be in the locale encoding, not UTF-8, and Zenity decodes command line string command line arguments with this assumption using GOption. There was a half-hearted attempt to deal with this in delete.c, but it wasn't correct since it immediately mixed the window title, converted to the locale encoding with a UTF-8 message. https://bugzilla.gnome.org/show_bug.cgi?id=649114 --- src/core/delete.c | 12 ++++++-- src/core/util.c | 77 +++++++++++++++++++++++++++++------------------ 2 files changed, 56 insertions(+), 33 deletions(-) diff --git a/src/core/delete.c b/src/core/delete.c index 43bd503c7..c6a408e59 100644 --- a/src/core/delete.c +++ b/src/core/delete.c @@ -88,7 +88,15 @@ delete_ping_timeout_func (MetaDisplay *display, return; } - window_title = g_locale_from_utf8 (window->title, -1, NULL, NULL, NULL); + /* This is to get a bit better string if the title isn't representable + * in the locale encoding; actual conversion to UTF-8 is done inside + * meta_show_dialog */ + tmp = g_locale_from_utf8 (window->title, -1, NULL, NULL, NULL); + if (tmp == NULL) + window_title = "???"; + else + window_title = window->title; + g_free (tmp); /* Translators: %s is a window title */ tmp = g_strdup_printf (_("%s is not responding."), @@ -99,8 +107,6 @@ delete_ping_timeout_func (MetaDisplay *display, _("You may choose to wait a short while for it to " "continue or force the application to quit entirely.")); - g_free (window_title); - dialog_pid = meta_show_dialog ("--question", window_content, NULL, diff --git a/src/core/util.c b/src/core/util.c index 3144b9bd6..aea1210c1 100644 --- a/src/core/util.c +++ b/src/core/util.c @@ -584,6 +584,25 @@ meta_gravity_to_string (int gravity) } } +/* Command line arguments are passed in the locale encoding; in almost + * all cases, we'd hope that is UTF-8 and no conversion is necessary. + * If it's not UTF-8, then it's possible that the message isn't + * representable in the locale encoding. + */ +static void +append_argument (GPtrArray *args, + const char *arg) +{ + char *locale_arg = g_locale_from_utf8 (arg, -1, NULL, NULL, NULL); + + /* This is cheesy, but it's better to have a few ???'s in the dialog + * for an unresponsive application than no dialog at all appear */ + if (!locale_arg) + locale_arg = g_strdup ("???"); + + g_ptr_array_add (args, locale_arg); +} + GPid meta_show_dialog (const char *type, const char *message, @@ -597,59 +616,57 @@ meta_show_dialog (const char *type, { GError *error = NULL; GSList *tmp; - int i=0; GPid child_pid; - const char **argvl = g_malloc(sizeof (char*) * - (17 + - g_slist_length (columns)*2 + - g_slist_length (entries))); + GPtrArray *args; - argvl[i++] = "zenity"; - argvl[i++] = type; - argvl[i++] = "--display"; - argvl[i++] = display; - argvl[i++] = "--class"; - argvl[i++] = "mutter-dialog"; - argvl[i++] = "--title"; + args = g_ptr_array_new (); + + append_argument (args, "zenity"); + append_argument (args, type); + append_argument (args, "--display"); + append_argument (args, display); + append_argument (args, "--class"); + append_argument (args, "mutter-dialog"); + append_argument (args, "--title"); /* Translators: This is the title used on dialog boxes */ - argvl[i++] = _("Mutter"); - argvl[i++] = "--text"; - argvl[i++] = message; - + append_argument (args, _("Mutter")); + append_argument (args, "--text"); + append_argument (args, message); + if (timeout) { - argvl[i++] = "--timeout"; - argvl[i++] = timeout; + append_argument (args, "--timeout"); + append_argument (args, timeout); } if (ok_text) { - argvl[i++] = "--ok-label"; - argvl[i++] = ok_text; + append_argument (args, "--ok-label"); + append_argument (args, ok_text); } if (cancel_text) { - argvl[i++] = "--cancel-label"; - argvl[i++] = cancel_text; + append_argument (args, "--cancel-label"); + append_argument (args, cancel_text); } - + tmp = columns; while (tmp) { - argvl[i++] = "--column"; - argvl[i++] = tmp->data; + append_argument (args, "--column"); + append_argument (args, tmp->data); tmp = tmp->next; } tmp = entries; while (tmp) { - argvl[i++] = tmp->data; + append_argument (args, tmp->data); tmp = tmp->next; } - - argvl[i] = NULL; + + g_ptr_array_add (args, NULL); /* NULL-terminate */ if (transient_for) { @@ -660,7 +677,7 @@ meta_show_dialog (const char *type, g_spawn_async ( "/", - (gchar**) argvl, /* ugh */ + (gchar**) args->pdata, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, @@ -671,7 +688,7 @@ meta_show_dialog (const char *type, if (transient_for) unsetenv ("WINDOWID"); - g_free (argvl); + g_ptr_array_free (args, TRUE); if (error) {