nautilus-3.6.3/libnautilus-private/nautilus-program-choosing.c

No issues found

  1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
  2 
  3 /* nautilus-program-choosing.c - functions for selecting and activating
  4  				 programs for opening/viewing particular files.
  5 
  6    Copyright (C) 2000 Eazel, Inc.
  7 
  8    The Gnome Library is free software; you can redistribute it and/or
  9    modify it under the terms of the GNU Library General Public License as
 10    published by the Free Software Foundation; either version 2 of the
 11    License, or (at your option) any later version.
 12 
 13    The Gnome Library is distributed in the hope that it will be useful,
 14    but WITHOUT ANY WARRANTY; without even the implied warranty of
 15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 16    Library General Public License for more details.
 17 
 18    You should have received a copy of the GNU Library General Public
 19    License along with the Gnome Library; see the file COPYING.LIB.  If not,
 20    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 21    Boston, MA 02111-1307, USA.
 22 
 23    Author: John Sullivan <sullivan@eazel.com>
 24 */
 25 
 26 #include <config.h>
 27 #include "nautilus-program-choosing.h"
 28 
 29 #include "nautilus-global-preferences.h"
 30 #include "nautilus-icon-info.h"
 31 #include "nautilus-recent.h"
 32 #include "nautilus-desktop-icon-file.h"
 33 #include <eel/eel-gnome-extensions.h>
 34 #include <eel/eel-stock-dialogs.h>
 35 #include <gtk/gtk.h>
 36 #include <glib/gi18n.h>
 37 #include <gio/gio.h>
 38 #include <gio/gdesktopappinfo.h>
 39 #include <stdlib.h>
 40 
 41 #include <gdk/gdk.h>
 42 #include <gdk/gdkx.h>
 43 
 44 void
 45 nautilus_launch_application_for_mount (GAppInfo *app_info,
 46 				       GMount *mount,
 47 				       GtkWindow *parent_window)
 48 {
 49 	GFile *root;
 50 	NautilusFile *file;
 51 	GList *files;
 52 
 53 	root = g_mount_get_root (mount);
 54 	file = nautilus_file_get (root);
 55 	g_object_unref (root);
 56 
 57 	files = g_list_append (NULL, file);
 58 	nautilus_launch_application (app_info,
 59 				     files,
 60 				     parent_window);
 61 
 62 	g_list_free_full (files, (GDestroyNotify) nautilus_file_unref);
 63 }
 64 
 65 /**
 66  * nautilus_launch_application:
 67  * 
 68  * Fork off a process to launch an application with a given file as a
 69  * parameter. Provide a parent window for error dialogs. 
 70  * 
 71  * @application: The application to be launched.
 72  * @uris: The files whose locations should be passed as a parameter to the application.
 73  * @parent_window: A window to use as the parent for any error dialogs.
 74  */
 75 void
 76 nautilus_launch_application (GAppInfo *application, 
 77 			     GList *files,
 78 			     GtkWindow *parent_window)
 79 {
 80 	GList *uris, *l;
 81 
 82 	uris = NULL;
 83 	for (l = files; l != NULL; l = l->next) {
 84 		uris = g_list_prepend (uris, nautilus_file_get_activation_uri (l->data));
 85 	}
 86 	uris = g_list_reverse (uris);
 87 	nautilus_launch_application_by_uri (application, uris,
 88 					    parent_window);
 89 	g_list_free_full (uris, g_free);
 90 }
 91 
 92 void
 93 nautilus_launch_application_by_uri (GAppInfo *application, 
 94 				    GList *uris,
 95 				    GtkWindow *parent_window)
 96 {
 97 	char *uri;
 98 	GList *locations, *l;
 99 	GFile *location;
100 	NautilusFile *file;
101 	gboolean result;
102 	GError *error;
103 	GdkDisplay *display;
104 	GdkAppLaunchContext *launch_context;
105 	NautilusIconInfo *icon;
106 	int count, total;
107 
108 	g_assert (uris != NULL);
109 
110 	/* count the number of uris with local paths */
111 	count = 0;
112 	total = g_list_length (uris);
113 	locations = NULL;
114 	for (l = uris; l != NULL; l = l->next) {
115 		uri = l->data;
116 		
117 		location = g_file_new_for_uri (uri);
118 		if (g_file_is_native (location)) {
119 			count++;
120 		}
121 		locations = g_list_prepend (locations, location);
122 	}
123 	locations = g_list_reverse (locations);
124 
125 	if (parent_window != NULL) {
126 		display = gtk_widget_get_display (GTK_WIDGET (parent_window));
127 	} else {
128 		display = gdk_display_get_default ();
129 	}
130 
131 	launch_context = gdk_display_get_app_launch_context (display);
132 
133 	if (parent_window != NULL) {
134 		gdk_app_launch_context_set_screen (launch_context,
135 						   gtk_window_get_screen (parent_window));
136 	}
137 
138 	file = nautilus_file_get_by_uri (uris->data);
139 	icon = nautilus_file_get_icon (file, 48, 0);
140 	nautilus_file_unref (file);
141 	if (icon) {
142 		gdk_app_launch_context_set_icon_name (launch_context,
143 							nautilus_icon_info_get_used_name (icon));
144 		g_object_unref (icon);
145 	}
146 	
147 	error = NULL;
148 
149 	if (count == total) {
150 		/* All files are local, so we can use g_app_info_launch () with
151 		 * the file list we constructed before.
152 		 */
153 		result = g_app_info_launch (application,
154 					    locations,
155 					    G_APP_LAUNCH_CONTEXT (launch_context),
156 					    &error);
157 	} else {
158 		/* Some files are non local, better use g_app_info_launch_uris ().
159 		 */
160 		result = g_app_info_launch_uris (application,
161 						 uris,
162 						 G_APP_LAUNCH_CONTEXT (launch_context),
163 						 &error);
164 	}
165 
166 	g_object_unref (launch_context);
167 
168 	if (result) {
169 		for (l = uris; l != NULL; l = l->next) {
170 			file = nautilus_file_get_by_uri (l->data);
171 			nautilus_recent_add_file (file, application);
172 			nautilus_file_unref (file);
173 		}
174 	}
175 
176 	g_list_free_full (locations, g_object_unref);
177 }
178 
179 static void
180 launch_application_from_command_internal (const gchar *full_command,
181 					  GdkScreen *screen,
182 					  gboolean use_terminal)
183 {
184 	GAppInfo *app;
185 	GdkAppLaunchContext *ctx;
186 	GdkDisplay *display;
187 
188 	if (use_terminal) {
189 		eel_gnome_open_terminal_on_screen (full_command, screen);
190 	} else {
191 		app = g_app_info_create_from_commandline (full_command, NULL, 0, NULL);
192 
193 		if (app != NULL) {
194 			display = gdk_screen_get_display (screen);
195 			ctx = gdk_display_get_app_launch_context (display);
196 			gdk_app_launch_context_set_screen (ctx, screen);
197 
198 			g_app_info_launch (app, NULL, G_APP_LAUNCH_CONTEXT (ctx), NULL);
199 
200 			g_object_unref (app);
201 			g_object_unref (ctx);
202 		}
203 	}
204 }					  
205 
206 /**
207  * nautilus_launch_application_from_command:
208  * 
209  * Fork off a process to launch an application with a given uri as
210  * a parameter.
211  * 
212  * @command_string: The application to be launched, with any desired
213  * command-line options.
214  * @...: Passed as parameters to the application after quoting each of them.
215  */
216 void
217 nautilus_launch_application_from_command (GdkScreen  *screen,
218 					  const char *command_string, 
219 					  gboolean use_terminal,
220 					  ...)
221 {
222 	char *full_command, *tmp;
223 	char *quoted_parameter; 
224 	char *parameter;
225 	va_list ap;
226 
227 	full_command = g_strdup (command_string);
228 
229 	va_start (ap, use_terminal);
230 
231 	while ((parameter = va_arg (ap, char *)) != NULL) {
232 		quoted_parameter = g_shell_quote (parameter);
233 		tmp = g_strconcat (full_command, " ", quoted_parameter, NULL);
234 		g_free (quoted_parameter);
235 
236 		g_free (full_command);
237 		full_command = tmp;
238 
239 	}
240 
241 	va_end (ap);
242 
243 	launch_application_from_command_internal (full_command, screen, use_terminal);
244 	
245 	g_free (full_command);
246 }
247 
248 /**
249  * nautilus_launch_application_from_command:
250  * 
251  * Fork off a process to launch an application with a given uri as
252  * a parameter.
253  * 
254  * @command_string: The application to be launched, with any desired
255  * command-line options.
256  * @parameters: Passed as parameters to the application after quoting each of them.
257  */
258 void
259 nautilus_launch_application_from_command_array (GdkScreen  *screen,
260 						const char *command_string,
261 						gboolean use_terminal,
262 						const char * const * parameters)
263 {
264 	char *full_command, *tmp;
265 	char *quoted_parameter; 
266 	const char * const *p;
267 
268 	full_command = g_strdup (command_string);
269 
270 	if (parameters != NULL) {
271 		for (p = parameters; *p != NULL; p++) {
272 			quoted_parameter = g_shell_quote (*p);
273 			tmp = g_strconcat (full_command, " ", quoted_parameter, NULL);
274 			g_free (quoted_parameter);
275 
276 			g_free (full_command);
277 			full_command = tmp;
278 		}
279 	}
280 
281 	launch_application_from_command_internal (full_command, screen, use_terminal);
282 
283 	g_free (full_command);
284 }
285 
286 void
287 nautilus_launch_desktop_file (GdkScreen   *screen,
288 			      const char  *desktop_file_uri,
289 			      const GList *parameter_uris,
290 			      GtkWindow   *parent_window)
291 {
292 	GError *error;
293 	char *message, *desktop_file_path;
294 	const GList *p;
295 	GList *files;
296 	int total, count;
297 	GFile *file, *desktop_file;
298 	GDesktopAppInfo *app_info;
299 	GdkAppLaunchContext *context;
300 
301 	/* Don't allow command execution from remote locations
302 	 * to partially mitigate the security
303 	 * risk of executing arbitrary commands.
304 	 */
305 	desktop_file = g_file_new_for_uri (desktop_file_uri);
306 	desktop_file_path = g_file_get_path (desktop_file);
307 	if (!g_file_is_native (desktop_file)) {
308 		g_free (desktop_file_path);
309 		g_object_unref (desktop_file);
310 		eel_show_error_dialog
311 			(_("Sorry, but you cannot execute commands from "
312 			   "a remote site."), 
313 			 _("This is disabled due to security considerations."),
314 			 parent_window);
315 			 
316 		return;
317 	}
318 	g_object_unref (desktop_file);
319 
320 	app_info = g_desktop_app_info_new_from_filename (desktop_file_path);
321 	g_free (desktop_file_path);
322 	if (app_info == NULL) {
323 		eel_show_error_dialog
324 			(_("There was an error launching the application."),
325 			 NULL,
326 			 parent_window);
327 		return;
328 	}
329 	
330 	/* count the number of uris with local paths */
331 	count = 0;
332 	total = g_list_length ((GList *) parameter_uris);
333 	files = NULL;
334 	for (p = parameter_uris; p != NULL; p = p->next) {
335 		file = g_file_new_for_uri ((const char *) p->data);
336 		if (g_file_is_native (file)) {
337 			count++;
338 		}
339 		files = g_list_prepend (files, file);
340 	}
341 
342 	/* check if this app only supports local files */
343 	if (g_app_info_supports_files (G_APP_INFO (app_info)) &&
344 	    !g_app_info_supports_uris (G_APP_INFO (app_info)) &&
345 	    parameter_uris != NULL) {
346 		if (count == 0) {
347 			/* all files are non-local */
348 			eel_show_error_dialog
349 				(_("This drop target only supports local files."),
350 				 _("To open non-local files copy them to a local folder and then"
351 				   " drop them again."),
352 				 parent_window);
353 
354 			g_list_free_full (files, g_object_unref);
355 			g_object_unref (app_info);
356 			return;
357 		} else if (count != total) {
358 			/* some files are non-local */
359 			eel_show_warning_dialog
360 				(_("This drop target only supports local files."),
361 				 _("To open non-local files copy them to a local folder and then"
362 				   " drop them again. The local files you dropped have already been opened."),
363 				 parent_window);
364 		}
365 	}
366 
367 	error = NULL;
368 	context = gdk_display_get_app_launch_context (gtk_widget_get_display (GTK_WIDGET (parent_window)));
369 	/* TODO: Ideally we should accept a timestamp here instead of using GDK_CURRENT_TIME */
370 	gdk_app_launch_context_set_timestamp (context, GDK_CURRENT_TIME);
371 	gdk_app_launch_context_set_screen (context,
372 					   gtk_window_get_screen (parent_window));
373 	if (count == total) {
374 		/* All files are local, so we can use g_app_info_launch () with
375 		 * the file list we constructed before.
376 		 */
377 		g_app_info_launch (G_APP_INFO (app_info),
378 				   files,
379 				   G_APP_LAUNCH_CONTEXT (context),
380 				   &error);
381 	} else {
382 		/* Some files are non local, better use g_app_info_launch_uris ().
383 		 */
384 		g_app_info_launch_uris (G_APP_INFO (app_info),
385 					(GList *) parameter_uris,
386 					G_APP_LAUNCH_CONTEXT (context),
387 					&error);
388 	}
389 	if (error != NULL) {
390 		message = g_strconcat (_("Details: "), error->message, NULL);
391 		eel_show_error_dialog
392 			(_("There was an error launching the application."),
393 			 message,
394 			 parent_window);
395 		
396 		g_error_free (error);
397 		g_free (message);
398 	}
399 
400 	g_list_free_full (files, g_object_unref);
401 	g_object_unref (context);
402 	g_object_unref (app_info);
403 }