No issues found
Tool | Failure ID | Location | Function | Message | Data |
---|---|---|---|---|---|
clang-analyzer | no-output-found | nautilus-mime-actions.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None |
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3 /* nautilus-mime-actions.c - uri-specific versions of mime action functions
4
5 Copyright (C) 2000, 2001 Eazel, Inc.
6
7 The Gnome Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 The Gnome Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public
18 License along with the Gnome Library; see the file COPYING.LIB. If not,
19 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.
21
22 Authors: Maciej Stachowiak <mjs@eazel.com>
23 */
24
25 #include <config.h>
26
27 #include "nautilus-mime-actions.h"
28
29 #include "nautilus-window-slot.h"
30
31 #include <eel/eel-glib-extensions.h>
32 #include <eel/eel-stock-dialogs.h>
33 #include <eel/eel-string.h>
34 #include <glib/gi18n.h>
35 #include <glib/gstdio.h>
36 #include <string.h>
37 #include <gdk/gdkx.h>
38
39 #include <libnautilus-private/nautilus-file-attributes.h>
40 #include <libnautilus-private/nautilus-file.h>
41 #include <libnautilus-private/nautilus-file-operations.h>
42 #include <libnautilus-private/nautilus-metadata.h>
43 #include <libnautilus-private/nautilus-program-choosing.h>
44 #include <libnautilus-private/nautilus-desktop-icon-file.h>
45 #include <libnautilus-private/nautilus-global-preferences.h>
46 #include <libnautilus-private/nautilus-signaller.h>
47
48 #define DEBUG_FLAG NAUTILUS_DEBUG_MIME
49 #include <libnautilus-private/nautilus-debug.h>
50
51 typedef enum {
52 ACTIVATION_ACTION_LAUNCH_DESKTOP_FILE,
53 ACTIVATION_ACTION_ASK,
54 ACTIVATION_ACTION_LAUNCH,
55 ACTIVATION_ACTION_LAUNCH_IN_TERMINAL,
56 ACTIVATION_ACTION_OPEN_IN_VIEW,
57 ACTIVATION_ACTION_OPEN_IN_APPLICATION,
58 ACTIVATION_ACTION_DO_NOTHING,
59 } ActivationAction;
60
61 typedef struct {
62 NautilusFile *file;
63 char *uri;
64 } LaunchLocation;
65
66 typedef struct {
67 GAppInfo *application;
68 GList *uris;
69 } ApplicationLaunchParameters;
70
71 typedef struct {
72 NautilusWindowSlot *slot;
73 gpointer window;
74 GtkWindow *parent_window;
75 GCancellable *cancellable;
76 GList *locations;
77 GList *mountables;
78 GList *start_mountables;
79 GList *not_mounted;
80 NautilusWindowOpenFlags flags;
81 char *timed_wait_prompt;
82 gboolean timed_wait_active;
83 NautilusFileListHandle *files_handle;
84 gboolean tried_mounting;
85 char *activation_directory;
86 gboolean user_confirmation;
87 } ActivateParameters;
88
89 /* Number of seconds until cancel dialog shows up */
90 #define DELAY_UNTIL_CANCEL_MSECS 5000
91
92 #define RESPONSE_RUN 1000
93 #define RESPONSE_DISPLAY 1001
94 #define RESPONSE_RUN_IN_TERMINAL 1002
95 #define RESPONSE_MARK_TRUSTED 1003
96
97 #define SILENT_WINDOW_OPEN_LIMIT 5
98 #define SILENT_OPEN_LIMIT 5
99
100 /* This number controls a maximum character count for a URL that is
101 * displayed as part of a dialog. It's fairly arbitrary -- big enough
102 * to allow most "normal" URIs to display in full, but small enough to
103 * prevent the dialog from getting insanely wide.
104 */
105 #define MAX_URI_IN_DIALOG_LENGTH 60
106
107 static void cancel_activate_callback (gpointer callback_data);
108 static void activate_activation_uris_ready_callback (GList *files,
109 gpointer callback_data);
110 static void activation_mount_mountables (ActivateParameters *parameters);
111 static void activation_start_mountables (ActivateParameters *parameters);
112 static void activate_callback (GList *files,
113 gpointer callback_data);
114 static void activation_mount_not_mounted (ActivateParameters *parameters);
115
116
117 static void
118 launch_location_free (LaunchLocation *location)
119 {
120 nautilus_file_unref (location->file);
121 g_free (location->uri);
122 g_free (location);
123 }
124
125 static void
126 launch_location_list_free (GList *list)
127 {
128 g_list_foreach (list, (GFunc)launch_location_free, NULL);
129 g_list_free (list);
130 }
131
132 static GList *
133 get_file_list_for_launch_locations (GList *locations)
134 {
135 GList *files, *l;
136 LaunchLocation *location;
137
138 files = NULL;
139 for (l = locations; l != NULL; l = l->next) {
140 location = l->data;
141
142 files = g_list_prepend (files,
143 nautilus_file_ref (location->file));
144 }
145 return g_list_reverse (files);
146 }
147
148
149 static LaunchLocation *
150 launch_location_from_file (NautilusFile *file)
151 {
152 LaunchLocation *location;
153 location = g_new (LaunchLocation, 1);
154 location->file = nautilus_file_ref (file);
155 location->uri = nautilus_file_get_uri (file);
156
157 return location;
158 }
159
160 static void
161 launch_location_update_from_file (LaunchLocation *location,
162 NautilusFile *file)
163 {
164 nautilus_file_unref (location->file);
165 g_free (location->uri);
166 location->file = nautilus_file_ref (file);
167 location->uri = nautilus_file_get_uri (file);
168 }
169
170 static void
171 launch_location_update_from_uri (LaunchLocation *location,
172 const char *uri)
173 {
174 nautilus_file_unref (location->file);
175 g_free (location->uri);
176 location->file = nautilus_file_get_by_uri (uri);
177 location->uri = g_strdup (uri);
178 }
179
180 static LaunchLocation *
181 find_launch_location_for_file (GList *list,
182 NautilusFile *file)
183 {
184 LaunchLocation *location;
185 GList *l;
186
187 for (l = list; l != NULL; l = l->next) {
188 location = l->data;
189
190 if (location->file == file) {
191 return location;
192 }
193 }
194 return NULL;
195 }
196
197 static GList *
198 launch_locations_from_file_list (GList *list)
199 {
200 GList *new;
201
202 new = NULL;
203 while (list) {
204 new = g_list_prepend (new,
205 launch_location_from_file (list->data));
206 list = list->next;
207 }
208 new = g_list_reverse (new);
209 return new;
210 }
211
212 static ApplicationLaunchParameters *
213 application_launch_parameters_new (GAppInfo *application,
214 GList *uris)
215 {
216 ApplicationLaunchParameters *result;
217
218 result = g_new0 (ApplicationLaunchParameters, 1);
219 result->application = g_object_ref (application);
220 result->uris = eel_g_str_list_copy (uris);
221
222 return result;
223 }
224
225 static void
226 application_launch_parameters_free (ApplicationLaunchParameters *parameters)
227 {
228 g_object_unref (parameters->application);
229 g_list_free_full (parameters->uris, g_free);
230
231 g_free (parameters);
232 }
233
234 static GList*
235 filter_nautilus_handler (GList *apps)
236 {
237 GList *l, *next;
238 GAppInfo *application;
239 const char *id;
240
241 l = apps;
242 while (l != NULL) {
243 application = (GAppInfo *) l->data;
244 next = l->next;
245
246 id = g_app_info_get_id (application);
247 if (id != NULL &&
248 strcmp (id,
249 "nautilus.desktop") == 0) {
250 g_object_unref (application);
251 apps = g_list_delete_link (apps, l);
252 }
253
254 l = next;
255 }
256
257 return apps;
258 }
259
260 static GList*
261 filter_non_uri_apps (GList *apps,
262 gboolean accept_files)
263 {
264 GList *l, *next;
265 GAppInfo *app;
266
267 for (l = apps; l != NULL; l = next) {
268 gboolean support;
269
270 app = l->data;
271 next = l->next;
272 support = g_app_info_supports_uris (app);
273 if (accept_files) {
274 support |= g_app_info_supports_files (app);
275 }
276 if (!support) {
277 apps = g_list_delete_link (apps, l);
278 g_object_unref (app);
279 }
280 }
281 return apps;
282 }
283
284 static gboolean
285 nautilus_mime_actions_check_if_required_attributes_ready (NautilusFile *file)
286 {
287 NautilusFileAttributes attributes;
288 gboolean ready;
289
290 attributes = nautilus_mime_actions_get_required_file_attributes ();
291 ready = nautilus_file_check_if_ready (file, attributes);
292
293 return ready;
294 }
295
296 NautilusFileAttributes
297 nautilus_mime_actions_get_required_file_attributes (void)
298 {
299 return NAUTILUS_FILE_ATTRIBUTE_INFO |
300 NAUTILUS_FILE_ATTRIBUTE_LINK_INFO;
301 }
302
303 static gboolean
304 file_has_local_path (NautilusFile *file)
305 {
306 GFile *location;
307 char *path;
308 gboolean res;
309
310
311 /* Don't only check _is_native, because we want to support
312 using the fuse path */
313 location = nautilus_file_get_location (file);
314 if (g_file_is_native (location)) {
315 res = TRUE;
316 } else {
317 path = g_file_get_path (location);
318
319 res = path != NULL;
320
321 g_free (path);
322 }
323 g_object_unref (location);
324
325 return res;
326 }
327
328 GAppInfo *
329 nautilus_mime_get_default_application_for_file (NautilusFile *file)
330 {
331 GAppInfo *app;
332 char *mime_type;
333 char *uri_scheme;
334
335 if (!nautilus_mime_actions_check_if_required_attributes_ready (file)) {
336 return NULL;
337 }
338
339 mime_type = nautilus_file_get_mime_type (file);
340 app = g_app_info_get_default_for_type (mime_type, !file_has_local_path (file));
341 g_free (mime_type);
342
343 if (app == NULL) {
344 uri_scheme = nautilus_file_get_uri_scheme (file);
345 if (uri_scheme != NULL) {
346 app = g_app_info_get_default_for_uri_scheme (uri_scheme);
347 g_free (uri_scheme);
348 }
349 }
350
351 return app;
352 }
353
354 static int
355 file_compare_by_mime_type (NautilusFile *file_a,
356 NautilusFile *file_b)
357 {
358 char *mime_type_a, *mime_type_b;
359 int ret;
360
361 mime_type_a = nautilus_file_get_mime_type (file_a);
362 mime_type_b = nautilus_file_get_mime_type (file_b);
363
364 ret = strcmp (mime_type_a, mime_type_b);
365
366 g_free (mime_type_a);
367 g_free (mime_type_b);
368
369 return ret;
370 }
371
372 static int
373 file_compare_by_parent_uri (NautilusFile *file_a,
374 NautilusFile *file_b) {
375 char *parent_uri_a, *parent_uri_b;
376 int ret;
377
378 parent_uri_a = nautilus_file_get_parent_uri (file_a);
379 parent_uri_b = nautilus_file_get_parent_uri (file_b);
380
381 ret = strcmp (parent_uri_a, parent_uri_b);
382
383 g_free (parent_uri_a);
384 g_free (parent_uri_b);
385
386 return ret;
387 }
388
389 static int
390 application_compare_by_name (const GAppInfo *app_a,
391 const GAppInfo *app_b)
392 {
393 return g_utf8_collate (g_app_info_get_display_name ((GAppInfo *)app_a),
394 g_app_info_get_display_name ((GAppInfo *)app_b));
395 }
396
397 static int
398 application_compare_by_id (const GAppInfo *app_a,
399 const GAppInfo *app_b)
400 {
401 const char *id_a, *id_b;
402
403 id_a = g_app_info_get_id ((GAppInfo *)app_a);
404 id_b = g_app_info_get_id ((GAppInfo *)app_b);
405
406 if (id_a == NULL && id_b == NULL) {
407 if (g_app_info_equal ((GAppInfo *)app_a, (GAppInfo *)app_b)) {
408 return 0;
409 }
410 if ((gsize)app_a < (gsize) app_b) {
411 return -1;
412 }
413 return 1;
414 }
415
416 if (id_a == NULL) {
417 return -1;
418 }
419
420 if (id_b == NULL) {
421 return 1;
422 }
423
424
425 return strcmp (id_a, id_b);
426 }
427
428 GList *
429 nautilus_mime_get_applications_for_file (NautilusFile *file)
430 {
431 char *mime_type;
432 char *uri_scheme;
433 GList *result;
434 GAppInfo *uri_handler;
435
436 if (!nautilus_mime_actions_check_if_required_attributes_ready (file)) {
437 return NULL;
438 }
439 mime_type = nautilus_file_get_mime_type (file);
440 result = g_app_info_get_all_for_type (mime_type);
441
442 uri_scheme = nautilus_file_get_uri_scheme (file);
443 if (uri_scheme != NULL) {
444 uri_handler = g_app_info_get_default_for_uri_scheme (uri_scheme);
445 if (uri_handler) {
446 result = g_list_prepend (result, uri_handler);
447 }
448 g_free (uri_scheme);
449 }
450
451 /* Filter out non-uri supporting apps */
452 result = filter_non_uri_apps (result, file_has_local_path (file));
453
454 result = g_list_sort (result, (GCompareFunc) application_compare_by_name);
455 g_free (mime_type);
456
457 return filter_nautilus_handler (result);
458 }
459
460 GAppInfo *
461 nautilus_mime_get_default_application_for_files (GList *files)
462 {
463 GList *l, *sorted_files;
464 NautilusFile *file;
465 GAppInfo *app, *one_app;
466
467 g_assert (files != NULL);
468
469 sorted_files = g_list_sort (g_list_copy (files), (GCompareFunc) file_compare_by_mime_type);
470
471 app = NULL;
472 for (l = sorted_files; l != NULL; l = l->next) {
473 file = l->data;
474
475 if (l->prev &&
476 file_compare_by_mime_type (file, l->prev->data) == 0 &&
477 file_compare_by_parent_uri (file, l->prev->data) == 0) {
478 continue;
479 }
480
481 one_app = nautilus_mime_get_default_application_for_file (file);
482 if (one_app == NULL || (app != NULL && !g_app_info_equal (app, one_app))) {
483 if (app) {
484 g_object_unref (app);
485 }
486 if (one_app) {
487 g_object_unref (one_app);
488 }
489 app = NULL;
490 break;
491 }
492
493 if (app == NULL) {
494 app = one_app;
495 } else {
496 g_object_unref (one_app);
497 }
498 }
499
500 g_list_free (sorted_files);
501
502 return app;
503 }
504
505 /* returns an intersection of two mime application lists,
506 * and returns a new list, freeing a, b and all applications
507 * that are not in the intersection set.
508 * The lists are assumed to be pre-sorted by their IDs */
509 static GList *
510 intersect_application_lists (GList *a,
511 GList *b)
512 {
513 GList *l, *m;
514 GList *ret;
515 GAppInfo *a_app, *b_app;
516 int cmp;
517
518 ret = NULL;
519
520 l = a;
521 m = b;
522
523 while (l != NULL && m != NULL) {
524 a_app = (GAppInfo *) l->data;
525 b_app = (GAppInfo *) m->data;
526
527 cmp = application_compare_by_id (a_app, b_app);
528 if (cmp > 0) {
529 g_object_unref (b_app);
530 m = m->next;
531 } else if (cmp < 0) {
532 g_object_unref (a_app);
533 l = l->next;
534 } else {
535 g_object_unref (b_app);
536 ret = g_list_prepend (ret, a_app);
537 l = l->next;
538 m = m->next;
539 }
540 }
541
542 g_list_foreach (l, (GFunc) g_object_unref, NULL);
543 g_list_foreach (m, (GFunc) g_object_unref, NULL);
544
545 g_list_free (a);
546 g_list_free (b);
547
548 return g_list_reverse (ret);
549 }
550
551 GList *
552 nautilus_mime_get_applications_for_files (GList *files)
553 {
554 GList *l, *sorted_files;
555 NautilusFile *file;
556 GList *one_ret, *ret;
557
558 g_assert (files != NULL);
559
560 sorted_files = g_list_sort (g_list_copy (files), (GCompareFunc) file_compare_by_mime_type);
561
562 ret = NULL;
563 for (l = sorted_files; l != NULL; l = l->next) {
564 file = l->data;
565
566 if (l->prev &&
567 file_compare_by_mime_type (file, l->prev->data) == 0 &&
568 file_compare_by_parent_uri (file, l->prev->data) == 0) {
569 continue;
570 }
571
572 one_ret = nautilus_mime_get_applications_for_file (file);
573 one_ret = g_list_sort (one_ret, (GCompareFunc) application_compare_by_id);
574 if (ret != NULL) {
575 ret = intersect_application_lists (ret, one_ret);
576 } else {
577 ret = one_ret;
578 }
579
580 if (ret == NULL) {
581 break;
582 }
583 }
584
585 g_list_free (sorted_files);
586
587 ret = g_list_sort (ret, (GCompareFunc) application_compare_by_name);
588
589 return ret;
590 }
591
592 static void
593 trash_or_delete_files (GtkWindow *parent_window,
594 const GList *files,
595 gboolean delete_if_all_already_in_trash)
596 {
597 GList *locations;
598 const GList *node;
599
600 locations = NULL;
601 for (node = files; node != NULL; node = node->next) {
602 locations = g_list_prepend (locations,
603 nautilus_file_get_location ((NautilusFile *) node->data));
604 }
605
606 locations = g_list_reverse (locations);
607
608 nautilus_file_operations_trash_or_delete (locations,
609 parent_window,
610 NULL, NULL);
611 g_list_free_full (locations, g_object_unref);
612 }
613
614 static void
615 report_broken_symbolic_link (GtkWindow *parent_window, NautilusFile *file)
616 {
617 char *target_path;
618 char *display_name;
619 char *prompt;
620 char *detail;
621 GtkDialog *dialog;
622 GList file_as_list;
623 int response;
624 gboolean can_trash;
625
626 g_assert (nautilus_file_is_broken_symbolic_link (file));
627
628 display_name = nautilus_file_get_display_name (file);
629 can_trash = nautilus_file_can_trash (file) && !nautilus_file_is_in_trash (file);
630
631 if (can_trash) {
632 prompt = g_strdup_printf (_("The link ā%sā is broken. Move it to Trash?"), display_name);
633 } else {
634 prompt = g_strdup_printf (_("The link ā%sā is broken."), display_name);
635 }
636 g_free (display_name);
637
638 target_path = nautilus_file_get_symbolic_link_target_path (file);
639 if (target_path == NULL) {
640 detail = g_strdup (_("This link cannot be used because it has no target."));
641 } else {
642 detail = g_strdup_printf (_("This link cannot be used because its target "
643 "ā%sā doesn't exist."), target_path);
644 }
645
646 if (!can_trash) {
647 eel_run_simple_dialog (GTK_WIDGET (parent_window), FALSE, GTK_MESSAGE_WARNING,
648 prompt, detail, GTK_STOCK_CANCEL, NULL);
649 goto out;
650 }
651
652 dialog = eel_show_yes_no_dialog (prompt, detail, _("Mo_ve to Trash"), GTK_STOCK_CANCEL,
653 parent_window);
654
655 gtk_dialog_set_default_response (dialog, GTK_RESPONSE_CANCEL);
656
657 /* Make this modal to avoid problems with reffing the view & file
658 * to keep them around in case the view changes, which would then
659 * cause the old view not to be destroyed, which would cause its
660 * merged Bonobo items not to be un-merged. Maybe we need to unmerge
661 * explicitly when disconnecting views instead of relying on the
662 * unmerge in Destroy. But since BonoboUIHandler is probably going
663 * to change wildly, I don't want to mess with this now.
664 */
665
666 response = gtk_dialog_run (dialog);
667 gtk_widget_destroy (GTK_WIDGET (dialog));
668
669 if (response == GTK_RESPONSE_YES) {
670 file_as_list.data = file;
671 file_as_list.next = NULL;
672 file_as_list.prev = NULL;
673 trash_or_delete_files (parent_window, &file_as_list, TRUE);
674 }
675
676 out:
677 g_free (prompt);
678 g_free (target_path);
679 g_free (detail);
680 }
681
682 static ActivationAction
683 get_executable_text_file_action (GtkWindow *parent_window, NautilusFile *file)
684 {
685 GtkDialog *dialog;
686 char *file_name;
687 char *prompt;
688 char *detail;
689 int preferences_value;
690 int response;
691
692 g_assert (nautilus_file_contains_text (file));
693
694 preferences_value = g_settings_get_enum (nautilus_preferences,
695 NAUTILUS_PREFERENCES_EXECUTABLE_TEXT_ACTIVATION);
696 switch (preferences_value) {
697 case NAUTILUS_EXECUTABLE_TEXT_LAUNCH:
698 return ACTIVATION_ACTION_LAUNCH;
699 case NAUTILUS_EXECUTABLE_TEXT_DISPLAY:
700 return ACTIVATION_ACTION_OPEN_IN_APPLICATION;
701 case NAUTILUS_EXECUTABLE_TEXT_ASK:
702 break;
703 default:
704 /* Complain non-fatally, since preference data can't be trusted */
705 g_warning ("Unknown value %d for NAUTILUS_PREFERENCES_EXECUTABLE_TEXT_ACTIVATION",
706 preferences_value);
707
708 }
709
710
711 file_name = nautilus_file_get_display_name (file);
712 prompt = g_strdup_printf (_("Do you want to run ā%sā, or display its contents?"),
713 file_name);
714 detail = g_strdup_printf (_("ā%sā is an executable text file."),
715 file_name);
716 g_free (file_name);
717
718 dialog = eel_create_question_dialog (prompt,
719 detail,
720 _("Run in _Terminal"), RESPONSE_RUN_IN_TERMINAL,
721 _("_Display"), RESPONSE_DISPLAY,
722 parent_window);
723 gtk_dialog_add_button (dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
724 gtk_dialog_add_button (dialog, _("_Run"), RESPONSE_RUN);
725 gtk_dialog_set_default_response (dialog, GTK_RESPONSE_CANCEL);
726 gtk_widget_show (GTK_WIDGET (dialog));
727
728 g_free (prompt);
729 g_free (detail);
730
731 response = gtk_dialog_run (dialog);
732 gtk_widget_destroy (GTK_WIDGET (dialog));
733
734 switch (response) {
735 case RESPONSE_RUN:
736 return ACTIVATION_ACTION_LAUNCH;
737 case RESPONSE_RUN_IN_TERMINAL:
738 return ACTIVATION_ACTION_LAUNCH_IN_TERMINAL;
739 case RESPONSE_DISPLAY:
740 return ACTIVATION_ACTION_OPEN_IN_APPLICATION;
741 default:
742 return ACTIVATION_ACTION_DO_NOTHING;
743 }
744 }
745
746 static ActivationAction
747 get_default_executable_text_file_action (void)
748 {
749 int preferences_value;
750
751 preferences_value = g_settings_get_enum (nautilus_preferences,
752 NAUTILUS_PREFERENCES_EXECUTABLE_TEXT_ACTIVATION);
753 switch (preferences_value) {
754 case NAUTILUS_EXECUTABLE_TEXT_LAUNCH:
755 return ACTIVATION_ACTION_LAUNCH;
756 case NAUTILUS_EXECUTABLE_TEXT_DISPLAY:
757 return ACTIVATION_ACTION_OPEN_IN_APPLICATION;
758 case NAUTILUS_EXECUTABLE_TEXT_ASK:
759 default:
760 return ACTIVATION_ACTION_ASK;
761 }
762 }
763
764 gboolean
765 nautilus_mime_file_opens_in_view (NautilusFile *file)
766 {
767 return (nautilus_file_is_directory (file) ||
768 NAUTILUS_IS_DESKTOP_ICON_FILE (file));
769 }
770
771 static ActivationAction
772 get_activation_action (NautilusFile *file)
773 {
774 ActivationAction action;
775 char *activation_uri;
776
777 if (nautilus_file_is_nautilus_link (file)) {
778 return ACTIVATION_ACTION_LAUNCH_DESKTOP_FILE;
779 }
780
781 activation_uri = nautilus_file_get_activation_uri (file);
782 if (activation_uri == NULL) {
783 activation_uri = nautilus_file_get_uri (file);
784 }
785
786 action = ACTIVATION_ACTION_DO_NOTHING;
787 if (nautilus_file_is_launchable (file)) {
788 char *executable_path;
789
790 action = ACTIVATION_ACTION_LAUNCH;
791
792 executable_path = g_filename_from_uri (activation_uri, NULL, NULL);
793 if (!executable_path) {
794 action = ACTIVATION_ACTION_DO_NOTHING;
795 } else if (nautilus_file_contains_text (file)) {
796 action = get_default_executable_text_file_action ();
797 }
798 g_free (executable_path);
799 }
800
801 if (action == ACTIVATION_ACTION_DO_NOTHING) {
802 if (nautilus_mime_file_opens_in_view (file)) {
803 action = ACTIVATION_ACTION_OPEN_IN_VIEW;
804 } else {
805 action = ACTIVATION_ACTION_OPEN_IN_APPLICATION;
806 }
807 }
808 g_free (activation_uri);
809
810 return action;
811 }
812
813 gboolean
814 nautilus_mime_file_opens_in_external_app (NautilusFile *file)
815 {
816 ActivationAction activation_action;
817
818 activation_action = get_activation_action (file);
819
820 return (activation_action == ACTIVATION_ACTION_OPEN_IN_APPLICATION);
821 }
822
823
824 static unsigned int
825 mime_application_hash (GAppInfo *app)
826 {
827 const char *id;
828
829 id = g_app_info_get_id (app);
830
831 if (id == NULL) {
832 return GPOINTER_TO_UINT(app);
833 }
834
835 return g_str_hash (id);
836 }
837
838 static void
839 list_to_parameters_foreach (GAppInfo *application,
840 GList *uris,
841 GList **ret)
842 {
843 ApplicationLaunchParameters *parameters;
844
845 uris = g_list_reverse (uris);
846
847 parameters = application_launch_parameters_new
848 (application, uris);
849 *ret = g_list_prepend (*ret, parameters);
850 }
851
852
853 /**
854 * make_activation_parameters
855 *
856 * Construct a list of ApplicationLaunchParameters from a list of NautilusFiles,
857 * where files that have the same default application are put into the same
858 * launch parameter, and others are put into the unhandled_files list.
859 *
860 * @files: Files to use for construction.
861 * @unhandled_files: Files without any default application will be put here.
862 *
863 * Return value: Newly allocated list of ApplicationLaunchParameters.
864 **/
865 static GList *
866 make_activation_parameters (GList *uris,
867 GList **unhandled_uris)
868 {
869 GList *ret, *l, *app_uris;
870 NautilusFile *file;
871 GAppInfo *app, *old_app;
872 GHashTable *app_table;
873 char *uri;
874
875 ret = NULL;
876 *unhandled_uris = NULL;
877
878 app_table = g_hash_table_new_full
879 ((GHashFunc) mime_application_hash,
880 (GEqualFunc) g_app_info_equal,
881 (GDestroyNotify) g_object_unref,
882 (GDestroyNotify) g_list_free);
883
884 for (l = uris; l != NULL; l = l->next) {
885 uri = l->data;
886 file = nautilus_file_get_by_uri (uri);
887
888 app = nautilus_mime_get_default_application_for_file (file);
889 if (app != NULL) {
890 app_uris = NULL;
891
892 if (g_hash_table_lookup_extended (app_table, app,
893 (gpointer *) &old_app,
894 (gpointer *) &app_uris)) {
895 g_hash_table_steal (app_table, old_app);
896
897 app_uris = g_list_prepend (app_uris, uri);
898
899 g_object_unref (app);
900 app = old_app;
901 } else {
902 app_uris = g_list_prepend (NULL, uri);
903 }
904
905 g_hash_table_insert (app_table, app, app_uris);
906 } else {
907 *unhandled_uris = g_list_prepend (*unhandled_uris, uri);
908 }
909 nautilus_file_unref (file);
910 }
911
912 g_hash_table_foreach (app_table,
913 (GHFunc) list_to_parameters_foreach,
914 &ret);
915
916 g_hash_table_destroy (app_table);
917
918 *unhandled_uris = g_list_reverse (*unhandled_uris);
919
920 return g_list_reverse (ret);
921 }
922
923 static gboolean
924 file_was_cancelled (NautilusFile *file)
925 {
926 GError *error;
927
928 error = nautilus_file_get_file_info_error (file);
929 return
930 error != NULL &&
931 error->domain == G_IO_ERROR &&
932 error->code == G_IO_ERROR_CANCELLED;
933 }
934
935 static gboolean
936 file_was_not_mounted (NautilusFile *file)
937 {
938 GError *error;
939
940 error = nautilus_file_get_file_info_error (file);
941 return
942 error != NULL &&
943 error->domain == G_IO_ERROR &&
944 error->code == G_IO_ERROR_NOT_MOUNTED;
945 }
946
947 static void
948 activation_parameters_free (ActivateParameters *parameters)
949 {
950 if (parameters->timed_wait_active) {
951 eel_timed_wait_stop (cancel_activate_callback, parameters);
952 }
953
954 if (parameters->slot) {
955 g_object_remove_weak_pointer (G_OBJECT (parameters->slot), (gpointer *)¶meters->slot);
956 }
957 if (parameters->parent_window) {
958 g_object_remove_weak_pointer (G_OBJECT (parameters->parent_window), (gpointer *)¶meters->parent_window);
959 }
960 g_object_unref (parameters->cancellable);
961 launch_location_list_free (parameters->locations);
962 nautilus_file_list_free (parameters->mountables);
963 nautilus_file_list_free (parameters->start_mountables);
964 nautilus_file_list_free (parameters->not_mounted);
965 g_free (parameters->activation_directory);
966 g_free (parameters->timed_wait_prompt);
967 g_assert (parameters->files_handle == NULL);
968 g_free (parameters);
969 }
970
971 static void
972 cancel_activate_callback (gpointer callback_data)
973 {
974 ActivateParameters *parameters = callback_data;
975
976 parameters->timed_wait_active = FALSE;
977
978 g_cancellable_cancel (parameters->cancellable);
979
980 if (parameters->files_handle) {
981 nautilus_file_list_cancel_call_when_ready (parameters->files_handle);
982 parameters->files_handle = NULL;
983 activation_parameters_free (parameters);
984 }
985 }
986
987 static void
988 activation_start_timed_cancel (ActivateParameters *parameters)
989 {
990 parameters->timed_wait_active = TRUE;
991 eel_timed_wait_start_with_duration
992 (DELAY_UNTIL_CANCEL_MSECS,
993 cancel_activate_callback,
994 parameters,
995 parameters->timed_wait_prompt,
996 parameters->parent_window);
997 }
998
999 static void
1000 pause_activation_timed_cancel (ActivateParameters *parameters)
1001 {
1002 if (parameters->timed_wait_active) {
1003 eel_timed_wait_stop (cancel_activate_callback, parameters);
1004 parameters->timed_wait_active = FALSE;
1005 }
1006 }
1007
1008 static void
1009 unpause_activation_timed_cancel (ActivateParameters *parameters)
1010 {
1011 if (!parameters->timed_wait_active) {
1012 activation_start_timed_cancel (parameters);
1013 }
1014 }
1015
1016
1017 static void
1018 activate_mount_op_active (GtkMountOperation *operation,
1019 GParamSpec *pspec,
1020 ActivateParameters *parameters)
1021 {
1022 gboolean is_active;
1023
1024 g_object_get (operation, "is-showing", &is_active, NULL);
1025
1026 if (is_active) {
1027 pause_activation_timed_cancel (parameters);
1028 } else {
1029 unpause_activation_timed_cancel (parameters);
1030 }
1031 }
1032
1033 static gboolean
1034 confirm_multiple_windows (GtkWindow *parent_window,
1035 int count,
1036 gboolean use_tabs)
1037 {
1038 GtkDialog *dialog;
1039 char *prompt;
1040 char *detail;
1041 int response;
1042
1043 if (count <= SILENT_WINDOW_OPEN_LIMIT) {
1044 return TRUE;
1045 }
1046
1047 prompt = _("Are you sure you want to open all files?");
1048 if (use_tabs) {
1049 detail = g_strdup_printf (ngettext("This will open %d separate tab.",
1050 "This will open %d separate tabs.", count), count);
1051 } else {
1052 detail = g_strdup_printf (ngettext("This will open %d separate window.",
1053 "This will open %d separate windows.", count), count);
1054 }
1055 dialog = eel_show_yes_no_dialog (prompt, detail,
1056 GTK_STOCK_OK, GTK_STOCK_CANCEL,
1057 parent_window);
1058 g_free (detail);
1059
1060 response = gtk_dialog_run (dialog);
1061 gtk_widget_destroy (GTK_WIDGET (dialog));
1062
1063 return response == GTK_RESPONSE_YES;
1064 }
1065
1066 typedef struct {
1067 NautilusWindowSlot *slot;
1068 GtkWindow *parent_window;
1069 NautilusFile *file;
1070 GList *files;
1071 NautilusWindowOpenFlags flags;
1072 char *activation_directory;
1073 gboolean user_confirmation;
1074 char *uri;
1075 GDBusProxy *proxy;
1076 GtkWidget *dialog;
1077 } ActivateParametersInstall;
1078
1079 static void
1080 activate_parameters_install_free (ActivateParametersInstall *parameters_install)
1081 {
1082 if (parameters_install->slot) {
1083 g_object_remove_weak_pointer (G_OBJECT (parameters_install->slot), (gpointer *)¶meters_install->slot);
1084 }
1085 if (parameters_install->parent_window) {
1086 g_object_remove_weak_pointer (G_OBJECT (parameters_install->parent_window), (gpointer *)¶meters_install->parent_window);
1087 }
1088
1089 if (parameters_install->proxy != NULL) {
1090 g_object_unref (parameters_install->proxy);
1091 }
1092
1093 nautilus_file_unref (parameters_install->file);
1094 nautilus_file_list_free (parameters_install->files);
1095 g_free (parameters_install->activation_directory);
1096 g_free (parameters_install->uri);
1097 g_free (parameters_install);
1098 }
1099
1100 static char *
1101 get_application_no_mime_type_handler_message (NautilusFile *file, char *uri)
1102 {
1103 char *uri_for_display;
1104 char *name;
1105 char *error_message;
1106
1107 name = nautilus_file_get_display_name (file);
1108
1109 /* Truncate the URI so it doesn't get insanely wide. Note that even
1110 * though the dialog uses wrapped text, if the URI doesn't contain
1111 * white space then the text-wrapping code is too stupid to wrap it.
1112 */
1113 uri_for_display = eel_str_middle_truncate (name, MAX_URI_IN_DIALOG_LENGTH);
1114 error_message = g_strdup_printf (_("Could not display ā%sā."), uri_for_display);
1115 g_free (uri_for_display);
1116 g_free (name);
1117
1118 return error_message;
1119 }
1120
1121 static void
1122 open_with_response_cb (GtkDialog *dialog,
1123 gint response_id,
1124 gpointer user_data)
1125 {
1126 GtkWindow *parent_window;
1127 NautilusFile *file;
1128 GList files;
1129 GAppInfo *info;
1130 ActivateParametersInstall *parameters = user_data;
1131
1132 if (response_id != GTK_RESPONSE_OK) {
1133 gtk_widget_destroy (GTK_WIDGET (dialog));
1134 return;
1135 }
1136
1137 parent_window = parameters->parent_window;
1138 file = g_object_get_data (G_OBJECT (dialog), "mime-action:file");
1139 info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (dialog));
1140
1141 gtk_widget_destroy (GTK_WIDGET (dialog));
1142
1143 g_signal_emit_by_name (nautilus_signaller_get_current (), "mime_data_changed");
1144
1145 files.next = NULL;
1146 files.prev = NULL;
1147 files.data = file;
1148 nautilus_launch_application (info, &files, parent_window);
1149
1150 g_object_unref (info);
1151
1152 activate_parameters_install_free (parameters);
1153 }
1154
1155 static void
1156 choose_program (GtkDialog *message_dialog, int response, gpointer callback_data)
1157 {
1158 GtkWidget *dialog;
1159 NautilusFile *file;
1160 GFile *location;
1161 ActivateParametersInstall *parameters = callback_data;
1162
1163 if (response != GTK_RESPONSE_ACCEPT){
1164 gtk_widget_destroy (GTK_WIDGET (message_dialog));
1165 activate_parameters_install_free (parameters);
1166 return;
1167 }
1168
1169 file = g_object_get_data (G_OBJECT (message_dialog), "mime-action:file");
1170
1171 g_assert (NAUTILUS_IS_FILE (file));
1172
1173 location = nautilus_file_get_location (file);
1174 nautilus_file_ref (file);
1175
1176 /* Destroy the message dialog after ref:ing the file */
1177 gtk_widget_destroy (GTK_WIDGET (message_dialog));
1178
1179 dialog = gtk_app_chooser_dialog_new (parameters->parent_window,
1180 0, location);
1181 g_object_set_data_full (G_OBJECT (dialog),
1182 "mime-action:file",
1183 nautilus_file_ref (file),
1184 (GDestroyNotify)nautilus_file_unref);
1185
1186 gtk_widget_show (dialog);
1187
1188 g_signal_connect (dialog,
1189 "response",
1190 G_CALLBACK (open_with_response_cb),
1191 parameters);
1192
1193 g_object_unref (location);
1194 nautilus_file_unref (file);
1195 }
1196
1197 static void
1198 show_unhandled_type_error (ActivateParametersInstall *parameters)
1199 {
1200 GtkWidget *dialog;
1201
1202 char *mime_type = nautilus_file_get_mime_type (parameters->file);
1203 char *error_message = get_application_no_mime_type_handler_message (parameters->file, parameters->uri);
1204 if (g_content_type_is_unknown (mime_type)) {
1205 dialog = gtk_message_dialog_new (parameters->parent_window,
1206 GTK_DIALOG_DESTROY_WITH_PARENT,
1207 GTK_MESSAGE_ERROR,
1208 0,
1209 NULL);
1210 g_object_set (dialog,
1211 "text", error_message,
1212 "secondary-text", _("The file is of an unknown type"),
1213 NULL);
1214 } else {
1215 char *text;
1216 text = g_strdup_printf (_("There is no application installed for ā%sā files"), g_content_type_get_description (mime_type));
1217
1218 dialog = gtk_message_dialog_new (parameters->parent_window,
1219 GTK_DIALOG_DESTROY_WITH_PARENT,
1220 GTK_MESSAGE_ERROR,
1221 0,
1222 NULL);
1223 g_object_set (dialog,
1224 "text", error_message,
1225 "secondary-text", text,
1226 NULL);
1227
1228 g_free (text);
1229 }
1230
1231 gtk_dialog_add_button (GTK_DIALOG (dialog), _("_Select Application"), GTK_RESPONSE_ACCEPT);
1232
1233 gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_OK, GTK_RESPONSE_OK);
1234
1235 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
1236
1237 g_object_set_data_full (G_OBJECT (dialog),
1238 "mime-action:file",
1239 nautilus_file_ref (parameters->file),
1240 (GDestroyNotify)nautilus_file_unref);
1241
1242 gtk_widget_show (GTK_WIDGET (dialog));
1243
1244 g_signal_connect (dialog, "response",
1245 G_CALLBACK (choose_program), parameters);
1246
1247 g_free (error_message);
1248 g_free (mime_type);
1249 }
1250
1251 static void
1252 search_for_application_dbus_call_notify_cb (GDBusProxy *proxy,
1253 GAsyncResult *result,
1254 gpointer user_data)
1255 {
1256 ActivateParametersInstall *parameters_install = user_data;
1257 GVariant *variant;
1258 GError *error = NULL;
1259
1260 variant = g_dbus_proxy_call_finish (proxy, result, &error);
1261 if (variant == NULL) {
1262 if (!g_dbus_error_is_remote_error (error) ||
1263 g_strcmp0 (g_dbus_error_get_remote_error (error), "org.freedesktop.PackageKit.Modify.Failed") == 0) {
1264 char *message;
1265
1266 message = g_strdup_printf ("%s\n%s",
1267 _("There was an internal error trying to search for applications:"),
1268 error->message);
1269 eel_show_error_dialog (_("Unable to search for application"), message,
1270 parameters_install->parent_window);
1271 g_free (message);
1272 }
1273
1274 g_error_free (error);
1275 activate_parameters_install_free (parameters_install);
1276 return;
1277 }
1278
1279 g_variant_unref (variant);
1280
1281 /* activate the file again */
1282 nautilus_mime_activate_files (parameters_install->parent_window,
1283 parameters_install->slot,
1284 parameters_install->files,
1285 parameters_install->activation_directory,
1286 parameters_install->flags,
1287 parameters_install->user_confirmation);
1288
1289 activate_parameters_install_free (parameters_install);
1290 }
1291
1292 static void
1293 search_for_application_mime_type (ActivateParametersInstall *parameters_install, const gchar *mime_type)
1294 {
1295 GdkWindow *window;
1296 guint xid = 0;
1297 const char *mime_types[2];
1298
1299 g_assert (parameters_install->proxy != NULL);
1300
1301 /* get XID from parent window */
1302 window = gtk_widget_get_window (GTK_WIDGET (parameters_install->parent_window));
1303 if (window != NULL) {
1304 xid = GDK_WINDOW_XID (window);
1305 }
1306
1307 mime_types[0] = mime_type;
1308 mime_types[1] = NULL;
1309
1310 g_dbus_proxy_call (parameters_install->proxy,
1311 "InstallMimeTypes",
1312 g_variant_new ("(u^ass)",
1313 xid,
1314 mime_types,
1315 "hide-confirm-search"),
1316 G_DBUS_CALL_FLAGS_NONE,
1317 G_MAXINT /* no timeout */,
1318 NULL /* cancellable */,
1319 (GAsyncReadyCallback) search_for_application_dbus_call_notify_cb,
1320 parameters_install);
1321
1322 DEBUG ("InstallMimeType method invoked for %s", mime_type);
1323 }
1324
1325 static void
1326 application_unhandled_file_install (GtkDialog *dialog,
1327 gint response_id,
1328 ActivateParametersInstall *parameters_install)
1329 {
1330 char *mime_type;
1331
1332 gtk_widget_destroy (GTK_WIDGET (dialog));
1333 parameters_install->dialog = NULL;
1334
1335 if (response_id == GTK_RESPONSE_YES) {
1336 mime_type = nautilus_file_get_mime_type (parameters_install->file);
1337 search_for_application_mime_type (parameters_install, mime_type);
1338 g_free (mime_type);
1339 } else {
1340 /* free as we're not going to get the async dbus callback */
1341 activate_parameters_install_free (parameters_install);
1342 }
1343 }
1344
1345 static gboolean
1346 delete_cb (GtkDialog *dialog)
1347 {
1348 gtk_dialog_response (dialog, GTK_RESPONSE_DELETE_EVENT);
1349 return TRUE;
1350 }
1351
1352 static void
1353 pk_proxy_appeared_cb (GObject *source,
1354 GAsyncResult *res,
1355 gpointer user_data)
1356 {
1357 ActivateParametersInstall *parameters_install = user_data;
1358 char *mime_type;
1359 char *error_message;
1360 GtkWidget *dialog;
1361 GDBusProxy *proxy;
1362 GError *error = NULL;
1363
1364 proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
1365
1366 if (error != NULL) {
1367 g_warning ("Couldn't call Modify on the PackageKit interface: %s",
1368 error->message);
1369 g_error_free (error);
1370
1371 /* show an unhelpful dialog */
1372 show_unhandled_type_error (parameters_install);
1373 /* The callback wasn't started, so we have to free the parameters */
1374 activate_parameters_install_free (parameters_install);
1375
1376 return;
1377 }
1378
1379 mime_type = nautilus_file_get_mime_type (parameters_install->file);
1380 error_message = get_application_no_mime_type_handler_message (parameters_install->file,
1381 parameters_install->uri);
1382 /* use a custom dialog to prompt the user to install new software */
1383 dialog = gtk_message_dialog_new (parameters_install->parent_window, 0,
1384 GTK_MESSAGE_ERROR,
1385 GTK_BUTTONS_YES_NO,
1386 "%s", error_message);
1387 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
1388 _("There is no application installed for ā%sā files.\n"
1389 "Do you want to search for an application to open this file?"),
1390 g_content_type_get_description (mime_type));
1391 gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
1392
1393 parameters_install->dialog = dialog;
1394 parameters_install->proxy = proxy;
1395
1396 g_signal_connect (dialog, "response",
1397 G_CALLBACK (application_unhandled_file_install),
1398 parameters_install);
1399 g_signal_connect (dialog, "delete-event",
1400 G_CALLBACK (delete_cb), NULL);
1401 gtk_widget_show_all (dialog);
1402 g_free (mime_type);
1403 }
1404
1405 static void
1406 application_unhandled_uri (ActivateParameters *parameters, char *uri)
1407 {
1408 gboolean show_install_mime;
1409 char *mime_type;
1410 NautilusFile *file;
1411 ActivateParametersInstall *parameters_install;
1412
1413 file = nautilus_file_get_by_uri (uri);
1414
1415 mime_type = nautilus_file_get_mime_type (file);
1416
1417 /* copy the parts of parameters we are interested in as the orignal will be unref'd */
1418 parameters_install = g_new0 (ActivateParametersInstall, 1);
1419 parameters_install->slot = parameters->slot;
1420 g_object_add_weak_pointer (G_OBJECT (parameters_install->slot), (gpointer *)¶meters_install->slot);
1421 if (parameters->parent_window) {
1422 parameters_install->parent_window = parameters->parent_window;
1423 g_object_add_weak_pointer (G_OBJECT (parameters_install->parent_window), (gpointer *)¶meters_install->parent_window);
1424 }
1425 parameters_install->activation_directory = g_strdup (parameters->activation_directory);
1426 parameters_install->file = file;
1427 parameters_install->files = get_file_list_for_launch_locations (parameters->locations);
1428 parameters_install->flags = parameters->flags;
1429 parameters_install->user_confirmation = parameters->user_confirmation;
1430 parameters_install->uri = g_strdup(uri);
1431
1432 #ifdef ENABLE_PACKAGEKIT
1433 /* allow an admin to disable the PackageKit search functionality */
1434 show_install_mime = g_settings_get_boolean (nautilus_preferences, NAUTILUS_PREFERENCES_INSTALL_MIME_ACTIVATION);
1435 #else
1436 /* we have no install functionality */
1437 show_install_mime = FALSE;
1438 #endif
1439 /* There is no use trying to look for handlers of application/octet-stream */
1440 if (g_content_type_is_unknown (mime_type)) {
1441 show_install_mime = FALSE;
1442 }
1443
1444 g_free (mime_type);
1445
1446 if (!show_install_mime) {
1447 goto out;
1448 }
1449
1450 g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
1451 G_DBUS_PROXY_FLAGS_NONE,
1452 NULL,
1453 "org.freedesktop.PackageKit",
1454 "/org/freedesktop/PackageKit",
1455 "org.freedesktop.PackageKit.Modify",
1456 NULL,
1457 pk_proxy_appeared_cb,
1458 parameters_install);
1459
1460 return;
1461
1462 out:
1463 /* show an unhelpful dialog */
1464 show_unhandled_type_error (parameters_install);
1465 }
1466
1467 typedef struct {
1468 GtkWindow *parent_window;
1469 NautilusFile *file;
1470 } ActivateParametersDesktop;
1471
1472 static void
1473 activate_parameters_desktop_free (ActivateParametersDesktop *parameters_desktop)
1474 {
1475 if (parameters_desktop->parent_window) {
1476 g_object_remove_weak_pointer (G_OBJECT (parameters_desktop->parent_window), (gpointer *)¶meters_desktop->parent_window);
1477 }
1478 nautilus_file_unref (parameters_desktop->file);
1479 g_free (parameters_desktop);
1480 }
1481
1482 static void
1483 untrusted_launcher_response_callback (GtkDialog *dialog,
1484 int response_id,
1485 ActivateParametersDesktop *parameters)
1486 {
1487 GdkScreen *screen;
1488 char *uri;
1489 GFile *file;
1490
1491 switch (response_id) {
1492 case RESPONSE_RUN:
1493 screen = gtk_widget_get_screen (GTK_WIDGET (parameters->parent_window));
1494 uri = nautilus_file_get_uri (parameters->file);
1495 DEBUG ("Launching untrusted launcher %s", uri);
1496 nautilus_launch_desktop_file (screen, uri, NULL,
1497 parameters->parent_window);
1498 g_free (uri);
1499 break;
1500 case RESPONSE_MARK_TRUSTED:
1501 file = nautilus_file_get_location (parameters->file);
1502 nautilus_file_mark_desktop_file_trusted (file,
1503 parameters->parent_window,
1504 TRUE,
1505 NULL, NULL);
1506 g_object_unref (file);
1507 break;
1508 default:
1509 /* Just destroy dialog */
1510 break;
1511 }
1512
1513 gtk_widget_destroy (GTK_WIDGET (dialog));
1514 activate_parameters_desktop_free (parameters);
1515 }
1516
1517 static void
1518 activate_desktop_file (ActivateParameters *parameters,
1519 NautilusFile *file)
1520 {
1521 ActivateParametersDesktop *parameters_desktop;
1522 char *primary, *secondary, *display_name;
1523 GtkWidget *dialog;
1524 GdkScreen *screen;
1525 char *uri;
1526
1527 screen = gtk_widget_get_screen (GTK_WIDGET (parameters->parent_window));
1528
1529 if (!nautilus_file_is_trusted_link (file)) {
1530 /* copy the parts of parameters we are interested in as the orignal will be freed */
1531 parameters_desktop = g_new0 (ActivateParametersDesktop, 1);
1532 if (parameters->parent_window) {
1533 parameters_desktop->parent_window = parameters->parent_window;
1534 g_object_add_weak_pointer (G_OBJECT (parameters_desktop->parent_window), (gpointer *)¶meters_desktop->parent_window);
1535 }
1536 parameters_desktop->file = nautilus_file_ref (file);
1537
1538 primary = _("Untrusted application launcher");
1539 display_name = nautilus_file_get_display_name (file);
1540 secondary =
1541 g_strdup_printf (_("The application launcher ā%sā has not been marked as trusted. "
1542 "If you do not know the source of this file, launching it may be unsafe."
1543 ),
1544 display_name);
1545
1546 dialog = gtk_message_dialog_new (parameters->parent_window,
1547 0,
1548 GTK_MESSAGE_WARNING,
1549 GTK_BUTTONS_NONE,
1550 NULL);
1551 g_object_set (dialog,
1552 "text", primary,
1553 "secondary-text", secondary,
1554 NULL);
1555 gtk_dialog_add_button (GTK_DIALOG (dialog),
1556 _("_Launch Anyway"), RESPONSE_RUN);
1557 if (nautilus_file_can_set_permissions (file)) {
1558 gtk_dialog_add_button (GTK_DIALOG (dialog),
1559 _("Mark as _Trusted"), RESPONSE_MARK_TRUSTED);
1560 }
1561 gtk_dialog_add_button (GTK_DIALOG (dialog),
1562 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
1563 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
1564
1565 g_signal_connect (dialog, "response",
1566 G_CALLBACK (untrusted_launcher_response_callback),
1567 parameters_desktop);
1568 gtk_widget_show (dialog);
1569
1570 g_free (display_name);
1571 g_free (secondary);
1572 return;
1573 }
1574
1575 uri = nautilus_file_get_uri (file);
1576 DEBUG ("Launching trusted launcher %s", uri);
1577 nautilus_launch_desktop_file (screen, uri, NULL,
1578 parameters->parent_window);
1579 g_free (uri);
1580 }
1581
1582 static void
1583 activate_files (ActivateParameters *parameters)
1584 {
1585 NautilusWindow *window;
1586 NautilusWindowOpenFlags flags;
1587 NautilusFile *file;
1588 GList *launch_desktop_files;
1589 GList *launch_files;
1590 GList *launch_in_terminal_files;
1591 GList *open_in_app_uris;
1592 GList *open_in_app_parameters;
1593 GList *unhandled_open_in_app_uris;
1594 ApplicationLaunchParameters *one_parameters;
1595 GList *open_in_view_files;
1596 GList *l;
1597 int count;
1598 char *uri;
1599 char *executable_path, *quoted_path;
1600 char *old_working_dir;
1601 ActivationAction action;
1602 GdkScreen *screen;
1603 LaunchLocation *location;
1604 gint num_apps;
1605 gint num_unhandled;
1606 gint num_files;
1607 gboolean open_files;
1608
1609 screen = gtk_widget_get_screen (GTK_WIDGET (parameters->parent_window));
1610
1611 launch_desktop_files = NULL;
1612 launch_files = NULL;
1613 launch_in_terminal_files = NULL;
1614 open_in_app_uris = NULL;
1615 open_in_view_files = NULL;
1616
1617 for (l = parameters->locations; l != NULL; l = l->next) {
1618 location = l->data;
1619 file = location->file;
1620
1621 if (file_was_cancelled (file)) {
1622 continue;
1623 }
1624
1625 action = get_activation_action (file);
1626 if (action == ACTIVATION_ACTION_ASK) {
1627 /* Special case for executable text files, since it might be
1628 * dangerous & unexpected to launch these.
1629 */
1630 pause_activation_timed_cancel (parameters);
1631 action = get_executable_text_file_action (parameters->parent_window, file);
1632 unpause_activation_timed_cancel (parameters);
1633 }
1634
1635 switch (action) {
1636 case ACTIVATION_ACTION_LAUNCH_DESKTOP_FILE :
1637 launch_desktop_files = g_list_prepend (launch_desktop_files, file);
1638 break;
1639 case ACTIVATION_ACTION_LAUNCH :
1640 launch_files = g_list_prepend (launch_files, file);
1641 break;
1642 case ACTIVATION_ACTION_LAUNCH_IN_TERMINAL :
1643 launch_in_terminal_files = g_list_prepend (launch_in_terminal_files, file);
1644 break;
1645 case ACTIVATION_ACTION_OPEN_IN_VIEW :
1646 open_in_view_files = g_list_prepend (open_in_view_files, file);
1647 break;
1648 case ACTIVATION_ACTION_OPEN_IN_APPLICATION :
1649 open_in_app_uris = g_list_prepend (open_in_app_uris, location->uri);
1650 break;
1651 case ACTIVATION_ACTION_DO_NOTHING :
1652 break;
1653 case ACTIVATION_ACTION_ASK :
1654 g_assert_not_reached ();
1655 break;
1656 }
1657 }
1658
1659 launch_desktop_files = g_list_reverse (launch_desktop_files);
1660 for (l = launch_desktop_files; l != NULL; l = l->next) {
1661 file = NAUTILUS_FILE (l->data);
1662
1663 activate_desktop_file (parameters, file);
1664 }
1665
1666 old_working_dir = NULL;
1667 if (parameters->activation_directory &&
1668 (launch_files != NULL || launch_in_terminal_files != NULL)) {
1669 old_working_dir = g_get_current_dir ();
1670 g_chdir (parameters->activation_directory);
1671
1672 }
1673
1674 launch_files = g_list_reverse (launch_files);
1675 for (l = launch_files; l != NULL; l = l->next) {
1676 file = NAUTILUS_FILE (l->data);
1677
1678 uri = nautilus_file_get_activation_uri (file);
1679 executable_path = g_filename_from_uri (uri, NULL, NULL);
1680 quoted_path = g_shell_quote (executable_path);
1681
1682 DEBUG ("Launching file path %s", quoted_path);
1683
1684 nautilus_launch_application_from_command (screen, quoted_path, FALSE, NULL);
1685 g_free (quoted_path);
1686 g_free (executable_path);
1687 g_free (uri);
1688
1689 }
1690
1691 launch_in_terminal_files = g_list_reverse (launch_in_terminal_files);
1692 for (l = launch_in_terminal_files; l != NULL; l = l->next) {
1693 file = NAUTILUS_FILE (l->data);
1694
1695 uri = nautilus_file_get_activation_uri (file);
1696 executable_path = g_filename_from_uri (uri, NULL, NULL);
1697 quoted_path = g_shell_quote (executable_path);
1698
1699 DEBUG ("Launching in terminal file quoted path %s", quoted_path);
1700
1701 nautilus_launch_application_from_command (screen, quoted_path, TRUE, NULL);
1702
1703 g_free (quoted_path);
1704 g_free (executable_path);
1705 g_free (uri);
1706 }
1707
1708 if (old_working_dir != NULL) {
1709 g_chdir (old_working_dir);
1710 g_free (old_working_dir);
1711 }
1712
1713 open_in_view_files = g_list_reverse (open_in_view_files);
1714 count = g_list_length (open_in_view_files);
1715
1716 flags = parameters->flags;
1717 if (count > 1) {
1718 if ((parameters->flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW) == 0) {
1719 flags |= NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB;
1720 } else {
1721 flags |= NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW;
1722 }
1723 }
1724
1725 if (parameters->slot != NULL &&
1726 (!parameters->user_confirmation ||
1727 confirm_multiple_windows (parameters->parent_window, count,
1728 (flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB) != 0))) {
1729
1730 if ((flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB) != 0 &&
1731 g_settings_get_enum (nautilus_preferences, NAUTILUS_PREFERENCES_NEW_TAB_POSITION) ==
1732 NAUTILUS_NEW_TAB_POSITION_AFTER_CURRENT_TAB) {
1733 /* When inserting N tabs after the current one,
1734 * we first open tab N, then tab N-1, ..., then tab 0.
1735 * Each of them is appended to the current tab, i.e.
1736 * prepended to the list of tabs to open.
1737 */
1738 open_in_view_files = g_list_reverse (open_in_view_files);
1739 }
1740
1741
1742 for (l = open_in_view_files; l != NULL; l = l->next) {
1743 GFile *f;
1744 /* The ui should ask for navigation or object windows
1745 * depending on what the current one is */
1746 file = NAUTILUS_FILE (l->data);
1747
1748 uri = nautilus_file_get_activation_uri (file);
1749 f = g_file_new_for_uri (uri);
1750 nautilus_window_slot_open_location (parameters->slot, f, flags);
1751 g_object_unref (f);
1752 g_free (uri);
1753 }
1754 }
1755
1756 open_in_app_parameters = NULL;
1757 unhandled_open_in_app_uris = NULL;
1758
1759 if (open_in_app_uris != NULL) {
1760 open_in_app_uris = g_list_reverse (open_in_app_uris);
1761
1762 open_in_app_parameters = make_activation_parameters
1763 (open_in_app_uris, &unhandled_open_in_app_uris);
1764 }
1765
1766 num_apps = g_list_length (open_in_app_parameters);
1767 num_unhandled = g_list_length (unhandled_open_in_app_uris);
1768 num_files = g_list_length (open_in_app_uris);
1769 open_files = TRUE;
1770
1771 if (open_in_app_uris != NULL &&
1772 (!parameters->user_confirmation ||
1773 num_files + num_unhandled > SILENT_OPEN_LIMIT) &&
1774 num_apps > 1) {
1775 GtkDialog *dialog;
1776 char *prompt;
1777 char *detail;
1778 int response;
1779
1780 pause_activation_timed_cancel (parameters);
1781
1782 prompt = _("Are you sure you want to open all files?");
1783 detail = g_strdup_printf (ngettext ("This will open %d separate application.",
1784 "This will open %d separate applications.", num_apps), num_apps);
1785 dialog = eel_show_yes_no_dialog (prompt, detail,
1786 GTK_STOCK_OK, GTK_STOCK_CANCEL,
1787 parameters->parent_window);
1788 g_free (detail);
1789
1790 response = gtk_dialog_run (dialog);
1791 gtk_widget_destroy (GTK_WIDGET (dialog));
1792
1793 unpause_activation_timed_cancel (parameters);
1794
1795 if (response != GTK_RESPONSE_YES) {
1796 open_files = FALSE;
1797 }
1798 }
1799
1800 if (open_files) {
1801 for (l = open_in_app_parameters; l != NULL; l = l->next) {
1802 one_parameters = l->data;
1803
1804 nautilus_launch_application_by_uri (one_parameters->application,
1805 one_parameters->uris,
1806 parameters->parent_window);
1807 application_launch_parameters_free (one_parameters);
1808 }
1809
1810 for (l = unhandled_open_in_app_uris; l != NULL; l = l->next) {
1811 uri = l->data;
1812
1813 /* this does not block */
1814 application_unhandled_uri (parameters, uri);
1815 }
1816 }
1817
1818 window = NULL;
1819 if (parameters->slot != NULL) {
1820 window = nautilus_window_slot_get_window (parameters->slot);
1821 }
1822
1823 if (open_in_app_parameters != NULL ||
1824 unhandled_open_in_app_uris != NULL) {
1825 if ((parameters->flags & NAUTILUS_WINDOW_OPEN_FLAG_CLOSE_BEHIND) != 0 &&
1826 window != NULL) {
1827 nautilus_window_close (window);
1828 }
1829 }
1830
1831 g_list_free (launch_desktop_files);
1832 g_list_free (launch_files);
1833 g_list_free (launch_in_terminal_files);
1834 g_list_free (open_in_view_files);
1835 g_list_free (open_in_app_uris);
1836 g_list_free (open_in_app_parameters);
1837 g_list_free (unhandled_open_in_app_uris);
1838
1839 activation_parameters_free (parameters);
1840 }
1841
1842 static void
1843 activation_mount_not_mounted_callback (GObject *source_object,
1844 GAsyncResult *res,
1845 gpointer user_data)
1846 {
1847 ActivateParameters *parameters = user_data;
1848 GError *error;
1849 NautilusFile *file;
1850 LaunchLocation *loc;
1851
1852 file = parameters->not_mounted->data;
1853
1854 error = NULL;
1855 if (!g_file_mount_enclosing_volume_finish (G_FILE (source_object), res, &error)) {
1856 if (error->domain != G_IO_ERROR ||
1857 (error->code != G_IO_ERROR_CANCELLED &&
1858 error->code != G_IO_ERROR_FAILED_HANDLED &&
1859 error->code != G_IO_ERROR_ALREADY_MOUNTED)) {
1860 eel_show_error_dialog (_("Unable to access location"), error->message, parameters->parent_window);
1861 }
1862
1863 if (error->domain != G_IO_ERROR ||
1864 error->code != G_IO_ERROR_ALREADY_MOUNTED) {
1865 loc = find_launch_location_for_file (parameters->locations,
1866 file);
1867 if (loc) {
1868 parameters->locations =
1869 g_list_remove (parameters->locations, loc);
1870 launch_location_free (loc);
1871 }
1872 }
1873
1874 g_error_free (error);
1875 }
1876
1877 parameters->not_mounted = g_list_delete_link (parameters->not_mounted,
1878 parameters->not_mounted);
1879 nautilus_file_unref (file);
1880
1881 activation_mount_not_mounted (parameters);
1882 }
1883
1884 static void
1885 activation_mount_not_mounted (ActivateParameters *parameters)
1886 {
1887 NautilusFile *file;
1888 GFile *location;
1889 LaunchLocation *loc;
1890 GMountOperation *mount_op;
1891 GList *l, *next, *files;
1892
1893 if (parameters->not_mounted != NULL) {
1894 file = parameters->not_mounted->data;
1895 mount_op = gtk_mount_operation_new (parameters->parent_window);
1896 g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION);
1897 g_signal_connect (mount_op, "notify::is-showing",
1898 G_CALLBACK (activate_mount_op_active), parameters);
1899 location = nautilus_file_get_location (file);
1900 g_file_mount_enclosing_volume (location, 0, mount_op, parameters->cancellable,
1901 activation_mount_not_mounted_callback, parameters);
1902 g_object_unref (location);
1903 /* unref mount_op here - g_file_mount_enclosing_volume() does ref for itself */
1904 g_object_unref (mount_op);
1905 return;
1906 }
1907
1908 parameters->tried_mounting = TRUE;
1909
1910 if (parameters->locations == NULL) {
1911 activation_parameters_free (parameters);
1912 return;
1913 }
1914
1915 /* once the mount is finished, refresh all attributes */
1916 /* - fixes new windows not appearing after successful mount */
1917 for (l = parameters->locations; l != NULL; l = next) {
1918 loc = l->data;
1919 next = l->next;
1920 nautilus_file_invalidate_all_attributes (loc->file);
1921 }
1922
1923 files = get_file_list_for_launch_locations (parameters->locations);
1924 nautilus_file_list_call_when_ready
1925 (files,
1926 nautilus_mime_actions_get_required_file_attributes () | NAUTILUS_FILE_ATTRIBUTE_LINK_INFO,
1927 ¶meters->files_handle,
1928 activate_callback, parameters);
1929 nautilus_file_list_free (files);
1930 }
1931
1932
1933 static void
1934 activate_callback (GList *files, gpointer callback_data)
1935 {
1936 ActivateParameters *parameters = callback_data;
1937 GList *l, *next;
1938 NautilusFile *file;
1939 LaunchLocation *location;
1940
1941 parameters->files_handle = NULL;
1942
1943 for (l = parameters->locations; l != NULL; l = next) {
1944 location = l->data;
1945 file = location->file;
1946 next = l->next;
1947
1948 if (file_was_cancelled (file)) {
1949 launch_location_free (location);
1950 parameters->locations = g_list_delete_link (parameters->locations, l);
1951 continue;
1952 }
1953
1954 if (file_was_not_mounted (file)) {
1955 if (parameters->tried_mounting) {
1956 launch_location_free (location);
1957 parameters->locations = g_list_delete_link (parameters->locations, l);
1958 } else {
1959 parameters->not_mounted = g_list_prepend (parameters->not_mounted,
1960 nautilus_file_ref (file));
1961 }
1962 continue;
1963 }
1964 }
1965
1966
1967 if (parameters->not_mounted != NULL) {
1968 activation_mount_not_mounted (parameters);
1969 } else {
1970 activate_files (parameters);
1971 }
1972 }
1973
1974 static void
1975 activate_activation_uris_ready_callback (GList *files_ignore,
1976 gpointer callback_data)
1977 {
1978 ActivateParameters *parameters = callback_data;
1979 GList *l, *next, *files;
1980 NautilusFile *file;
1981 LaunchLocation *location;
1982
1983 parameters->files_handle = NULL;
1984
1985 for (l = parameters->locations; l != NULL; l = next) {
1986 location = l->data;
1987 file = location->file;
1988 next = l->next;
1989
1990 if (file_was_cancelled (file)) {
1991 launch_location_free (location);
1992 parameters->locations = g_list_delete_link (parameters->locations, l);
1993 continue;
1994 }
1995
1996 if (nautilus_file_is_broken_symbolic_link (file)) {
1997 launch_location_free (location);
1998 parameters->locations = g_list_delete_link (parameters->locations, l);
1999 pause_activation_timed_cancel (parameters);
2000 report_broken_symbolic_link (parameters->parent_window, file);
2001 unpause_activation_timed_cancel (parameters);
2002 continue;
2003 }
2004
2005 if (nautilus_file_get_file_type (file) == G_FILE_TYPE_MOUNTABLE &&
2006 !nautilus_file_has_activation_uri (file)) {
2007 /* Don't launch these... There is nothing we
2008 can do */
2009 launch_location_free (location);
2010 parameters->locations = g_list_delete_link (parameters->locations, l);
2011 continue;
2012 }
2013
2014 }
2015
2016 if (parameters->locations == NULL) {
2017 activation_parameters_free (parameters);
2018 return;
2019 }
2020
2021 /* Convert the files to the actual activation uri files */
2022 for (l = parameters->locations; l != NULL; l = l->next) {
2023 char *uri = NULL;
2024
2025 location = l->data;
2026
2027 /* We want the file for the activation URI since we care
2028 * about the attributes for that, not for the original file.
2029 */
2030 if (nautilus_file_is_symbolic_link (location->file)) {
2031 uri = nautilus_file_get_symbolic_link_target_uri (location->file);
2032 }
2033
2034 if (uri == NULL) {
2035 uri = nautilus_file_get_activation_uri (location->file);
2036 }
2037
2038 if (uri != NULL) {
2039 launch_location_update_from_uri (location, uri);
2040 }
2041 g_free (uri);
2042 }
2043
2044
2045 /* get the parameters for the actual files */
2046 files = get_file_list_for_launch_locations (parameters->locations);
2047 nautilus_file_list_call_when_ready
2048 (files,
2049 nautilus_mime_actions_get_required_file_attributes () | NAUTILUS_FILE_ATTRIBUTE_LINK_INFO,
2050 ¶meters->files_handle,
2051 activate_callback, parameters);
2052 nautilus_file_list_free (files);
2053 }
2054
2055 static void
2056 activation_get_activation_uris (ActivateParameters *parameters)
2057 {
2058 GList *l, *files;
2059 NautilusFile *file;
2060 LaunchLocation *location;
2061
2062 /* link target info might be stale, re-read it */
2063 for (l = parameters->locations; l != NULL; l = l->next) {
2064 location = l->data;
2065 file = location->file;
2066
2067 if (file_was_cancelled (file)) {
2068 launch_location_free (location);
2069 parameters->locations = g_list_delete_link (parameters->locations, l);
2070 continue;
2071 }
2072 }
2073
2074 if (parameters->locations == NULL) {
2075 activation_parameters_free (parameters);
2076 return;
2077 }
2078
2079 files = get_file_list_for_launch_locations (parameters->locations);
2080 nautilus_file_list_call_when_ready
2081 (files,
2082 NAUTILUS_FILE_ATTRIBUTE_INFO |
2083 NAUTILUS_FILE_ATTRIBUTE_LINK_INFO,
2084 ¶meters->files_handle,
2085 activate_activation_uris_ready_callback, parameters);
2086 nautilus_file_list_free (files);
2087 }
2088
2089 static void
2090 activation_mountable_mounted (NautilusFile *file,
2091 GFile *result_location,
2092 GError *error,
2093 gpointer callback_data)
2094 {
2095 ActivateParameters *parameters = callback_data;
2096 NautilusFile *target_file;
2097 LaunchLocation *location;
2098
2099 /* Remove from list of files that have to be mounted */
2100 parameters->mountables = g_list_remove (parameters->mountables, file);
2101 nautilus_file_unref (file);
2102
2103
2104 if (error == NULL) {
2105 /* Replace file with the result of the mount */
2106 target_file = nautilus_file_get (result_location);
2107
2108 location = find_launch_location_for_file (parameters->locations,
2109 file);
2110 if (location) {
2111 launch_location_update_from_file (location, target_file);
2112 }
2113 nautilus_file_unref (target_file);
2114 } else {
2115 /* Remove failed file */
2116
2117 if (error->domain != G_IO_ERROR ||
2118 (error->code != G_IO_ERROR_FAILED_HANDLED &&
2119 error->code != G_IO_ERROR_ALREADY_MOUNTED)) {
2120 location = find_launch_location_for_file (parameters->locations,
2121 file);
2122 if (location) {
2123 parameters->locations =
2124 g_list_remove (parameters->locations,
2125 location);
2126 launch_location_free (location);
2127 }
2128 }
2129
2130 if (error->domain != G_IO_ERROR ||
2131 (error->code != G_IO_ERROR_CANCELLED &&
2132 error->code != G_IO_ERROR_FAILED_HANDLED &&
2133 error->code != G_IO_ERROR_ALREADY_MOUNTED)) {
2134 eel_show_error_dialog (_("Unable to access location"),
2135 error->message, parameters->parent_window);
2136 }
2137
2138 if (error->code == G_IO_ERROR_CANCELLED) {
2139 activation_parameters_free (parameters);
2140 return;
2141 }
2142 }
2143
2144 /* Mount more mountables */
2145 activation_mount_mountables (parameters);
2146 }
2147
2148
2149 static void
2150 activation_mount_mountables (ActivateParameters *parameters)
2151 {
2152 NautilusFile *file;
2153 GMountOperation *mount_op;
2154
2155 if (parameters->mountables != NULL) {
2156 file = parameters->mountables->data;
2157 mount_op = gtk_mount_operation_new (parameters->parent_window);
2158 g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION);
2159 g_signal_connect (mount_op, "notify::is-showing",
2160 G_CALLBACK (activate_mount_op_active), parameters);
2161 nautilus_file_mount (file,
2162 mount_op,
2163 parameters->cancellable,
2164 activation_mountable_mounted,
2165 parameters);
2166 g_object_unref (mount_op);
2167 return;
2168 }
2169
2170 if (parameters->mountables == NULL && parameters->start_mountables == NULL)
2171 activation_get_activation_uris (parameters);
2172 }
2173
2174
2175 static void
2176 activation_mountable_started (NautilusFile *file,
2177 GFile *gfile_of_file,
2178 GError *error,
2179 gpointer callback_data)
2180 {
2181 ActivateParameters *parameters = callback_data;
2182 LaunchLocation *location;
2183
2184 /* Remove from list of files that have to be mounted */
2185 parameters->start_mountables = g_list_remove (parameters->start_mountables, file);
2186 nautilus_file_unref (file);
2187
2188 if (error == NULL) {
2189 /* Remove file */
2190 location = find_launch_location_for_file (parameters->locations, file);
2191 if (location != NULL) {
2192 parameters->locations = g_list_remove (parameters->locations, location);
2193 launch_location_free (location);
2194 }
2195
2196 } else {
2197 /* Remove failed file */
2198 if (error->domain != G_IO_ERROR ||
2199 (error->code != G_IO_ERROR_FAILED_HANDLED)) {
2200 location = find_launch_location_for_file (parameters->locations,
2201 file);
2202 if (location) {
2203 parameters->locations =
2204 g_list_remove (parameters->locations,
2205 location);
2206 launch_location_free (location);
2207 }
2208 }
2209
2210 if (error->domain != G_IO_ERROR ||
2211 (error->code != G_IO_ERROR_CANCELLED &&
2212 error->code != G_IO_ERROR_FAILED_HANDLED)) {
2213 eel_show_error_dialog (_("Unable to start location"),
2214 error->message, NULL);
2215 }
2216
2217 if (error->code == G_IO_ERROR_CANCELLED) {
2218 activation_parameters_free (parameters);
2219 return;
2220 }
2221 }
2222
2223 /* Start more mountables */
2224 activation_start_mountables (parameters);
2225 }
2226
2227 static void
2228 activation_start_mountables (ActivateParameters *parameters)
2229 {
2230 NautilusFile *file;
2231 GMountOperation *start_op;
2232
2233 if (parameters->start_mountables != NULL) {
2234 file = parameters->start_mountables->data;
2235 start_op = gtk_mount_operation_new (parameters->parent_window);
2236 g_signal_connect (start_op, "notify::is-showing",
2237 G_CALLBACK (activate_mount_op_active), parameters);
2238 nautilus_file_start (file,
2239 start_op,
2240 parameters->cancellable,
2241 activation_mountable_started,
2242 parameters);
2243 g_object_unref (start_op);
2244 return;
2245 }
2246
2247 if (parameters->mountables == NULL && parameters->start_mountables == NULL)
2248 activation_get_activation_uris (parameters);
2249 }
2250
2251 /**
2252 * nautilus_mime_activate_files:
2253 *
2254 * Activate a list of files. Each one might launch with an application or
2255 * with a component. This is normally called only by subclasses.
2256 * @view: FMDirectoryView in question.
2257 * @files: A GList of NautilusFiles to activate.
2258 *
2259 **/
2260 void
2261 nautilus_mime_activate_files (GtkWindow *parent_window,
2262 NautilusWindowSlot *slot,
2263 GList *files,
2264 const char *launch_directory,
2265 NautilusWindowOpenFlags flags,
2266 gboolean user_confirmation)
2267 {
2268 ActivateParameters *parameters;
2269 char *file_name;
2270 int file_count;
2271 GList *l, *next;
2272 NautilusFile *file;
2273 LaunchLocation *location;
2274
2275 if (files == NULL) {
2276 return;
2277 }
2278
2279 DEBUG_FILES (files, "Calling activate_files() with files:");
2280
2281 parameters = g_new0 (ActivateParameters, 1);
2282 parameters->slot = slot;
2283 g_object_add_weak_pointer (G_OBJECT (parameters->slot), (gpointer *)¶meters->slot);
2284 if (parent_window) {
2285 parameters->parent_window = parent_window;
2286 g_object_add_weak_pointer (G_OBJECT (parameters->parent_window), (gpointer *)¶meters->parent_window);
2287 }
2288 parameters->cancellable = g_cancellable_new ();
2289 parameters->activation_directory = g_strdup (launch_directory);
2290 parameters->locations = launch_locations_from_file_list (files);
2291 parameters->flags = flags;
2292 parameters->user_confirmation = user_confirmation;
2293
2294 file_count = g_list_length (files);
2295 if (file_count == 1) {
2296 file_name = nautilus_file_get_display_name (files->data);
2297 parameters->timed_wait_prompt = g_strdup_printf (_("Opening ā%sā."), file_name);
2298 g_free (file_name);
2299 } else {
2300 parameters->timed_wait_prompt = g_strdup_printf (ngettext ("Opening %d item.",
2301 "Opening %d items.",
2302 file_count),
2303 file_count);
2304 }
2305
2306
2307 for (l = parameters->locations; l != NULL; l = next) {
2308 location = l->data;
2309 file = location->file;
2310 next = l->next;
2311
2312 if (nautilus_file_can_mount (file)) {
2313 parameters->mountables = g_list_prepend (parameters->mountables,
2314 nautilus_file_ref (file));
2315 }
2316
2317 if (nautilus_file_can_start (file)) {
2318 parameters->start_mountables = g_list_prepend (parameters->start_mountables,
2319 nautilus_file_ref (file));
2320 }
2321 }
2322
2323 activation_start_timed_cancel (parameters);
2324 if (parameters->mountables != NULL)
2325 activation_mount_mountables (parameters);
2326 if (parameters->start_mountables != NULL)
2327 activation_start_mountables (parameters);
2328 if (parameters->mountables == NULL && parameters->start_mountables == NULL)
2329 activation_get_activation_uris (parameters);
2330 }
2331
2332 /**
2333 * nautilus_mime_activate_file:
2334 *
2335 * Activate a file in this view. This might involve switching the displayed
2336 * location for the current window, or launching an application.
2337 * @view: FMDirectoryView in question.
2338 * @file: A NautilusFile representing the file in this view to activate.
2339 * @use_new_window: Should this item be opened in a new window?
2340 *
2341 **/
2342
2343 void
2344 nautilus_mime_activate_file (GtkWindow *parent_window,
2345 NautilusWindowSlot *slot,
2346 NautilusFile *file,
2347 const char *launch_directory,
2348 NautilusWindowOpenFlags flags)
2349 {
2350 GList *files;
2351
2352 g_return_if_fail (NAUTILUS_IS_FILE (file));
2353
2354 files = g_list_prepend (NULL, file);
2355 nautilus_mime_activate_files (parent_window, slot, files, launch_directory, flags, FALSE);
2356 g_list_free (files);
2357 }