gnome-terminal r3250 - trunk/src



Author: chpe
Date: Mon Dec 15 19:57:46 2008
New Revision: 3250
URL: http://svn.gnome.org/viewvc/gnome-terminal?rev=3250&view=rev

Log:
Don't try to send (potentially) non-UTF-8 data as G_TYPE_STRING over
dbus. Use byte arrays instead.

Modified:
   trunk/src/terminal-factory-service.xml
   trunk/src/terminal-options.c
   trunk/src/terminal-options.h
   trunk/src/terminal-util.c
   trunk/src/terminal-util.h
   trunk/src/terminal.c

Modified: trunk/src/terminal-factory-service.xml
==============================================================================
--- trunk/src/terminal-factory-service.xml	(original)
+++ trunk/src/terminal-factory-service.xml	Mon Dec 15 19:57:46 2008
@@ -1,11 +1,11 @@
 <node name="/org/gnome/Terminal">
   <interface name="org.gnome.Terminal.Factory">
-    <method name="NewTerminal">
-      <arg type="s" name="working_directory" direction="in" />
-      <arg type="s" name="display_name" direction="in" />
-      <arg type="s" name="startup_id" direction="in" />
-      <arg type="as" name="environment" direction="in" />
-      <arg type="as" name="arguments" direction="in" />
+    <method name="HandleArguments">
+      <arg type="ay" name="working_directory" direction="in" />
+      <arg type="ay" name="display_name" direction="in" />
+      <arg type="ay" name="startup_id" direction="in" />
+      <arg type="ay" name="environment" direction="in" />
+      <arg type="ay" name="arguments" direction="in" />
     </method>
   </interface>
 </node>

Modified: trunk/src/terminal-options.c
==============================================================================
--- trunk/src/terminal-options.c	(original)
+++ trunk/src/terminal-options.c	Mon Dec 15 19:57:46 2008
@@ -665,7 +665,7 @@
 terminal_options_parse (const char *working_directory,
                         const char *display_name,
                         const char *startup_id,
-                        const char **env,
+                        char **env,
                         gboolean ignore_unknown_options,
                         int *argcp,
                         char ***argvp,
@@ -689,7 +689,7 @@
   options->execute = FALSE;
   options->use_factory = TRUE;
 
-  options->env = g_strdupv ((char **) env);
+  options->env = g_strdupv (env);
   options->startup_id = g_strdup (startup_id && startup_id[0] ? startup_id : NULL);
   options->display_name = g_strdup (display_name);
   options->initial_windows = NULL;

Modified: trunk/src/terminal-options.h
==============================================================================
--- trunk/src/terminal-options.h	(original)
+++ trunk/src/terminal-options.h	Mon Dec 15 19:57:46 2008
@@ -84,7 +84,7 @@
 TerminalOptions *terminal_options_parse (const char *working_directory,
                                          const char *display_name,
                                          const char *startup_id,
-                                         const char **env,
+                                         char **env,
                                          gboolean ignore_unknown_options,
                                          int *argcp,
                                          char ***argvp,

Modified: trunk/src/terminal-util.c
==============================================================================
--- trunk/src/terminal-util.c	(original)
+++ trunk/src/terminal-util.c	Mon Dec 15 19:57:46 2008
@@ -465,6 +465,144 @@
   return NULL;
 }
 
+/* Why? Because dbus-glib sucks, that's why! */
+
+/**
+ * terminal_util_string_to_array:
+ * @string:
+ *
+ * Converts the string @string into a #GArray.
+ * 
+ * Returns: a newly allocated #GArray containing @string's bytes.
+ */
+GArray *
+terminal_util_string_to_array (const char *string)
+{
+  GArray *array;
+  gsize len = 0;
+
+  if (string)
+    len = strlen (string);
+
+  array = g_array_sized_new (FALSE, FALSE, sizeof (guchar), len);
+  return g_array_append_vals (array, string, len);
+}
+
+/**
+ * terminal_util_strv_to_array:
+ * @argc: the length of @argv
+ * @argv: a string array
+ *
+ * Converts the string array @argv of length @argc into a #GArray.
+ * 
+ * Returns: a newly allocated #GArray
+ */
+GArray *
+terminal_util_strv_to_array (int argc,
+                             char **argv)
+{
+  GArray *array;
+  gsize len = 0;
+  int i;
+  const char nullbyte = 0;
+
+  for (i = 0; i < argc; ++i)
+    len += strlen (argv[i]);
+  if (argc > 0)
+    len += argc - 1;
+
+  array = g_array_sized_new (FALSE, FALSE, sizeof (guchar), len);
+
+  for (i = 0; i < argc; ++i) {
+    g_array_append_vals (array, argv[i], strlen (argv[i]));
+    if (i < argc)
+      g_array_append_val (array, nullbyte);
+  }
+
+  return array;
+}
+
+/**
+ * terminal_util_array_to_string:
+ * @array:
+ * @error: a #GError to fill in
+ *
+ * Converts @array into a string.
+ * 
+ * Returns: a newly allocated string, or %NULL on error
+ */
+char *
+terminal_util_array_to_string (const GArray *array,
+                               GError **error)
+{
+  char *string;
+  g_return_val_if_fail (array != NULL, NULL);
+
+  string = g_strndup (array->data, array->len);
+
+  /* Validate */
+  if (strlen (string) < array->len) {
+    g_set_error_literal (error,
+                         g_quark_from_static_string ("terminal-error"),
+                         0,
+                         "String is shorter than claimed");
+    return NULL;
+  }
+
+  return string;
+}
+
+/**
+ * terminal_util_array_to_strv:
+ * @array:
+ * @argc: a location to store the length of the returned string array
+ * @error: a #GError to fill in
+ *
+ * Converts @array into a string.
+ * 
+ * Returns: a newly allocated string array of length * argc, or %NULL on error
+ */
+char **
+terminal_util_array_to_strv (const GArray *array,
+                             int *argc,
+                             GError **error)
+{
+  GPtrArray *argv;
+  const char *data, *nullbyte;
+  gsize len;
+
+  g_return_val_if_fail (array != NULL, NULL);
+
+  if (array->len == 0) {
+    *argc = 0;
+    return NULL;
+  }
+
+  argv = g_ptr_array_new ();
+
+  len = array->len;
+  data = array->data;
+
+  do {
+    gsize string_len;
+
+    nullbyte = memchr (data, '\0', len);
+
+    string_len = nullbyte ? nullbyte - data : len;
+    g_ptr_array_add (argv, g_strndup (data, string_len));
+
+    len -= string_len + 1;
+    data += string_len + 1;
+  } while (len > 0);
+
+  if (argc)
+    *argc = argv->len;
+
+  /* NULL terminate */
+  g_ptr_array_add (argv, NULL);
+  return (char **) g_ptr_array_free (argv, FALSE);
+}
+
 /* Bidirectional object/widget binding */
 
 typedef struct {

Modified: trunk/src/terminal-util.h
==============================================================================
--- trunk/src/terminal-util.h	(original)
+++ trunk/src/terminal-util.h	Mon Dec 15 19:57:46 2008
@@ -79,6 +79,18 @@
                                            int *argc,
                                            GError **error);
 
+GArray *terminal_util_string_to_array (const char *string);
+
+GArray *terminal_util_strv_to_array (int argc,
+                                     char **argv);
+
+char *terminal_util_array_to_string (const GArray *array,
+                                     GError **error);
+
+char **terminal_util_array_to_strv (const GArray *array,
+                                    int *argc,
+                                    GError **error);
+
 typedef enum {
   FLAG_INVERT_BOOL  = 1 << 0,
 } PropertyChangeFlags;

Modified: trunk/src/terminal.c
==============================================================================
--- trunk/src/terminal.c	(original)
+++ trunk/src/terminal.c	Mon Dec 15 19:57:46 2008
@@ -69,13 +69,13 @@
 };
 
 static gboolean
-terminal_factory_new_terminal (TerminalFactory *factory,
-                               const char *working_directory,
-                               const char *display_name,
-                               const char *startup_id,
-                               const char **argv,
-                               const char **env,
-                               GError **error);
+terminal_factory_handle_arguments (TerminalFactory *factory,
+                                   const GArray *working_directory_array,
+                                   const GArray *display_name_array,
+                                   const GArray *startup_id_array,
+                                   const GArray *argv_array,
+                                   const GArray *env_array,
+                                   GError **error);
 
 #include "terminal-factory-client.h"
 #include "terminal-factory-server.h"
@@ -214,6 +214,7 @@
 {
   int i;
   char **argv_copy;
+  int argc_copy;
   const char *startup_id;
   const char *display_name;
   GdkDisplay *display;
@@ -234,6 +235,7 @@
   for (i = 0; i < argc; ++i)
     argv_copy [i] = argv [i];
   argv_copy [i] = NULL;
+  argc_copy = argc;
 
   startup_id = g_getenv ("DESKTOP_STARTUP_ID");
 
@@ -322,43 +324,62 @@
   /* Forward to the existing factory and exit */
   if (request_name_ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
     {
+      char *working_directory;
       char **env;
       const char *evalue;
-      guint i, n;
-      GPtrArray *env_array;
+      GPtrArray *env_ptr_array;
+      int i, envc;
+      GArray *working_directory_array, *display_name_array, *startup_id_array;
+      GArray *env_array, *argv_array;
+      gboolean retval;
       int ret = EXIT_SUCCESS;
 
       env = g_listenv ();
-      n = g_strv_length (env);
-      env_array = g_ptr_array_sized_new (n);
-      for (i = 0; i < n; ++i)
+      envc = g_strv_length (env);
+      env_ptr_array = g_ptr_array_sized_new (envc);
+      for (i = 0; i < envc; ++i)
         {
           evalue = g_getenv (env[i]);
           if (evalue)
-            g_ptr_array_add (env_array, g_strdup_printf ("%s=%s", env[i], evalue));
+            g_ptr_array_add (env_ptr_array, g_strdup_printf ("%s=%s", env[i], evalue));
         }
-      g_ptr_array_add (env_array, NULL);
+      g_ptr_array_add (env_ptr_array, NULL);
 
       g_strfreev (env);
-      env = (char **) g_ptr_array_free (env_array, FALSE);
+      env = (char **) g_ptr_array_free (env_ptr_array, FALSE);
+
+      working_directory = g_get_current_dir ();
+      working_directory_array = terminal_util_string_to_array (working_directory);
+      display_name_array = terminal_util_string_to_array (options->display_name);
+      startup_id_array = terminal_util_string_to_array (options->startup_id);
+      env_array = terminal_util_strv_to_array (envc, env);
+      argv_array = terminal_util_strv_to_array (argc_copy, argv_copy);
 
       proxy = dbus_g_proxy_new_for_name (connection,
                                          TERMINAL_FACTORY_SERVICE_NAME,
                                          TERMINAL_FACTORY_SERVICE_PATH,
                                          TERMINAL_FACTORY_INTERFACE_NAME);
-      if (!org_gnome_Terminal_Factory_new_terminal (proxy,
-                                                    g_get_current_dir (),
-                                                    options->display_name,
-                                                    options->startup_id,
-                                                    (const char **) env,
-                                                    (const char **) argv_copy,
-                                                    &error))
+      retval = org_gnome_Terminal_Factory_handle_arguments (proxy,
+                                                            working_directory_array,
+                                                            display_name_array,
+                                                            startup_id_array,
+                                                            env_array,
+                                                            argv_array,
+                                                            &error);
+      g_free (working_directory);
+      g_array_free (working_directory_array, TRUE);
+      g_array_free (display_name_array, TRUE);
+      g_array_free (startup_id_array, TRUE);
+      g_array_free (env_array, TRUE);
+      g_array_free (argv_array, TRUE);
+      g_strfreev (env);
+
+      if (!retval)
         {
           if (g_error_matches (error, DBUS_GERROR, DBUS_GERROR_UNKNOWN_METHOD))
             {
               /* Incompatible factory version, fall back, to new instance */
               g_printerr (_("Incompatible factory version; creating a new instance.\n"));
-              g_strfreev (env);
               g_error_free (error);
 
               goto factory_disabled;
@@ -370,7 +391,6 @@
         }
 
       g_free (argv_copy);
-      g_strfreev (env);
       terminal_options_free (options);
 
       exit (ret);
@@ -441,31 +461,61 @@
 }
 
 static gboolean
-terminal_factory_new_terminal (TerminalFactory *factory,
-                               const char *working_directory,
-                               const char *display_name,
-                               const char *startup_id,
-                               const char **env,
-                               const char **arguments,
-                               GError **error)
+terminal_factory_handle_arguments (TerminalFactory *factory,
+                                   const GArray *working_directory_array,
+                                   const GArray *display_name_array,
+                                   const GArray *startup_id_array,
+                                   const GArray *env_array,
+                                   const GArray *argv_array,
+                                   GError **error)
 {
-  TerminalOptions *options;
-  char **argv;
+  TerminalOptions *options = NULL;
+  char *working_directory = NULL, *display_name = NULL, *startup_id = NULL;
+  char **env = NULL, **argv = NULL, **argv_copy = NULL;
   int argc;
+  GError *arg_error = NULL;
+
+  working_directory = terminal_util_array_to_string (working_directory_array, &arg_error);
+  if (arg_error)
+    goto out;
+  display_name = terminal_util_array_to_string (display_name_array, &arg_error);
+  if (arg_error)
+    goto out;
+  startup_id = terminal_util_array_to_string (startup_id_array, &arg_error);
+  if (arg_error)
+    goto out;
+  env = terminal_util_array_to_strv (env_array, NULL, &arg_error);
+  if (arg_error)
+    goto out;
+  argv = terminal_util_array_to_strv (argv_array, &argc, &arg_error);
+  if (arg_error)
+    goto out;
 
   /* Copy the arguments since terminal_options_parse potentially modifies the array */
-  argc = g_strv_length ((char **) arguments);
-  argv = (char **) g_memdup (arguments, (argc + 1) * sizeof (char *));
+  argv_copy = (char **) g_memdup (argv, (argc + 1) * sizeof (char *));
 
   options = terminal_options_parse (working_directory,
                                     display_name,
                                     startup_id,
                                     env,
                                     TRUE,
-                                    &argc, &argv,
+                                    &argc, &argv_copy,
                                     error,
                                     NULL);
-  g_free (argv);
+
+out:
+  g_free (working_directory);
+  g_free (display_name);
+  g_free (startup_id);
+  g_strfreev (env);
+  g_strfreev (argv);
+  g_free (argv_copy);
+
+  if (arg_error)
+    {
+      g_propagate_error (error, arg_error);
+      return FALSE;
+    }
 
   if (!options)
     return FALSE;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]