2008-05-05 Paolo Borelli <pborelli@katamail.com>
[nautilus.git] / src / nautilus-autorun-software.c
blob63616e3a98dc1d2a183e4eac76054f4b30a55be1
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
3 /* Nautilus
5 Copyright (C) 2008 Red Hat, Inc.
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.
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.
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.
22 Author: David Zeuthen <davidz@redhat.com>
26 #include <config.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <time.h>
31 #include <gtk/gtk.h>
32 #include <gio/gio.h>
34 #include <glib/gi18n.h>
36 #include <libgnome/gnome-program.h>
37 #include <libgnomeui/gnome-ui-init.h>
38 #include <libnautilus-private/nautilus-module.h>
39 #include <libnautilus-private/nautilus-icon-info.h>
41 typedef struct
43 GtkWidget *dialog;
44 GMount *mount;
45 } AutorunSoftwareDialogData;
47 static void autorun_software_dialog_mount_unmounted (GMount *mount, AutorunSoftwareDialogData *data);
49 static void
50 autorun_software_dialog_destroy (AutorunSoftwareDialogData *data)
52 g_signal_handlers_disconnect_by_func (G_OBJECT (data->mount),
53 G_CALLBACK (autorun_software_dialog_mount_unmounted),
54 data);
56 gtk_widget_destroy (GTK_WIDGET (data->dialog));
57 g_object_unref (data->mount);
58 g_free (data);
61 static void
62 autorun_software_dialog_mount_unmounted (GMount *mount, AutorunSoftwareDialogData *data)
64 autorun_software_dialog_destroy (data);
67 static gboolean
68 _check_file (GFile *mount_root, const char *file_path, gboolean must_be_executable)
70 GFile *file;
71 GFileInfo *file_info;
72 gboolean ret;
74 ret = FALSE;
76 file = g_file_get_child (mount_root, file_path);
77 file_info = g_file_query_info (file,
78 G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE,
79 G_FILE_QUERY_INFO_NONE,
80 NULL,
81 NULL);
82 if (file_info != NULL) {
83 if (must_be_executable) {
84 if (g_file_info_get_attribute_boolean (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE)) {
85 ret = TRUE;
87 } else {
88 ret = TRUE;
90 g_object_unref (file_info);
92 g_object_unref (file);
94 return ret;
97 static void
98 autorun (GMount *mount)
100 char *error_string;
101 GFile *root;
102 GFile *program_to_spawn;
103 char *path_to_spawn;
104 char *cwd_for_program;
106 root = g_mount_get_root (mount);
108 /* Careful here, according to
110 * http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html
112 * the ordering does matter.
115 program_to_spawn = NULL;
116 path_to_spawn = NULL;
118 if (_check_file (root, ".autorun", TRUE)) {
119 program_to_spawn = g_file_get_child (root, ".autorun");
120 } else if (_check_file (root, "autorun", TRUE)) {
121 program_to_spawn = g_file_get_child (root, "autorun");
122 } else if (_check_file (root, "autorun.sh", TRUE)) {
123 program_to_spawn = g_file_get_child (root, "autorun.sh");
124 } else if (_check_file (root, "autorun.exe", TRUE)) {
125 /* TODO */
126 } else if (_check_file (root, "AUTORUN.EXE", TRUE)) {
127 /* TODO */
128 } else if (_check_file (root, "autorun.inf", FALSE)) {
129 /* TODO */
130 } else if (_check_file (root, "AUTORUN.INF", FALSE)) {
131 /* TODO */
134 if (program_to_spawn != NULL) {
135 path_to_spawn = g_file_get_path (program_to_spawn);
138 cwd_for_program = g_file_get_path (root);
140 error_string = NULL;
141 if (path_to_spawn != NULL && cwd_for_program != NULL) {
142 if (chdir (cwd_for_program) == 0) {
143 execl (path_to_spawn, path_to_spawn, NULL);
144 error_string = g_strdup_printf (_("Error starting autorun program: %s"), strerror (errno));
145 goto out;
147 error_string = g_strdup_printf (_("Error starting autorun program: %s"), strerror (errno));
148 goto out;
150 error_string = g_strdup_printf (_("Cannot find the autorun program"));
152 out:
153 if (program_to_spawn != NULL) {
154 g_object_unref (program_to_spawn);
156 if (root != NULL) {
157 g_object_unref (root);
159 g_free (path_to_spawn);
160 g_free (cwd_for_program);
162 if (error_string != NULL) {
163 GtkWidget *dialog;
164 dialog = gtk_message_dialog_new_with_markup (NULL, /* TODO: parent window? */
166 GTK_MESSAGE_ERROR,
167 GTK_BUTTONS_OK,
168 _("<big><b>Error autorunning software</b></big>"));
169 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), error_string);
170 gtk_dialog_run (GTK_DIALOG (dialog));
171 gtk_widget_destroy (dialog);
172 g_free (error_string);
176 static void
177 present_autorun_for_software_dialog (GMount *mount)
179 GIcon *icon;
180 int icon_size;
181 NautilusIconInfo *icon_info;
182 GdkPixbuf *pixbuf;
183 GtkWidget *image;
184 char *mount_name;
185 GtkWidget *dialog;
186 AutorunSoftwareDialogData *data;
188 mount_name = g_mount_get_name (mount);
190 dialog = gtk_message_dialog_new_with_markup (NULL, /* TODO: parent window? */
192 GTK_MESSAGE_OTHER,
193 GTK_BUTTONS_CANCEL,
194 _("<big><b>This media contains software intended to be automatically started. Would you like to run it?</b></big>"));
195 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
196 _("The software will run directly from the media \"%s\". "
197 "You should never run software that you don't trust.\n"
198 "\n"
199 "If in doubt, press Cancel."),
200 mount_name);
202 /* TODO: in a star trek future add support for verifying
203 * software on media (e.g. if it has a certificate, check it
204 * etc.)
208 icon = g_mount_get_icon (mount);
209 icon_size = nautilus_get_icon_size_for_stock_size (GTK_ICON_SIZE_DIALOG);
210 icon_info = nautilus_icon_info_lookup (icon, icon_size);
211 pixbuf = nautilus_icon_info_get_pixbuf_at_size (icon_info, icon_size);
212 image = gtk_image_new_from_pixbuf (pixbuf);
213 gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
215 gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), image);
217 gtk_window_set_title (GTK_WINDOW (dialog), mount_name);
218 gtk_window_set_icon (GTK_WINDOW (dialog), pixbuf);
220 data = g_new0 (AutorunSoftwareDialogData, 1);
221 data->dialog = dialog;
222 data->mount = g_object_ref (mount);
224 g_signal_connect (G_OBJECT (mount),
225 "unmounted",
226 G_CALLBACK (autorun_software_dialog_mount_unmounted),
227 data);
229 gtk_dialog_add_button (GTK_DIALOG (dialog),
230 _("_Run"),
231 GTK_RESPONSE_OK);
233 gtk_widget_show_all (dialog);
235 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
236 gtk_widget_destroy (dialog);
237 autorun (mount);
240 g_object_unref (icon_info);
241 g_object_unref (pixbuf);
242 g_free (mount_name);
246 main (int argc, char *argv[])
248 GVolumeMonitor *monitor;
249 GFile *file;
250 GMount *mount;
252 bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
253 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
254 textdomain (GETTEXT_PACKAGE);
256 gnome_program_init ("nautilus-autorun-software", VERSION,
257 LIBGNOMEUI_MODULE, argc, argv,
258 NULL, NULL);
260 if (argc != 2) {
261 goto out;
264 /* instantiate monitor so we get the "unmounted" signal properly */
265 monitor = g_volume_monitor_get ();
266 if (monitor == NULL) {
267 goto out;
270 file = g_file_new_for_commandline_arg (argv[1]);
271 if (file == NULL) {
272 g_object_unref (monitor);
273 goto out;
276 mount = g_file_find_enclosing_mount (file, NULL, NULL);
277 if (mount == NULL) {
278 g_object_unref (file);
279 g_object_unref (monitor);
280 goto out;
283 present_autorun_for_software_dialog (mount);
284 g_object_unref (file);
285 g_object_unref (monitor);
286 g_object_unref (mount);
288 out:
289 return 0;