1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3 /*
4 * Copyright (C) 2004 Roberto Majadas
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more av.
15 *
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA.
20 *
21 * Author: Roberto Majadas <roberto.majadas@openshine.com>
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <string.h>
29 #include <stdlib.h>
30 #include <glib.h>
31 #include <glib/gi18n.h>
32 #include <glib/gstdio.h>
33 #include <gtk/gtk.h>
34 #include "caja-sendto-plugin.h"
35
36 #define CAJA_SENDTO_LAST_MEDIUM "last-medium"
37 #define CAJA_SENDTO_LAST_COMPRESS "last-compress"
38 #define CAJA_SENDTO_STATUS_LABEL_TIMEOUT_SECONDS 10
39
40 #define UNINSTALLED_PLUGINDIR "plugins/removable-devices"
41
42 #define SOEXT ("." G_MODULE_SUFFIX)
43
44 enum {
45 COLUMN_ICON,
46 COLUMN_DESCRIPTION,
47 NUM_COLUMNS,
48 };
49
50 /* Options */
51 static char **filenames = NULL;
52
53 GList *file_list = NULL;
54 gboolean has_dirs = FALSE;
55 GList *plugin_list = NULL;
56 GHashTable *hash ;
57 guint option = 0;
58
59 static GSettings *settings = NULL;
60
61 typedef struct _NS_ui NS_ui;
62
63 struct _NS_ui {
64 GtkWidget *dialog;
65 GtkWidget *options_combobox;
66 GtkWidget *send_to_label;
67 GtkWidget *hbox_contacts_ws;
68 GtkWidget *cancel_button;
69 GtkWidget *send_button;
70 GtkWidget *pack_combobox;
71 GtkWidget *pack_checkbutton;
72 GtkWidget *pack_entry;
73 GList *contact_widgets;
74
75 GtkWidget *status_box;
76 GtkWidget *status_image;
77 GtkWidget *status_label;
78 guint status_timeoutid;
79 };
80
81 static const GOptionEntry entries[] = {
82 { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, "Files to send", "[FILES...]" },
83 { NULL }
84 };
85
86 static void
destroy_dialog(GtkWidget * widget,gpointer data)87 destroy_dialog (GtkWidget *widget, gpointer data )
88 {
89 gtk_main_quit ();
90 }
91
92 static char *
get_filename_from_list(void)93 get_filename_from_list (void)
94 {
95 GList *l;
96 GString *common_part = NULL;
97 gboolean matches = TRUE;
98 guint offset = 0;
99 const char *encoding;
100 gboolean use_utf8 = TRUE;
101
102 encoding = g_getenv ("G_FILENAME_ENCODING");
103
104 if (encoding != NULL && strcasecmp(encoding, "UTF-8") != 0)
105 use_utf8 = FALSE;
106
107 if (file_list == NULL)
108 return NULL;
109
110 common_part = g_string_new("");
111
112 while (TRUE) {
113 gunichar cur_char = '\0';
114 for (l = file_list; l ; l = l->next) {
115 char *path = NULL, *name = NULL;
116 char *offset_name = NULL;
117
118 path = g_filename_from_uri ((char *) l->data,
119 NULL, NULL);
120 if (!path)
121 break;
122
123 name = g_path_get_basename (path);
124
125 if (!use_utf8) {
126 char *tmp;
127
128 tmp = g_filename_to_utf8 (name, -1,
129 NULL, NULL, NULL);
130 g_free (name);
131 name = tmp;
132 }
133
134 if (!name) {
135 g_free (path);
136 break;
137 }
138
139 if (offset >= g_utf8_strlen (name, -1)) {
140 g_free(name);
141 g_free(path);
142 matches = FALSE;
143 break;
144 }
145
146 offset_name = g_utf8_offset_to_pointer (name, offset);
147
148 if (offset_name == g_utf8_strrchr (name, -1, '.')) {
149 g_free (name);
150 g_free (path);
151 matches = FALSE;
152 break;
153 }
154 if (cur_char == '\0') {
155 cur_char = g_utf8_get_char (offset_name);
156 } else if (cur_char != g_utf8_get_char (offset_name)) {
157 g_free (name);
158 g_free (path);
159 matches = FALSE;
160 break;
161 }
162 g_free (name);
163 g_free (path);
164 }
165 if (matches == TRUE && cur_char != '\0') {
166 offset++;
167 common_part = g_string_append_unichar (common_part,
168 cur_char);
169 } else {
170 break;
171 }
172 }
173
174 if (g_utf8_strlen (common_part->str, -1) < 4) {
175 g_string_free (common_part, TRUE);
176 return NULL;
177 }
178
179 return g_string_free (common_part, FALSE);
180 }
181
182 static char *
pack_files(NS_ui * ui)183 pack_files (NS_ui *ui)
184 {
185 char *engrampa_cmd;
186 const char *filename;
187 GList *l;
188 GString *cmd, *tmp;
189 char *pack_type, *tmp_dir, *tmp_work_dir, *packed_file;
190
191 engrampa_cmd = g_find_program_in_path ("engrampa");
192 filename = gtk_entry_get_text(GTK_ENTRY(ui->pack_entry));
193
194 g_assert (filename != NULL && *filename != '\0');
195
196 tmp_dir = g_strdup_printf ("%s/caja-sendto-%s",
197 g_get_tmp_dir(), g_get_user_name());
198 g_mkdir (tmp_dir, 0700);
199 tmp_work_dir = g_strdup_printf ("%s/caja-sendto-%s/%li",
200 g_get_tmp_dir(), g_get_user_name(),
201 time(NULL));
202 g_mkdir (tmp_work_dir, 0700);
203 g_free (tmp_dir);
204
205 if (gtk_combo_box_get_active (GTK_COMBO_BOX(ui->pack_combobox)) != 0) {
206 pack_type = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT(ui->pack_combobox));
207 } else {
208 pack_type = NULL;
209 g_assert_not_reached ();
210 }
211
212 g_settings_set_int (settings,
213 CAJA_SENDTO_LAST_COMPRESS,
214 gtk_combo_box_get_active(GTK_COMBO_BOX(ui->pack_combobox)));
215
216 cmd = g_string_new ("");
217 g_string_printf (cmd, "%s --add-to=\"%s/%s%s\"",
218 engrampa_cmd, tmp_work_dir,
219 filename,
220 pack_type);
221 g_free (engrampa_cmd);
222
223 /* engrampa doesn't understand URIs */
224 for (l = file_list ; l; l=l->next){
225 char *file;
226
227 file = g_filename_from_uri (l->data, NULL, NULL);
228 g_string_append_printf (cmd," \"%s\"", file);
229 g_free (file);
230 }
231
232 g_spawn_command_line_sync (cmd->str, NULL, NULL, NULL, NULL);
233 g_string_free (cmd, TRUE);
234 tmp = g_string_new("");
235 g_string_printf (tmp,"%s/%s%s", tmp_work_dir,
236 filename,
237 pack_type);
238 g_free (pack_type);
239 g_free (tmp_work_dir);
240 packed_file = g_filename_to_uri (tmp->str, NULL, NULL);
241 g_string_free(tmp, TRUE);
242 return packed_file;
243 }
244
245 static gboolean
status_label_clear(gpointer data)246 status_label_clear (gpointer data)
247 {
248 NS_ui *ui = (NS_ui *) data;
249 gtk_label_set_label (GTK_LABEL (ui->status_label), "");
250 gtk_widget_hide (ui->status_image);
251
252 ui->status_timeoutid = 0;
253
254 return FALSE;
255 }
256
257 static void
send_button_cb(GtkWidget * widget,NS_ui * ui)258 send_button_cb (GtkWidget *widget, NS_ui *ui)
259 {
260 char *error;
261 NstPlugin *p;
262 GtkWidget *w;
263
264 gtk_widget_set_sensitive (ui->dialog, FALSE);
265
266 p = (NstPlugin *) g_list_nth_data (plugin_list, option);
267 w = (GtkWidget *) g_list_nth_data (ui->contact_widgets, option);
268
269 if (ui->status_timeoutid != 0) {
270 g_source_remove (ui->status_timeoutid);
271 status_label_clear (ui);
272 }
273
274 if (p == NULL)
275 return;
276
277 if (p->info->validate_destination != NULL) {
278 error = NULL;
279 if (p->info->validate_destination (p, w, &error) == FALSE) {
280 char *message;
281
282 message = g_strdup_printf ("<b>%s</b>", error);
283 g_free (error);
284 gtk_label_set_markup (GTK_LABEL (ui->status_label), message);
285 g_free (message);
286 ui->status_timeoutid = g_timeout_add_seconds (CAJA_SENDTO_STATUS_LABEL_TIMEOUT_SECONDS,
287 status_label_clear,
288 ui);
289 gtk_widget_show (ui->status_image);
290 gtk_widget_show (ui->status_box);
291 gtk_widget_set_sensitive (ui->dialog, TRUE);
292 return;
293 }
294 }
295
296 g_settings_set_string (settings,
297 CAJA_SENDTO_LAST_MEDIUM,
298 p->info->id);
299
300 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ui->pack_checkbutton))){
301 char *f;
302
303 f = pack_files (ui);
304 if (f != NULL) {
305 GList *packed_file = NULL;
306 packed_file = g_list_append (packed_file, f);
307 if (!p->info->send_files (p, w, packed_file)) {
308 g_free (f);
309 g_list_free (packed_file);
310 return;
311 }
312 g_list_free (packed_file);
313 } else {
314 gtk_widget_set_sensitive (ui->dialog, TRUE);
315 return;
316 }
317 g_free (f);
318 } else {
319 if (!p->info->send_files (p, w, file_list)) {
320 g_list_free_full (file_list, g_free);
321 file_list = NULL;
322 return;
323 }
324 g_list_free (file_list);
325 file_list = NULL;
326 }
327 destroy_dialog (NULL,NULL);
328 }
329
330 static void
send_if_no_pack_cb(GtkWidget * widget,NS_ui * ui)331 send_if_no_pack_cb (GtkWidget *widget, NS_ui *ui)
332 {
333 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ui->pack_checkbutton))) {
334 if (gtk_widget_is_sensitive (ui->pack_entry)) {
335 gtk_widget_grab_focus (ui->pack_entry);
336 } else {
337 gtk_widget_grab_focus (ui->pack_checkbutton);
338 }
339 } else {
340 send_button_cb (widget, ui);
341 }
342 }
343
344 static void
toggle_pack_check(GtkWidget * widget,NS_ui * ui)345 toggle_pack_check (GtkWidget *widget, NS_ui *ui)
346 {
347 GtkToggleButton *t = GTK_TOGGLE_BUTTON (widget);
348 gboolean enabled, send_enabled;
349
350 enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (t));
351 gtk_widget_set_sensitive (ui->pack_combobox, enabled);
352 gtk_widget_set_sensitive (ui->pack_entry, enabled);
353
354 send_enabled = TRUE;
355
356 if (enabled) {
357 const char *filename;
358
359 filename = gtk_entry_get_text(GTK_ENTRY(ui->pack_entry));
360 if (filename == NULL || *filename == '\0')
361 send_enabled = FALSE;
362 }
363
364 gtk_widget_set_sensitive (ui->send_button, send_enabled);
365 }
366
367 static void
option_changed(GtkComboBox * cb,NS_ui * ui)368 option_changed (GtkComboBox *cb, NS_ui *ui)
369 {
370 GtkWidget *w;
371 NstPlugin *p;
372 gboolean supports_dirs = FALSE;
373
374 w = g_list_nth_data (ui->contact_widgets, option);
375 option = gtk_combo_box_get_active (GTK_COMBO_BOX(cb));
376 gtk_widget_hide (w);
377 w = g_list_nth_data (ui->contact_widgets, option);
378 gtk_widget_show (w);
379
380 gtk_label_set_mnemonic_widget (GTK_LABEL (ui->send_to_label), w);
381
382 p = (NstPlugin *) g_list_nth_data (plugin_list, option);
383 supports_dirs = (p->info->capabilities & CAJA_CAPS_SEND_DIRECTORIES);
384
385 if (has_dirs == FALSE || supports_dirs != FALSE) {
386 gboolean toggle;
387
388 toggle = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ui->pack_checkbutton));
389 gtk_widget_set_sensitive (ui->pack_combobox, toggle);
390 gtk_widget_set_sensitive (ui->pack_entry, toggle);
391 gtk_widget_set_sensitive (ui->pack_checkbutton, TRUE);
392 } else {
393 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ui->pack_checkbutton), TRUE);
394 gtk_widget_set_sensitive (ui->pack_checkbutton, FALSE);
395 }
396 }
397
398 static void
set_contact_widgets(NS_ui * ui)399 set_contact_widgets (NS_ui *ui)
400 {
401 GList *aux ;
402 GtkWidget *w;
403 NstPlugin *p;
404
405 ui->contact_widgets = NULL;
406
407 for (aux = plugin_list; aux; aux = aux->next){
408 p = (NstPlugin *) aux->data;
409 w = p->info->get_contacts_widget(p);
410 gtk_box_pack_end (GTK_BOX(ui->hbox_contacts_ws),w, TRUE, TRUE, 0);
411 gtk_widget_hide (GTK_WIDGET(w));
412 ui->contact_widgets = g_list_append (ui->contact_widgets, w);
413 if (GTK_IS_ENTRY (w)) {
414 g_signal_connect_after (G_OBJECT (w), "activate",
415 G_CALLBACK (send_if_no_pack_cb), ui);
416 }
417 }
418 }
419
420 static gboolean
set_model_for_options_combobox(NS_ui * ui)421 set_model_for_options_combobox (NS_ui *ui)
422 {
423 GdkPixbuf *pixbuf;
424 GtkTreeIter iter;
425 GtkListStore *model;
426 GtkIconTheme *it;
427 GtkCellRenderer *renderer;
428 GtkWidget *widget;
429 GList *aux;
430 NstPlugin *p;
431 char *last_used = NULL;
432 int i = 0;
433 gboolean last_used_support_dirs = FALSE;
434
435 it = gtk_icon_theme_get_default ();
436
437 model = gtk_list_store_new (NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING);
438
439 last_used = g_settings_get_string (settings,
440 CAJA_SENDTO_LAST_MEDIUM);
441
442 for (aux = plugin_list; aux; aux = aux->next) {
443 p = (NstPlugin *) aux->data;
444 pixbuf = gtk_icon_theme_load_icon (it, p->info->icon, 16,
445 GTK_ICON_LOOKUP_USE_BUILTIN, NULL);
446 gtk_list_store_append (model, &iter);
447 gtk_list_store_set (model, &iter,
448 COLUMN_ICON, pixbuf,
449 #ifdef ENABLE_NLS
450 COLUMN_DESCRIPTION, g_dgettext (p->info->gettext_package, p->info->description),
451 #else
452 COLUMN_DESCRIPTION, p->info->description,
453 #endif /* ENABLE_NLS */
454 -1);
455 if (last_used != NULL && !strcmp(last_used, p->info->id)) {
456 option = i;
457 last_used_support_dirs = (p->info->capabilities & CAJA_CAPS_SEND_DIRECTORIES);
458 }
459 i++;
460 }
461 g_free(last_used);
462
463 gtk_combo_box_set_model (GTK_COMBO_BOX(ui->options_combobox),
464 GTK_TREE_MODEL (model));
465 renderer = gtk_cell_renderer_pixbuf_new ();
466 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (ui->options_combobox),
467 renderer,
468 FALSE);
469 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (ui->options_combobox),
470 renderer,
471 "pixbuf", COLUMN_ICON,
472 NULL);
473 renderer = gtk_cell_renderer_text_new ();
474 g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
475 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (ui->options_combobox),
476 renderer,
477 TRUE);
478 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (ui->options_combobox),
479 renderer,
480 "text", COLUMN_DESCRIPTION,
481 NULL);
482
483 g_signal_connect (G_OBJECT (ui->options_combobox), "changed",
484 G_CALLBACK (option_changed), ui);
485
486 gtk_combo_box_set_active (GTK_COMBO_BOX (ui->options_combobox), option);
487
488 /* Grab the focus for the most recently used widget */
489 widget = g_list_nth_data (ui->contact_widgets, option);
490 gtk_widget_grab_focus (widget);
491
492 return last_used_support_dirs;
493 }
494
495 static void
pack_entry_changed_cb(GObject * object,GParamSpec * spec,NS_ui * ui)496 pack_entry_changed_cb (GObject *object, GParamSpec *spec, NS_ui *ui)
497 {
498 gboolean send_enabled;
499
500 send_enabled = TRUE;
501
502 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ui->pack_checkbutton))) {
503 const char *filename;
504
505 filename = gtk_entry_get_text(GTK_ENTRY(ui->pack_entry));
506 if (filename == NULL || *filename == '\0')
507 send_enabled = FALSE;
508 }
509
510 gtk_widget_set_sensitive (ui->send_button, send_enabled);
511 }
512
513 static void
update_button_image(GtkSettings * gtk_settings,GParamSpec * spec,GtkWidget * widget)514 update_button_image (GtkSettings *gtk_settings,
515 GParamSpec *spec,
516 GtkWidget *widget)
517 {
518 gboolean show_images;
519
520 g_object_get (gtk_settings, "gtk-button-images", &show_images, NULL);
521 if (show_images == FALSE)
522 gtk_widget_hide (widget);
523 else
524 gtk_widget_show (widget);
525 }
526
527 static void
caja_sendto_create_ui(void)528 caja_sendto_create_ui (void)
529 {
530 GtkBuilder *builder;
531 GError* error = NULL;
532 NS_ui *ui;
533 gboolean one_file = FALSE;
534 gboolean supports_dirs;
535 GtkSettings *gtk_settings;
536 GtkWidget *button_image;
537
538 builder = gtk_builder_new ();
539 if (gtk_builder_add_from_resource (builder, "/org/mate/caja/extensions/sendto/caja-sendto.ui", &error) == 0) {
540 g_warning ("Could not parse UI definition: %s", error->message);
541 g_error_free (error);
542 }
543
544 ui = g_new0 (NS_ui, 1);
545
546 ui->hbox_contacts_ws = GTK_WIDGET (gtk_builder_get_object (builder, "hbox_contacts_widgets"));
547 ui->send_to_label = GTK_WIDGET (gtk_builder_get_object (builder, "send_to_label"));
548 ui->options_combobox = GTK_WIDGET (gtk_builder_get_object (builder, "options_combobox"));
549 ui->dialog = GTK_WIDGET (gtk_builder_get_object (builder, "caja_sendto_dialog"));
550 ui->cancel_button = GTK_WIDGET (gtk_builder_get_object (builder, "cancel_button"));
551 ui->send_button = GTK_WIDGET (gtk_builder_get_object (builder, "send_button"));
552 ui->pack_combobox = GTK_WIDGET (gtk_builder_get_object (builder, "pack_combobox"));
553 ui->pack_entry = GTK_WIDGET (gtk_builder_get_object (builder, "pack_entry"));
554 ui->pack_checkbutton = GTK_WIDGET (gtk_builder_get_object (builder, "pack_checkbutton"));
555 ui->status_box = GTK_WIDGET (gtk_builder_get_object (builder, "status_box"));
556 ui->status_label = GTK_WIDGET (gtk_builder_get_object (builder, "status_label"));
557 ui->status_image = GTK_WIDGET (gtk_builder_get_object (builder, "status_image"));
558
559 gtk_settings = gtk_settings_get_default ();
560 button_image = GTK_WIDGET (gtk_builder_get_object (builder, "image1"));
561 g_signal_connect (G_OBJECT (gtk_settings), "notify::gtk-button-images",
562 G_CALLBACK (update_button_image), button_image);
563 update_button_image (gtk_settings, NULL, button_image);
564
565 gtk_combo_box_set_active (GTK_COMBO_BOX(ui->pack_combobox),
566 g_settings_get_int (settings,
567 CAJA_SENDTO_LAST_COMPRESS));
568
569 if (file_list != NULL && file_list->next != NULL)
570 one_file = FALSE;
571 else if (file_list != NULL)
572 one_file = TRUE;
573
574 gtk_entry_set_text (GTK_ENTRY (ui->pack_entry), _("Files"));
575
576 if (one_file) {
577 char *filepath = NULL, *filename = NULL;
578
579 filepath = g_filename_from_uri ((char *)file_list->data,
580 NULL, NULL);
581
582 if (filepath != NULL)
583 filename = g_path_get_basename (filepath);
584 if (filename != NULL && filename[0] != '\0')
585 gtk_entry_set_text (GTK_ENTRY (ui->pack_entry), filename);
586
587 g_free (filename);
588 g_free (filepath);
589 } else {
590 char *filename = get_filename_from_list ();
591 if (filename != NULL && filename[0] != '\0') {
592 gtk_entry_set_text (GTK_ENTRY (ui->pack_entry),
593 filename);
594 }
595 g_free (filename);
596 }
597
598 set_contact_widgets (ui);
599 supports_dirs = set_model_for_options_combobox (ui);
600 g_signal_connect (G_OBJECT (ui->dialog), "destroy",
601 G_CALLBACK (destroy_dialog), NULL);
602 g_signal_connect (G_OBJECT (ui->cancel_button), "clicked",
603 G_CALLBACK (destroy_dialog), NULL);
604 g_signal_connect (G_OBJECT (ui->send_button), "clicked",
605 G_CALLBACK (send_button_cb), ui);
606 g_signal_connect (G_OBJECT (ui->pack_entry), "activate",
607 G_CALLBACK (send_button_cb), ui);
608 g_signal_connect (G_OBJECT (ui->pack_entry), "notify::text",
609 G_CALLBACK (pack_entry_changed_cb), ui);
610 g_signal_connect (G_OBJECT (ui->pack_checkbutton), "toggled",
611 G_CALLBACK (toggle_pack_check), ui);
612
613 g_object_unref (builder);
614
615 if (has_dirs == FALSE || supports_dirs != FALSE) {
616 gboolean toggle;
617
618 toggle = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ui->pack_checkbutton));
619 gtk_widget_set_sensitive (ui->pack_combobox, toggle);
620 gtk_widget_set_sensitive (ui->pack_entry, toggle);
621 } else {
622 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ui->pack_checkbutton), TRUE);
623 gtk_widget_set_sensitive (ui->pack_checkbutton, FALSE);
624 }
625
626 gtk_widget_show (ui->dialog);
627
628 }
629
630 static void
caja_sendto_plugin_dir_process(const char * plugindir)631 caja_sendto_plugin_dir_process (const char *plugindir)
632 {
633 GDir *dir;
634 const char *item;
635 NstPlugin *p = NULL;
636 gboolean (*nst_init_plugin)(NstPlugin *p);
637 GError *err = NULL;
638
639 dir = g_dir_open (plugindir, 0, &err);
640
641 if (dir == NULL) {
642 g_warning ("Can't open the plugins dir: %s", err ? err->message : "No reason");
643 if (err)
644 g_error_free (err);
645 } else {
646 while ((item = g_dir_read_name(dir))) {
647 if (g_str_has_suffix (item, SOEXT)) {
648 g_autofree gchar *module_path = NULL;
649
650 p = g_new0(NstPlugin, 1);
651
652 module_path = g_module_build_path (plugindir, item);
653 if (!module_path) {
654 g_free (p);
655 continue;
656 }
657
658 p->module = g_module_open (module_path, 0);
659 if (!p->module) {
660 g_warning ("error opening %s: %s", module_path, g_module_error ());
661 g_free (p);
662 continue;
663 }
664
665 if (!g_module_symbol (p->module, "nst_init_plugin", (gpointer *) &nst_init_plugin)) {
666 g_warning ("error: %s", g_module_error ());
667 g_module_close (p->module);
668 g_free (p);
669 continue;
670 }
671
672 nst_init_plugin (p);
673 if (p->info->init(p)) {
674 plugin_list = g_list_append (plugin_list, p);
675 } else {
676 g_free (p);
677 }
678 }
679 }
680 g_dir_close (dir);
681 }
682 }
683
684 static gboolean
caja_sendto_plugin_init(void)685 caja_sendto_plugin_init (void)
686 {
687 if (g_file_test (UNINSTALLED_PLUGINDIR, G_FILE_TEST_IS_DIR) != FALSE) {
688 /* Try to load the local plugins */
689 GError *err = NULL;
690 GDir *dir;
691 const char *item;
692
693 dir = g_dir_open ("plugins/", 0, &err);
694 if (dir == NULL) {
695 g_warning ("Can't open the plugins dir: %s", err ? err->message : "No reason");
696 if (err)
697 g_error_free (err);
698 return FALSE;
699 }
700 while ((item = g_dir_read_name(dir))) {
701 char *plugindir;
702
703 plugindir = g_strdup_printf ("plugins/%s/.libs/", item);
704 if (g_file_test (plugindir, G_FILE_TEST_IS_DIR) != FALSE)
705 caja_sendto_plugin_dir_process (plugindir);
706 g_free (plugindir);
707 }
708 g_dir_close (dir);
709 }
710
711 if (g_list_length (plugin_list) == 0)
712 caja_sendto_plugin_dir_process (PLUGINDIR);
713
714 return g_list_length (plugin_list) != 0;
715 }
716
717 static char *
escape_ampersands_and_commas(const char * url)718 escape_ampersands_and_commas (const char *url)
719 {
720 int i;
721 char *str, *ptr;
722
723 /* Count the number of ampersands & commas */
724 i = 0;
725 ptr = (char *) url;
726 while ((ptr = strchr (ptr, '&')) != NULL) {
727 i++;
728 ptr++;
729 }
730 ptr = (char *) url;
731 while ((ptr = strchr (ptr, ',')) != NULL) {
732 i++;
733 ptr++;
734 }
735
736 /* No ampersands or commas ? */
737 if (i == 0)
738 return NULL;
739
740 /* Replace the '&' */
741 str = g_malloc0 (strlen (url) - i + 3 * i + 1);
742 ptr = str;
743 for (i = 0; url[i] != '\0'; i++) {
744 if (url[i] == '&') {
745 *ptr++ = '%';
746 *ptr++ = '2';
747 *ptr++ = '6';
748 } else if (url[i] == ',') {
749 *ptr++ = '%';
750 *ptr++ = '2';
751 *ptr++ = 'C';
752 } else {
753 *ptr++ = url[i];
754 }
755 }
756
757 return str;
758 }
759
760 static void
caja_sendto_init(void)761 caja_sendto_init (void)
762 {
763 int i;
764
765 if (g_module_supported() == FALSE)
766 g_error ("Could not initialize gmodule support");
767
768 for (i = 0; filenames != NULL && filenames[i] != NULL; i++) {
769 GFile *file;
770 char *filename, *escaped, *uri;
771
772 file = g_file_new_for_commandline_arg (filenames[i]);
773 filename = g_file_get_path (file);
774 g_object_unref (file);
775 if (filename == NULL)
776 continue;
777
778 if (g_file_test (filename, G_FILE_TEST_IS_DIR) != FALSE)
779 has_dirs = TRUE;
780
781 uri = g_filename_to_uri (filename, NULL, NULL);
782 g_free (filename);
783 escaped = escape_ampersands_and_commas (uri);
784
785 if (escaped == NULL) {
786 file_list = g_list_prepend (file_list, uri);
787 } else {
788 file_list = g_list_prepend (file_list, escaped);
789 g_free (uri);
790 }
791 }
792
793 if (file_list == NULL) {
794 g_print (_("Expects URIs or filenames to be passed as options\n"));
795 exit (1);
796 }
797
798 file_list = g_list_reverse (file_list);
799 }
800
main(int argc,char ** argv)801 int main (int argc, char **argv)
802 {
803 GOptionContext *context;
804 GError *error = NULL;
805
806 #ifdef ENABLE_NLS
807 bindtextdomain (GETTEXT_PACKAGE, MATELOCALEDIR);
808 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
809 textdomain (GETTEXT_PACKAGE);
810 #endif /* ENABLE_NLS */
811
812 context = g_option_context_new ("");
813 g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
814 g_option_context_add_group (context, gtk_get_option_group (TRUE));
815 if (g_option_context_parse (context, &argc, &argv, &error) == FALSE) {
816 g_print (_("Could not parse command-line options: %s\n"), error->message);
817 g_error_free (error);
818 return 1;
819 }
820
821 settings = g_settings_new ("org.mate.Caja.Sendto");
822 caja_sendto_init ();
823 if (caja_sendto_plugin_init () == FALSE) {
824 GtkWidget *error_dialog;
825
826 error_dialog =
827 gtk_message_dialog_new (NULL,
828 GTK_DIALOG_MODAL,
829 GTK_MESSAGE_ERROR,
830 GTK_BUTTONS_OK,
831 _("Could not load any plugins."));
832 gtk_message_dialog_format_secondary_text
833 (GTK_MESSAGE_DIALOG (error_dialog),
834 _("Please verify your installation"));
835
836 gtk_window_set_title (GTK_WINDOW (error_dialog), ""); /* as per HIG */
837 gtk_container_set_border_width (GTK_CONTAINER (error_dialog), 5);
838 gtk_dialog_set_default_response (GTK_DIALOG (error_dialog),
839 GTK_RESPONSE_OK);
840 gtk_dialog_run (GTK_DIALOG (error_dialog));
841 return 1;
842 }
843 caja_sendto_create_ui ();
844
845 gtk_main ();
846 g_object_unref(settings);
847
848 return 0;
849 }
850
851