1 /*
2 * Edscott Wilson Garcia Copyright 2012
3 *
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program;
17 */
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21 #include "rodent.h"
22 #include "rfm_modules.h"
23 #include "fuse-group_options.h"
24 #include "fuse-common.h"
25
26 #define POPUP_ID "fuse_menu"
27 #define POPUP_MENU_ID "fuse_menu_menu"
28
29
30 #define FLAG_KEY(x) g_strdup_printf("FLAG_%d", x)
31 #define FUSE_MENU_STUFF \
32 {MENUITEM_TYPE,POPUP_MENU_ID,"fuse_new_tab",\
33 {0x2001, N_("Open in New Tab"),"xffm/stock_directory", \
34 (gpointer) new_tab_open, NULL}},\
35 {MENUITEM_TYPE,POPUP_MENU_ID,"fuse_new_window",\
36 {0x2002, N_("Open in New Window"),"rodent", \
37 (gpointer) new_window_open, NULL}},\
38 {MENUITEM_TYPE,POPUP_MENU_ID,"fuse_properties",\
39 {0x2003, N_("Properties"),"xffm/stock_properties", \
40 (gpointer) variable_call, NULL}},\
41 {MENUITEM_TYPE,POPUP_MENU_ID,"fuse_mount",\
42 {0x2004, N_("Mount"),"xffm/emblem_greenball", \
43 (gpointer) variable_call, NULL}},\
44 {MENUITEM_TYPE,POPUP_MENU_ID,"fuse_unmount",\
45 {0x2005, N_("Unmount"),"xffm/emblem_redball", \
46 (gpointer) variable_call, NULL}},\
47 {MENUITEM_TYPE,POPUP_MENU_ID,"fuse_broken_mount",\
48 {0x2006, N_("There was a network error."),"xffm/emblem_unreadable", \
49 (gpointer) NULL, NULL}},\
50 {MENUITEM_TYPE,POPUP_MENU_ID,"fuse_delete",\
51 {0x2007, N_("Delete"),"xffm/stock_delete", \
52 (gpointer) remove_host, NULL}},\
53 {NULL_TYPE}
54
55
56 static gboolean
57 confirm_host (fuse_data_t *(*dialog_f)(const gchar *url), const gchar *url, const gchar *module_name);
58
59 static
60 void *
submodule_up_item(void * p)61 submodule_up_item(void *p){
62 xfdir_t *xfdir_p = p;
63 xfdir_p->gl[0].en=rfm_mk_entry(0);
64 xfdir_p->gl[0].en->st = NULL;
65 // xfdir_p->gl[0].en->parent_module = MODULE_NAME;
66 xfdir_p->gl[0].en->module = "fuse";
67 gchar *g = rfm_void(PLUGIN_DIR, "fuse", "module_label");
68 if (!g) g=g_strdup_printf("FIXME: no module label for \"%s\"", "fuse");
69 xfdir_p->gl[0].en->path=g;
70 xfdir_p->gl[0].pathv = g_strdup(g);
71 SET_ROOT_TYPE(xfdir_p->gl[0].en->type);
72 // Up icon qualifier (for special icon treatment)
73 SET_UP_TYPE (xfdir_p->gl[0].en->type);
74 // Dummy type qualifier (for paper placement at 0,0 treatment)
75 SET_DUMMY_TYPE (xfdir_p->gl[0].en->type);
76
77 return NULL;
78 }
79
80 static
81 void
allocate_xfdir_p(xfdir_t * xfdir_p,gint items)82 allocate_xfdir_p(xfdir_t *xfdir_p, gint items){
83 xfdir_p->pathc=items;
84 xfdir_p->gl = (dir_t *)malloc(xfdir_p->pathc*sizeof(dir_t));
85 if (!xfdir_p->gl) g_error("malloc");
86 memset(xfdir_p->gl,0,xfdir_p->pathc*sizeof(dir_t));
87 return;
88 }
89
90 typedef struct wtf_t{
91 widgets_t *widgets_p;
92 gchar *application;
93 } wtf_t;
94
95 static
wtf(void * data)96 void * wtf(void *data){
97 wtf_t *wtf_p = data;
98 gchar *text=g_strdup_printf (_("The \"%s\" utility is not installed.\nPlease install it."), wtf_p->application);
99 // This rfm_confirm() has deadlock potential
100 // rfm_confirm(NULL, GTK_MESSAGE_WARNING, text, NULL, _("Accept"));
101 rfm_threaded_show_text(wtf_p->widgets_p);
102 rfm_threaded_diagnostics(wtf_p->widgets_p, "xffm/emblem_applications",NULL);
103 rfm_threaded_diagnostics(wtf_p->widgets_p, "xffm_tag/stderr",g_strconcat(text, "\n",NULL));
104 #ifdef THIS_IS_BSD
105 if (strstr(wtf_p->application, "sshfs")){
106 rfm_threaded_diagnostics(wtf_p->widgets_p, "xffm/stock_help",NULL);
107 rfm_threaded_diagnostics(wtf_p->widgets_p, "xffm_tag/green",
108 g_strconcat(_("For port sys-utils/fusefs-sshfs, you need BSD sources to build kernel module."),
109 "\n",NULL));
110 rfm_threaded_diagnostics(wtf_p->widgets_p, "xffm/stock_help",NULL);
111 rfm_threaded_diagnostics(wtf_p->widgets_p, "xffm_tag/green",
112 g_strconcat(_("Remember that user must be in group \"operator\" (see /dev/fuse0)."),
113 "\n",NULL));
114 rfm_threaded_diagnostics(wtf_p->widgets_p, "xffm/stock_help",NULL);
115 rfm_threaded_diagnostics(wtf_p->widgets_p, "xffm_tag/green",
116 g_strconcat(_("Remember that /etc/sysctl.conf must have the line: \"vfs.usermount=1\"."),
117 "\n",NULL));
118 }
119 #endif
120 g_free(text);
121 g_free(wtf_p->application);
122 g_free(data);
123 return NULL;
124 }
125
126 // This we do in a thread to avoid confusion with a dead hearbeat.
127 // (Load must satisfy heartbeat condition at all times!)
128 void *
fuse_check_program(const gchar * program_to_check)129 fuse_check_program(const gchar *program_to_check){
130 if (!program_to_check) {
131 DBG("check_program(): program_to_check==NULL!\n");
132 }
133 gchar *p = g_find_program_in_path(program_to_check);
134 if (!p) {
135 gchar *sbin = g_strdup_printf("/sbin/%s", program_to_check);
136 if (rfm_g_file_test(sbin, G_FILE_TEST_IS_EXECUTABLE)) {
137 p = sbin;
138 } else {
139 g_free(sbin);
140 }
141 }
142 if (!p) {
143 gchar *sbin = g_strdup_printf("/usr/sbin/%s", program_to_check);
144 if (rfm_g_file_test(sbin, G_FILE_TEST_IS_EXECUTABLE)) {
145 p = sbin;
146 } else {
147 g_free(sbin);
148 }
149 }
150 if (!p) {
151 gchar *sbin = g_strdup_printf("/usr/local/sbin/%s", program_to_check);
152 if (rfm_g_file_test(sbin, G_FILE_TEST_IS_EXECUTABLE)) {
153 p = sbin;
154 } else {
155 g_free(sbin);
156 }
157 }
158 if (!p){
159 widgets_t * widgets_p = rfm_get_widget("widgets_p");
160 wtf_t *wtf_p = (wtf_t *)malloc(sizeof(wtf_t));
161 memset(wtf_p, 0, sizeof(wtf_t));
162 wtf_p->widgets_p = widgets_p;
163 wtf_p->application = g_strdup(program_to_check);
164 view_t *view_p = widgets_p->view_p;
165 rfm_view_thread_create(view_p, wtf, wtf_p, "fuse_check_program() wtf thread\n");
166 return NULL;
167 }
168 g_free(p);
169 return GINT_TO_POINTER(TRUE);
170 }
171
172 static
173 void *
options_dummy(void * p,const gchar * path,const gchar * module_name)174 options_dummy(void *p, const gchar *path, const gchar *module_name){
175 xfdir_t *xfdir_p = p;
176 xfdir_p->gl[1].en=rfm_mk_entry(0);
177 xfdir_p->gl[1].en->st = NULL;
178 // xfdir_p->gl[1].en->parent_module = MODULE_NAME;
179 xfdir_p->gl[1].en->module = module_name;
180 xfdir_p->gl[1].en->path=g_strdup(path);
181 xfdir_p->gl[1].pathv = g_strdup(path);
182 SET_DUMMY_TYPE (xfdir_p->gl[1].en->type);
183 return p;
184 }
185
186 static
187 gchar **
loadcount_items(GKeyFile * key_file,const gchar * item_type,gint * items)188 loadcount_items (GKeyFile *key_file, const gchar *item_type, gint *items){
189 gchar *file = g_build_filename(FUSE_KEY_FILE, NULL);
190 gchar **groups = NULL;
191 if (g_key_file_load_from_file (key_file, file, 0, NULL)){
192 groups = g_key_file_get_groups (key_file, NULL);
193 gchar **g_p=groups;
194 for (;g_p && *g_p; g_p++) {
195 if (strncmp(*g_p, item_type, strlen(item_type))!=0) continue;
196 (*items)++;
197 }
198 }
199 g_free(file);
200 return groups;
201 }
202
203 static
204 gboolean
mount_test(record_entry_t * en)205 mount_test(record_entry_t *en) {
206 gint mounted = FSTAB_entry_is_mounted (en);
207 widgets_t * widgets_p = rfm_get_widget("widgets_p");
208 gchar *text = NULL;
209 if (mounted==0) {
210 text = g_strdup_printf("%s\n%s\n\n%s\n%s\n\n%s",
211 _("Path:"), en->pseudo_path,
212 _("Mount Point:"), en->path,
213 _("The volume is not mounted."));
214 rfm_confirm(widgets_p, GTK_MESSAGE_ERROR, text, NULL, NULL);
215 } else if (mounted<0) {
216 text = g_strdup_printf("%s\n%s\n\n%s\n%s\n\n%s",
217 _("Path:"), en->pseudo_path,
218 _("Mount Point:"), en->path,
219 _("There was a network error."));
220 rfm_confirm(widgets_p, GTK_MESSAGE_ERROR, text, NULL, NULL);
221 }
222 g_free(text);
223 return mounted;
224 }
225
226
227 static
228 void
fuse_error(GtkWidget * dialog,const gchar * text)229 fuse_error(GtkWidget *dialog, const gchar *text){
230 widgets_t * widgets_p = rfm_get_widget("widgets_p");
231 rfm_confirm(widgets_p, GTK_MESSAGE_ERROR, text, NULL, _("Accept"));
232 return;
233 }
234
235 static
236 gchar *
fuse_get_item(GtkWidget * dialog,const gchar * id)237 fuse_get_item(GtkWidget *dialog, const gchar *id){
238 if (!id || ! dialog) return NULL;
239 GtkWidget *entry = g_object_get_data(G_OBJECT(dialog), id);
240 if (!entry) return NULL;
241 const gchar *c = gtk_entry_get_text (GTK_ENTRY(entry));
242 if (!c || !strlen(c)) return NULL;
243 return g_strdup(c);
244 }
245
246 static
247 void
fuse_set_key_item_f(gpointer key,gpointer value,gpointer data)248 fuse_set_key_item_f (gpointer key, gpointer value, gpointer data){
249 key_options_t *key_options_p = data;
250 if (GPOINTER_TO_INT(value) == -1) {
251 g_key_file_set_boolean (key_options_p->key_file, key_options_p->group, key, TRUE);
252 } else if (value) {
253 NOOP(stderr, "set key value, %s -- > %s\n", (gchar *)key, (gchar *)value);
254 g_key_file_set_value (key_options_p->key_file, key_options_p->group, key, value);
255 }
256 return;
257 }
258
259 static
260 GtkWidget *
fuse_make_entry_box(GtkWidget * dialog,const gchar * text,const gchar * id,const gchar * colon,gboolean visibility,gpointer callback)261 fuse_make_entry_box(GtkWidget *dialog,
262 const gchar *text,
263 const gchar *id,
264 const gchar *colon,
265 gboolean visibility,
266 gpointer callback){
267 GtkWidget *hbox = rfm_hbox_new(FALSE, 0);
268 gchar *full_text = g_strconcat(text, colon, NULL);
269 GtkWidget *label = gtk_label_new(full_text);
270 g_free(full_text);
271 GtkWidget *entry = gtk_entry_new();
272 gtk_entry_set_visibility (GTK_ENTRY(entry), visibility);
273 g_object_set_data(G_OBJECT(dialog), id, entry);
274 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
275 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
276 gtk_widget_show(hbox);
277 gtk_widget_show(label);
278 gtk_widget_show(entry);
279 if (callback) {
280 g_signal_connect (G_OBJECT (entry), "key-release-event", G_CALLBACK (callback), dialog);
281 }
282 return hbox;
283 }
284
285 static
286 void
fuse_set_check_button_state(GtkWidget * dialog,GKeyFile * key_file,const gchar * group,const gchar * key,const gchar * id,gboolean default_state)287 fuse_set_check_button_state(GtkWidget *dialog,
288 GKeyFile *key_file,
289 const gchar *group,
290 const gchar *key,
291 const gchar *id,
292 gboolean default_state){
293 GtkWidget *check = g_object_get_data(G_OBJECT(dialog), id);
294 if (!check) return;
295 if (strstr(id, "FTP_PASSIVE")){
296 NOOP(stderr, "FTP_passive = %d\n",
297 g_key_file_get_boolean(key_file, group, key, NULL));
298 }
299 if (key_file){
300 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check),
301 g_key_file_get_boolean(key_file, group, key, NULL));
302 } else {
303 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), default_state);
304 }
305 }
306
307 static
308 GtkWidget *
fuse_make_check_box(GtkWidget * dialog,const gchar * text,const gchar * id,gpointer callback)309 fuse_make_check_box(GtkWidget *dialog,
310 const gchar *text,
311 const gchar *id,
312 gpointer callback)
313 {
314 GtkWidget *check;
315 check = gtk_check_button_new_with_label (text);
316 g_object_set_data(G_OBJECT(dialog), id, check);
317 gtk_widget_show(check);
318 if (callback){
319 g_signal_connect (check, "toggled", G_CALLBACK (callback), dialog);
320 }
321 return check;
322 }
323
324 static
325 void
fuse_set_entry(GtkWidget * entry,GKeyFile * key_file,const gchar * group,const gchar * key,const gchar * default_value)326 fuse_set_entry(GtkWidget *entry,
327 GKeyFile *key_file,
328 const gchar *group,
329 const gchar *key,
330 const gchar *default_value){
331 gchar *pre_set=NULL;
332 if (key_file && group) {
333 pre_set = g_key_file_get_value(key_file, group, key, NULL);
334 }
335
336 gtk_entry_set_text(GTK_ENTRY(entry),(pre_set)?pre_set:default_value);
337 g_free(pre_set);
338 }
339
340 static
341 const gchar *
fuse_icon_id(void * p,const gchar * label,const gchar * module_icon_id,const gchar * authorization)342 fuse_icon_id(void *p, const gchar *label,
343 const gchar *module_icon_id,
344 const gchar *authorization)
345 {
346 record_entry_t *en = (record_entry_t *)p;
347 if (!en || !en->path || !en->module) return "xffm/emblem_broken"; /* Error.*/
348 // FUSE module:
349 if (strcmp(en->module, "fuse")==0) {
350 // This never happens... Icon is resolved by module's item_icon_id
351 return "xffm/emblem_broken";
352 }
353
354 // Authorization icons:
355 if (strcmp(en->path, authorization)==0) {
356 if (strcmp(en->module, "obex")==0) {
357 // Bluetooth filesystems
358 return "xffm/emblem_bluetooth/compositeSW/stock_add";
359 } else if (strcmp(en->module, "ecryptfs")==0) {
360 // Encrypted filesystems
361 return "xffm/emblem_keyhole/compositeSW/stock_add";
362 } else {
363 // Network filesystems
364 return "xffm/emblem_network/compositeSW/stock_add";
365 }
366 }
367
368 // Module icons:
369 if (!IS_UP_TYPE(en->type)) {
370 if (en->path && strcmp(en->path, label)==0) {
371 return module_icon_id;
372 }
373 } else if (strcmp(en->module, "cifs")==0) {
374 static gchar *cifs_up_icon = NULL;
375 if (!cifs_up_icon) cifs_up_icon =
376 g_strconcat(module_icon_id, "/compositeSW/stock_go-up", NULL);
377 // Up type icons: currently just for cifs module
378 return cifs_up_icon;
379 }
380
381 // Plain item icons
382 if (en->module) {
383 void *mounted = rfm_natural(PLUGIN_DIR, "fstab", en->path, "is_mounted_with_wait");
384 if (mounted) {
385
386 if (strcmp(en->module, "obex")==0){
387 return "xffm/emblem_pda/compositeNW/emblem_greenball";
388 }
389 else if (strcmp(en->module, "sftp")==0){
390 return "xffm/emblem_network/compositeNW/emblem_greenball";
391 }
392 else if (strcmp(en->module, "ftp")==0){
393 return "xffm/emblem_network/compositeNW/emblem_greenball";
394 }
395 else if (strcmp(en->module, "cifs")==0){
396 return "xffm/emblem_network/compositeNW/emblem_greenball";
397 }
398 else if (strcmp(en->module, "nfs")==0){
399 return "xffm/emblem_network/compositeNW/emblem_greenball";
400 }
401 else if (strcmp(en->module, "ecryptfs")==0){
402 return "xffm/emblem_network/compositeNW/emblem_greenball";
403 }
404 } else {
405 if (strcmp(en->module, "obex")==0){
406 return "xffm/emblem_pda/compositeNW/emblem_redball";
407 }
408 else if (strcmp(en->module, "sftp")==0){
409 return "xffm/emblem_network/compositeNW/emblem_redball";
410 }
411 else if (strcmp(en->module, "ftp")==0){
412 return "xffm/emblem_network/compositeNW/emblem_redball";
413 }
414 else if (strcmp(en->module, "cifs")==0){
415 return "xffm/emblem_network/compositeNW/emblem_redball";
416 }
417 else if (strcmp(en->module, "nfs")==0){
418 return "xffm/emblem_network/compositeNW/emblem_redball";
419 }
420 else if (strcmp(en->module, "ecryptfs")==0){
421 return "xffm/emblem_network/compositeNW/emblem_redball";
422 }
423 }
424
425
426
427 return "xffm/emblem_shared/compositeSW/emblem_atom";
428 }
429 return "xffm/emblem_broken"; /* Error.*/
430
431 }
432
433 static
434 xfdir_t *
fuse_xfdir_get(void * p,const gchar * program,const gchar * scheme,const gchar * mount_point,const gchar * module_name,const gchar * authorization)435 fuse_xfdir_get(void *p,
436 const gchar *program,
437 const gchar *scheme,
438 const gchar *mount_point,
439 const gchar *module_name,
440 const gchar *authorization){
441 xfdir_t *xfdir_p = p;
442 NOOP(stderr, " fuse_xfdir_get...\n");
443 gint items = 1;
444 if (GPOINTER_TO_INT(fuse_check_program(program))) items++;
445 if (items == 1){
446 allocate_xfdir_p(xfdir_p, items);
447 submodule_up_item(xfdir_p);
448 return xfdir_p;
449 }
450
451 GKeyFile *key_file = g_key_file_new ();
452 gchar **groups = loadcount_items (key_file, scheme, &items);
453 allocate_xfdir_p(xfdir_p, items);
454 submodule_up_item(xfdir_p);
455 options_dummy(xfdir_p, authorization, module_name);
456 if (items > 2) {
457 gchar **g_p=groups;
458 gint i=2;
459 for (;g_p && *g_p; g_p++){
460 if (strncmp(*g_p, scheme, strlen(scheme))!=0) continue;
461 xfdir_p->gl[i].en=rfm_mk_entry(0);
462 xfdir_p->gl[i].en->st = (struct stat *) malloc(sizeof(struct stat));
463 memset(xfdir_p->gl[i].en->st, 0, sizeof(struct stat));
464 xfdir_p->gl[i].en->st->st_ino = 1;
465
466 SET_SDIR(xfdir_p->gl[i].en->type);
467 xfdir_p->gl[i].en->path=
468 g_key_file_get_value(key_file, *g_p,
469 mount_point, NULL);
470 if (!xfdir_p->gl[i].en->path) {
471 xfdir_p->gl[i].en->tag = rfm_default_url_mount_point(*g_p);
472 }
473 xfdir_p->gl[i].en->module = module_name;
474 xfdir_p->gl[i].en->pseudo_path=g_strdup(*g_p);
475 xfdir_p->gl[i].pathv = g_strdup(*g_p);
476 i++;
477 }
478 }
479 g_strfreev(groups);
480 g_key_file_free(key_file);
481
482 return xfdir_p;
483
484 }
485
486 void *
fuse_click(fuse_data_t * (* dialog_f)(const gchar * url),const gchar * url,record_entry_t * en,const gchar * module_name)487 fuse_click(fuse_data_t * (*dialog_f)(const gchar *url), const gchar *url, record_entry_t *en, const gchar *module_name){
488 widgets_t *widgets_p = rfm_get_widget("widgets_p");
489
490 // If entry is up type, go for default handler
491 if (en && IS_UP_TYPE(en->type)) return NULL;
492 // If entry is NULL, we just want to pop up the properties dialog.
493 // Or, if the url does not match the entry url (as in the "add item" icon)
494 if (!en || !url) {
495 confirm_host(dialog_f, url, module_name);
496 return GINT_TO_POINTER(1);
497 }
498
499 // If entry is not NULL and item is mounted, we want to go to mount point.
500 if (mount_test(en)) {
501 // record_entry_t *t_en = rfm_copy_entry(en);
502 record_entry_t *t_en = rfm_stat_entry(en->path, 0);
503 t_en->module=NULL;
504 rodent_push_view_go_history ();
505 if(!rodent_refresh (widgets_p, t_en)) {
506 // cannot load
507 DBG("could not load %s\n", t_en->path);
508 rfm_destroy_entry(t_en);
509 }
510 return GINT_TO_POINTER(1);
511 }
512 // Item is not mounted. Pop up the properties dialog.
513 confirm_host(dialog_f, url, module_name);
514 return GINT_TO_POINTER(1);
515 }
516
517 ///////////////// popup callbacks....
518 static
519 void
new_tab_open(GtkMenuItem * menuitem,gpointer user_data)520 new_tab_open (GtkMenuItem * menuitem, gpointer user_data) {
521 record_entry_t *en = g_object_get_data(G_OBJECT(menuitem), "entry");
522 if (!en) return;
523 widgets_t * widgets_p = rfm_get_widget("widgets_p");
524
525
526 if (!mount_test(en)) return;
527 //
528 view_t *view_p = widgets_p->view_p;
529
530 if(view_p->tab_constructor) {
531 (*(view_p->tab_constructor))(widgets_p, en->path);
532 }
533 }
534
535
536 static
537 void
new_window_open(GtkMenuItem * menuitem,gpointer user_data)538 new_window_open (GtkMenuItem * menuitem, gpointer user_data) {
539 record_entry_t *en = g_object_get_data(G_OBJECT(menuitem), "entry");
540 if (!en) return;
541 widgets_t * widgets_p = rfm_get_widget("widgets_p");
542
543
544 if (!mount_test(en)) return;
545 //
546 gchar *new_path=NULL;
547 new_path=g_strdup(en->path);
548 rodent_new_gridview(widgets_p, new_path);
549 g_free(new_path);
550 return;
551
552 }
553
554
555 static
556 void
unmount_host(GtkMenuItem * menuitem,gpointer user_data)557 unmount_host (GtkMenuItem * menuitem, gpointer user_data) {
558 //sshfs [user@]host:[dir] mountpoint
559 //fusermount -u mountpoint
560 record_entry_t *en = g_object_get_data(G_OBJECT(menuitem), "entry");
561 if (!en) return;
562 widgets_t * widgets_p = rfm_get_widget("widgets_p");
563
564
565 gchar *argv[4];
566 gint i=0;
567 #ifdef THIS_IS_LINUX
568 argv[i++] = "fusermount";
569 argv[i++] = "-u";
570 #else
571 # ifdef THIS_IS_BSD
572 argv[i++] = "umount";
573 # else
574 # error "This should not happen"
575 # endif
576 #endif
577 argv[i++] = en->path;
578 argv[i++] = NULL;
579
580 // FIXME: then remove mountpoint if empty (simple rmdir).
581
582 rfm_show_text(widgets_p);
583 rfm_thread_run_argv (widgets_p, argv, FALSE);
584 /* argv[0] = "rmdir";
585 argv[1] = en->tag;
586 argv[2] = NULL;
587 rfm_thread_run_argv (widgets_p, argv, FALSE); */
588
589 }
590
591
592 static
593 void
remove_host(GtkMenuItem * menuitem,gpointer user_data)594 remove_host (GtkMenuItem * menuitem, gpointer user_data) {
595 record_entry_t *en = g_object_get_data(G_OBJECT(menuitem), "entry");
596 if (!en) return;
597 widgets_t * widgets_p = rfm_get_widget("widgets_p");
598
599
600 // Unmount first if mounted.
601 gint mounted = FSTAB_entry_is_mounted (en);
602 if (mounted > 0) {
603 unmount_host (menuitem, user_data);
604 } else if (mounted < 0) {
605 gchar *text = g_strdup_printf("%s\n%s\n\n%s\n%s\n\n%s",
606 _("Path:"), en->pseudo_path,
607 _("Mount Point:"), en->path,
608 _("There was a network error."));
609 rfm_confirm(widgets_p, GTK_MESSAGE_ERROR, text, NULL, NULL);
610 g_free(text);
611 }
612 // Remove group
613 group_options_remove_group(en->pseudo_path);
614 // Refresh
615 view_t *view_p = widgets_p->view_p;
616 record_entry_t *t_en = rfm_copy_entry(view_p->en);
617 if(!rodent_refresh (widgets_p, t_en)) {
618 rfm_destroy_entry(t_en);
619 }
620 }
621
622 static void *
callback_f(void * p)623 callback_f(void *p){
624 void **arg = p;
625 void ((*callback)(GtkMenuItem *, gpointer)) = arg[0];
626 GtkMenuItem *menuitem = arg[1];
627 void *data = arg[2];
628 g_free(arg);
629 (*callback)(menuitem, data);
630 return NULL;
631 }
632
633
634
635
636
637 //////////////// end of popup callbacks....
638 static void
variable_call(GtkMenuItem * menuitem,gpointer data)639 variable_call(GtkMenuItem * menuitem, gpointer data){
640 void **arg = (void **)malloc(3*sizeof(void *));
641 if (!arg) g_error("malloc: %s\n", strerror(errno));
642
643 arg[0] = g_object_get_data(G_OBJECT(menuitem), "callback");
644 arg[1] = menuitem;
645 arg[2] = data;
646 widgets_t *widgets_p = rfm_get_widget("widgets_p");
647 view_t *view_p = widgets_p->view_p;
648 rfm_view_thread_create(view_p, callback_f, arg, "fuse callback_f");
649 return;
650 }
651
652 static void *
thread_popup(void * data)653 thread_popup(void *data){
654 if (rfm_get_gtk_thread() == g_thread_self()){
655 g_warning("thread_mk_popup_menu: only to be called from non main thread\n");
656 return NULL;
657 }
658
659 GtkWidget *popup_widget=NULL;
660 GMutex *popup_mutex = rfm_get_widget("fuse_popup_mutex");
661 g_mutex_lock(popup_mutex);
662 popup_widget = rfm_get_widget(POPUP_MENU_ID);
663 if (!popup_widget) {
664 popup_widget=rodent_thread_add_submenu (NULL, "rodent-fuse", POPUP_ID, NULL);
665 TRACE( "fuse_thread_popup creation...\n");
666 RodentMenuDefinition menu_definitions_p[] = {FUSE_MENU_STUFF};
667 rodent_thread_multimenu_make(NULL, menu_definitions_p);
668 widgets_t *widgets_p = rfm_get_widget ("widgets_p");
669 view_t *view_p = widgets_p->view_p;
670 xfdir_register_popup(view_p, popup_widget);
671 } else {
672 TRACE( "fuse_thread_popup retrieval...\n");
673 }
674 g_mutex_unlock(popup_mutex);
675 return popup_widget;
676 }
677
678 static
679 void *
fuse_private_popup(const gchar * label_text,void (* properties_f)(GtkMenuItem *,gpointer),void (* mount_f)(GtkMenuItem *,gpointer),void (* umount_f)(GtkMenuItem *,gpointer))680 fuse_private_popup(const gchar *label_text,
681 void (*properties_f)(GtkMenuItem *, gpointer),
682 void (*mount_f)(GtkMenuItem *, gpointer),
683 void (*umount_f)(GtkMenuItem *, gpointer)
684 )
685 {
686 TRACE( "fuse_private_popup...\n");
687 // if umount function is not defined, then use fusermount.
688 if (umount_f == NULL) umount_f = unmount_host;
689 widgets_t *widgets_p = rfm_get_widget("widgets_p");
690 view_t *view_p = widgets_p->view_p;
691 if (!(g_slist_length(view_p->selection_list)==1)) return NULL;
692
693 record_entry_t *en=(record_entry_t *)view_p->selection_list->data;
694 if (en==NULL || !en->st){
695 // No population item is found under the pointer
696 // or item not defined correctly (st==NULL)
697 // Do the default popup menu.
698 return NULL;
699 }
700
701 GtkWidget *popup_widget = rfm_get_widget(POPUP_MENU_ID);
702 if (!popup_widget) g_error("popup_widget is initialized on module load...\n");
703 // Set variable functions: properties, mount and unmount.
704 GtkWidget *item;
705 item = rfm_get_widget("fuse_properties");
706 g_object_set_data(G_OBJECT(item), "callback", properties_f);
707 item = rfm_get_widget("fuse_mount");
708 g_object_set_data(G_OBJECT(item), "callback", mount_f);
709 item = rfm_get_widget("fuse_unmount");
710 g_object_set_data(G_OBJECT(item), "callback", umount_f);
711
712 // Set record entry information.
713 gchar *items[]={"fuse_new_tab", "fuse_new_window", "fuse_properties",
714 "fuse_mount", "fuse_unmount", "fuse_delete", NULL};
715 gchar **y = items;
716 for (; y && *y; y++){
717 GtkWidget *w = rfm_get_widget(*y);
718 g_object_set_data(G_OBJECT(w),"widgets_p",widgets_p);
719 g_object_set_data(G_OBJECT(w), "entry", en);
720 }
721 gint mounted = FSTAB_entry_is_mounted (en);
722
723 if (mounted > 0) {
724 HIDE_IT("fuse_broken_mount");
725 HIDE_IT("fuse_mount");
726 SHOW_IT("fuse_unmount");
727 } else if (mounted == 0){
728 HIDE_IT("fuse_broken_mount");
729 HIDE_IT("fuse_unmount");
730 SHOW_IT("fuse_mount");
731 } else {
732 HIDE_IT("fuse_unmount");
733 HIDE_IT("fuse_mount");
734 SHOW_IT("fuse_broken_mount");
735 }
736
737
738 gtk_menu_popup(GTK_MENU(popup_widget), NULL, NULL, NULL, NULL, 3, gtk_get_current_event_time());
739
740 return GINT_TO_POINTER(1);
741
742 }
743
744
745 typedef struct fuse_login_t{
746 guint64 flag;
747 gchar *flag_key;
748 gchar *computer;
749 gchar *remote_path;
750 gchar *login;
751 gchar *empty_passphrase;
752 gchar *secure_shell_key;
753 gchar *url;
754 gchar *mount_point;
755 gchar *monitor;
756 gchar *broadband;
757 }fuse_login_t;
758
free_login_p(fuse_login_t * p)759 void free_login_p(fuse_login_t *p){
760 if (!p) return;
761 g_free(p->flag_key);
762 g_free(p->computer);
763 g_free(p->remote_path);
764 g_free(p->login);
765 g_free(p->empty_passphrase);
766 g_free(p->secure_shell_key);
767 g_free(p->url);
768 g_free(p->mount_point);
769 g_free(p->monitor);
770 g_free(p->broadband);
771 g_free(p);
772 }
773
774 // This function is called by "accept", which is contained in GDK mutex.
775 // The extra MUTEX is redundant (recursive).
776 void *
fuse_get_login_info(fuse_data_t * fuse_data_p)777 fuse_get_login_info (fuse_data_t *fuse_data_p){
778 if (!fuse_data_p->dialog) g_error("fuse_get_login_info(): dialog may not be NULL\n");
779 const gchar *url_template = g_object_get_data(G_OBJECT(fuse_data_p->dialog), "url_template");
780 if (!url_template) g_error("url_template not defined\n");
781
782 fuse_login_t *fuse_login_p =
783 (fuse_login_t *)malloc(sizeof(fuse_login_t));
784 if (!fuse_login_p){
785 g_error("unable to malloc fuse_login_p\n");
786 }
787 memset(fuse_login_p, 0, sizeof(fuse_login_t));
788
789 const gchar *group = fuse_data_p->url;
790 // Guint64 flag, FLAG_0
791 fuse_login_p->flag_key = FLAG_KEY(0);
792 guint64 ui = 0x01;
793
794 // Get specified host name, FUSE_COMPUTER, if it is in the dialog, of course.
795 if (g_object_get_data(G_OBJECT(fuse_data_p->dialog), "FUSE_COMPUTER")){
796 fuse_login_p->computer = fuse_get_item(fuse_data_p->dialog, "FUSE_COMPUTER");
797 if (!fuse_login_p->computer){
798 fuse_error(fuse_data_p->dialog,_("Invalid hostname"));
799 free_login_p(fuse_login_p);
800 fuse_login_p->url = g_strdup_printf("%s://%s%s", url_template, fuse_login_p->computer,
801 (fuse_login_p->remote_path)? fuse_login_p->remote_path: "");
802 return NULL;
803 } else {
804 fuse_login_p->flag |= (ui << 0);
805 }
806 } else if (fuse_data_p->computer == NULL){
807 fuse_error(fuse_data_p->dialog,_("Invalid hostname"));
808 free_login_p(fuse_login_p);
809 if (!fuse_login_p->url) {
810 DBG("fuse_get_login_info(): fuse_login_p->url is not defined\n");
811 }
812 return NULL;
813 } else {
814 fuse_login_p->url = g_strdup(fuse_data_p->url);
815 fuse_login_p->computer = g_strdup(fuse_data_p->computer);
816 }
817
818
819 // Get specified rpath, FUSE_REMOTE_PATH
820 if (g_object_get_data(G_OBJECT(fuse_data_p->dialog), "FUSE_REMOTE_PATH")){
821 fuse_login_p->remote_path = fuse_get_item(fuse_data_p->dialog, "FUSE_REMOTE_PATH");
822 if (!fuse_login_p->remote_path){
823 fuse_error(fuse_data_p->dialog,_("invalid path"));
824 free_login_p(fuse_login_p);
825 return NULL;
826 } else {
827 fuse_login_p->flag |= (ui << 1);
828 }
829 }
830
831
832
833 GtkWidget *check = g_object_get_data(G_OBJECT(fuse_data_p->dialog), "FUSE_ALLOW_EMPTY_PASSPHRASE");
834 if (check){
835 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check))) {
836 fuse_login_p->empty_passphrase = g_strdup("yes");
837 } else {
838 fuse_login_p->empty_passphrase = g_strdup("");
839 }
840 }
841 if (fuse_login_p->empty_passphrase && strlen(fuse_login_p->empty_passphrase)) {
842 fuse_login_p->flag |= (ui << 2);
843 }
844
845 check = g_object_get_data(G_OBJECT(fuse_data_p->dialog), "FUSE_SECURE_SHELL_KEY");
846 if (check){
847 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check))) {
848 fuse_login_p->secure_shell_key = g_strdup("yes");
849 } else {
850 fuse_login_p->secure_shell_key = g_strdup("");
851 }
852 }
853 if (fuse_login_p->secure_shell_key && strlen(fuse_login_p->secure_shell_key)) {
854 fuse_login_p->flag |= (ui << 3);
855 }
856
857 if (fuse_login_p->empty_passphrase && strlen(fuse_login_p->empty_passphrase)) {
858 fuse_login_p->flag |= (ui << 2);
859 }
860 if (fuse_login_p->secure_shell_key && strlen(fuse_login_p->secure_shell_key)){
861 fuse_login_p->flag |= (ui << 3);
862 }
863 {
864 // Get login (if any)
865 fuse_login_p->login =
866 fuse_get_item(fuse_data_p->dialog, "FUSE_LOGIN");
867 if (fuse_login_p->login){
868 fuse_login_p->flag |= (ui << 4);
869 }
870 }
871
872 // Get specified mount point
873 //GtkWidget *entry;
874 TRACE( "Get specified mount point...\n");
875 //if (rfm_void(PLUGIN_DIR, "fstab", "module_active"))
876 {
877 //if (!gtk_widget_get_sensitive(entry)){
878 // Get record_entry
879 record_entry_t *en = rfm_mk_entry(0);
880 gchar *preset_mnt_point = fuse_get_item(fuse_data_p->dialog, "FUSE_MOUNT_POINT");
881 if (preset_mnt_point && g_file_test(preset_mnt_point, G_FILE_TEST_IS_DIR)) {
882 en->tag = preset_mnt_point;
883 } else {
884 g_free(preset_mnt_point);
885 // en->tag will set default mount point in dialog
886 // Do this for ecryptfs:
887 if (g_object_get_data(G_OBJECT(fuse_data_p->dialog), "ECRYPTFS_SIG")
888 && fuse_login_p->remote_path) {
889 en->tag = g_strdup(fuse_login_p->remote_path);
890 }
891 }
892 if (!fuse_login_p->remote_path) {
893 en->path = g_strdup(fuse_login_p->computer);
894 } else {
895 en->path = g_strdup_printf("%s%s%s", fuse_login_p->computer,
896 (fuse_login_p->remote_path[0]=='/')? "":"/",
897 fuse_login_p->remote_path);
898 }
899
900 GtkWidget *entry = g_object_get_data(G_OBJECT(fuse_data_p->dialog),
901 "FUSE_MOUNT_POINT");
902 if (gtk_widget_get_sensitive(entry)){
903 en->pseudo_path = g_strdup(en->path);
904 } else {
905 en->pseudo_path = g_strdup_printf("%s", fuse_login_p->computer);
906 }
907 gchar *d;
908 if (gtk_widget_get_sensitive(entry)) for (d=en->path; d && *d; d++){
909 if (*d=='/' || *d=='@') *d='-'; //if (*d=='/') *d='\\';if (*d=='@') *d='\\';
910 }
911
912 fuse_login_p->mount_point =
913 (gchar *)rfm_natural(RFM_MODULE_DIR, "callbacks", en, "callback_mnt_point");
914 rfm_destroy_entry(en);
915 NOOP(stderr, "fuse-common.c: mount point=%s\n", fuse_login_p->mount_point);
916 if (!fuse_login_p->mount_point || !strlen(fuse_login_p->mount_point) || !g_path_is_absolute(fuse_login_p->mount_point)){
917 gchar *text = g_strconcat(_("Could not detect any mount point."),
918 " (callbacks: callback_mnt_point)", NULL);
919
920 fuse_error(fuse_data_p->dialog,text);
921 g_free(text);
922 free_login_p(fuse_login_p);
923 return NULL;
924 }
925 }
926 #if 0
927 // Deprecated. Mount point dialog is now in callbacks module, which
928 // will always be present.
929 else {
930 entry = g_object_get_data(G_OBJECT(fuse_data_p->dialog), "FUSE_MOUNT_POINT"); const gchar *c = gtk_entry_get_text (GTK_ENTRY(entry));
931 if (!c || !strlen(c) || !g_path_is_absolute(c)){
932 NOOP("2.invalid mountpoint\n");
933 fuse_error(fuse_data_p->dialog,_("Could not detect any mount point."));
934 free_login_p(fuse_login_p);
935 return NULL;
936 }
937 fuse_login_p->mount_point = g_strdup(c);
938 if(g_mkdir_with_parents (fuse_login_p->mount_point, 0700) < 0) {
939 gchar *warn = g_strdup_printf("mkdir(%s): %s\n",
940 fuse_login_p->mount_point, strerror (errno));
941 fuse_error(fuse_data_p->dialog, warn);
942 g_free(warn);
943 free_login_p(fuse_login_p);
944 return NULL;
945 }
946 }
947 #endif
948
949 fuse_login_p->flag |= (ui << 5);
950
951 // These are tree state check buttons.
952 // Null, does not exist
953 // strlen > 0, active
954 // strlen ==o, inactive.
955 check = g_object_get_data(G_OBJECT(fuse_data_p->dialog), "FUSE_MONITOR");
956 if (check){
957 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check))) {
958 fuse_login_p->monitor = g_strdup("yes");
959 } else {
960 fuse_login_p->monitor = g_strdup("");
961 }
962 }
963
964 if (fuse_login_p->monitor && strlen(fuse_login_p->monitor)) {
965 fuse_login_p->flag |= (ui << 6);
966 }
967
968 check = g_object_get_data(G_OBJECT(fuse_data_p->dialog), "FUSE_BROADBAND");
969 if (check){
970 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check))) {
971 fuse_login_p->broadband = g_strdup("yes");
972 } else {
973 fuse_login_p->broadband = g_strdup("");
974 }
975 }
976 if (fuse_login_p->broadband && strlen(fuse_login_p->broadband)) {
977 fuse_login_p->flag |= (ui << 7);
978 }
979
980
981
982 // all applicable items are now set.
983
984 // We now have enough to proceed...
985 key_options_t *key_options_p =
986 (key_options_t *)malloc(sizeof(key_options_t));
987 if (!key_options_p) g_error("cannot malloc key_options_p\n");
988 memset(key_options_p, 0, sizeof(key_options_t));
989 g_object_set_data(G_OBJECT(fuse_data_p->dialog), "key_options_p", key_options_p);
990
991 key_options_p->key_file = g_key_file_new ();
992
993
994 GHashTable *hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
995 g_object_set_data(G_OBJECT(fuse_data_p->dialog), "hash", hash);
996 g_hash_table_ref( hash);
997
998 if (g_object_get_data(G_OBJECT(fuse_data_p->dialog), "FUSE_URL")){
999 fuse_login_p->url = fuse_get_item(fuse_data_p->dialog, "FUSE_URL");
1000 if (!fuse_login_p->url){
1001 g_error("invalid URL");
1002 }
1003 }
1004 key_options_p->group = g_strdup(fuse_login_p->url);
1005 NOOP( "group %s\n", key_options_p->group);
1006
1007
1008 // Load previous values, including comments and translations...
1009 gchar *file = g_build_filename(FUSE_KEY_FILE, NULL);
1010 if (!g_key_file_load_from_file (key_options_p->key_file, file,
1011 G_KEY_FILE_KEEP_COMMENTS|G_KEY_FILE_KEEP_TRANSLATIONS, NULL)){
1012 NOOP("New file: %s\n", file);
1013 }
1014 g_free(file);
1015
1016 if (g_object_get_data(G_OBJECT(fuse_data_p->dialog), "FUSE_COMPUTER")){
1017 g_hash_table_insert(hash, g_strdup("FUSE_COMPUTER"), g_strdup(fuse_login_p->computer));
1018 }
1019 if(fuse_login_p->remote_path) {
1020 g_hash_table_insert(hash, g_strdup("FUSE_REMOTE_PATH"), g_strdup(fuse_login_p->remote_path));
1021 }
1022 if(fuse_login_p->login) {
1023 g_hash_table_insert(hash, g_strdup("FUSE_LOGIN"), g_strdup(fuse_login_p->login));
1024 }
1025 NOOP(stderr, "inserting to hash: %s\n", fuse_login_p->mount_point);
1026 g_hash_table_insert(hash, g_strdup("FUSE_MOUNT_POINT"), g_strdup(fuse_login_p->mount_point));
1027
1028 // Remove previous group values (if any).
1029 // This includes previous url:
1030 if (group) g_key_file_remove_group(key_options_p->key_file, group, NULL);
1031
1032 // And modified url:
1033 if (key_options_p->group) g_key_file_remove_group(key_options_p->key_file, key_options_p->group, NULL);
1034
1035 // Add group with new values.
1036 if (fuse_login_p->broadband && strlen(fuse_login_p->broadband)){
1037 g_key_file_set_boolean(key_options_p->key_file, key_options_p->group,
1038 "FUSE_BROADBAND", TRUE);
1039 g_key_file_set_boolean(key_options_p->key_file, key_options_p->group,
1040 "FUSE_MONITOR", FALSE);
1041 } else if (fuse_login_p->monitor && strlen(fuse_login_p->monitor)){
1042 g_key_file_set_boolean(key_options_p->key_file, key_options_p->group,
1043 "FUSE_MONITOR", TRUE);
1044 }
1045
1046 if (fuse_login_p->secure_shell_key && strlen(fuse_login_p->secure_shell_key)){
1047 g_key_file_set_boolean(key_options_p->key_file, key_options_p->group,
1048 "FUSE_SECURE_SHELL_KEY", TRUE);
1049 }
1050 if (fuse_login_p->empty_passphrase && strlen(fuse_login_p->empty_passphrase)){
1051 g_key_file_set_boolean(key_options_p->key_file, key_options_p->group,
1052 "FUSE_ALLOW_EMPTY_PASSPHRASE", TRUE);
1053 }
1054
1055 #if GLIB_MAJOR_VERSION==2 && GLIB_MINOR_VERSION<26
1056 g_key_file_set_integer (key_options_p->key_file, key_options_p->group,
1057 fuse_login_p->flag_key, (gint) fuse_login_p->flag);
1058
1059 #else
1060 g_key_file_set_uint64 (key_options_p->key_file, key_options_p->group,
1061 fuse_login_p->flag_key, fuse_login_p->flag);
1062 #endif
1063
1064 // replace current hash table values in key_file:
1065 if (hash){
1066 g_hash_table_foreach(hash, fuse_set_key_item_f, key_options_p);
1067 g_hash_table_destroy(hash);
1068 }
1069 // FLAG_0 is done.
1070 free_login_p(fuse_login_p);
1071
1072 return GINT_TO_POINTER(1);
1073 }
1074
1075 void *
fuse_set_options(fuse_data_t * fuse_data_p)1076 fuse_set_options(fuse_data_t *fuse_data_p){
1077 if (!fuse_data_p) g_error("fuse_data_p cannot be null\n");
1078
1079 guint64 flag = 0;
1080 gchar *flag_key = FLAG_KEY(fuse_data_p->flag_id);
1081 group_options_t *options_p = fuse_data_p->options_p;
1082 gchar ***options_keys_p = fuse_data_p->options_keys_p;
1083
1084 if (*options_keys_p == NULL) *options_keys_p = group_option_keys(options_p);
1085
1086 key_options_t *key_options_p =
1087 g_object_get_data(G_OBJECT(fuse_data_p->dialog), "key_options_p");
1088 if (!key_options_p) g_error("key_options_p cannot be null\n");
1089
1090 GHashTable *hash = group_options_get_option_hash(fuse_data_p->dialog, *options_keys_p, &flag);
1091 #if GLIB_MAJOR_VERSION==2 && GLIB_MINOR_VERSION<26
1092 g_key_file_set_integer (key_options_p->key_file, key_options_p->group, flag_key, (gint) flag);
1093
1094 #else
1095 g_key_file_set_uint64 (key_options_p->key_file, key_options_p->group, flag_key, flag);
1096 #endif
1097 g_free(flag_key);
1098 if (hash){
1099 g_hash_table_foreach(hash, fuse_set_key_item_f, key_options_p);
1100 g_hash_table_destroy(hash);
1101 }
1102
1103 return NULL;
1104 }
1105
1106 gchar *
fuse_save_keyfile(fuse_data_t * fuse_data_p)1107 fuse_save_keyfile(fuse_data_t *fuse_data_p){
1108 key_options_t *key_options_p =
1109 g_object_get_data(G_OBJECT(fuse_data_p->dialog), "key_options_p");
1110 if (!key_options_p) g_error("key_options_p cannot be null\n");
1111 NOOP(stderr, "writing keyfile for group: %s\n", key_options_p->group);
1112 gchar *url = g_strdup(key_options_p->group);
1113 group_options_write_keyfile(key_options_p->key_file);
1114 g_free(key_options_p->group);
1115 g_key_file_free(key_options_p->key_file);
1116 g_free(key_options_p);
1117
1118 GHashTable *hash =
1119 g_object_get_data(G_OBJECT(fuse_data_p->dialog), "hash");
1120 if (hash) g_hash_table_unref(hash);
1121 else{
1122 g_error("hash should not be null\n");
1123 }
1124 return url;
1125 }
1126
1127
1128 static
1129 void
toggle_broad(GtkToggleButton * togglebutton,gpointer data)1130 toggle_broad(GtkToggleButton *togglebutton , gpointer data){
1131 GtkWidget *dialog = data;
1132 GtkToggleButton *b = g_object_get_data(G_OBJECT(dialog), "FUSE_MONITOR");
1133 if (!b) return;
1134 if (gtk_toggle_button_get_active(togglebutton)){
1135 gtk_widget_set_sensitive(GTK_WIDGET(b), FALSE);
1136 gtk_toggle_button_set_active(b, FALSE);
1137 } else {
1138 gtk_widget_set_sensitive(GTK_WIDGET(b), TRUE);
1139 }
1140 }
1141
1142 static
1143 void
toggle_ssh(GtkToggleButton * togglebutton,gpointer data)1144 toggle_ssh(GtkToggleButton *togglebutton , gpointer data){
1145 GtkWidget *dialog = data;
1146 GtkWidget *b = g_object_get_data(G_OBJECT(dialog), "FUSE_ALLOW_EMPTY_PASSPHRASE");
1147 if (!b){
1148 return;
1149 }
1150 if (gtk_toggle_button_get_active(togglebutton)){
1151 gtk_widget_set_sensitive(b, TRUE);
1152 } else {
1153 gtk_widget_set_sensitive(b, FALSE );
1154 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b), FALSE);
1155 }
1156 }
1157
1158
1159 static
1160 gint
make_absolute(GtkWidget * in_entry,GdkEventKey * event,gpointer data)1161 make_absolute (GtkWidget * in_entry, GdkEventKey * event, gpointer data){
1162 const gchar *c = gtk_entry_get_text (GTK_ENTRY(in_entry));
1163 if (c && g_path_is_absolute(c)) return FALSE;
1164 gchar *a = g_strconcat("/", c, NULL);
1165 gtk_entry_set_text(GTK_ENTRY(in_entry), a);
1166
1167 g_free(a);
1168 gtk_editable_set_position (GTK_EDITABLE(in_entry), strlen(a));
1169 return FALSE;
1170 }
1171
1172 static
1173 gint
on_key_press(GtkWidget * in_entry,GdkEventKey * event,gpointer data)1174 on_key_press (GtkWidget * in_entry, GdkEventKey * event, gpointer data){
1175 GtkWidget *dialog = data;
1176 const gchar *url_template = g_object_get_data(G_OBJECT(data), "url_template");
1177 GtkWidget *entry;
1178 entry = g_object_get_data(G_OBJECT(dialog), "FUSE_COMPUTER");
1179 if (!entry) entry = g_object_get_data(G_OBJECT(dialog), "OBEX_NAME");
1180 gchar *host;
1181 if (entry) {
1182 const gchar *c = gtk_entry_get_text (GTK_ENTRY(entry));
1183 if (!c || !strlen(c)){
1184 host = g_strdup("");
1185 } else {
1186 host = g_strdup(c);
1187 }
1188 } else {
1189 DBG("No host name defined in function fuse_common.c:on_key_press()\n");
1190 host = g_strdup("");
1191 }
1192
1193
1194 gchar *rpath=NULL;
1195 entry = g_object_get_data(G_OBJECT(dialog), "FUSE_REMOTE_PATH");
1196 if (entry) {
1197 const gchar *c = gtk_entry_get_text (GTK_ENTRY(entry));
1198 if (!c || !strlen(c)){
1199 rpath = g_strdup("/");
1200 } else {
1201 if (c[0] != '/') rpath = g_strconcat("/", c, NULL);
1202 else rpath = g_strdup(c);
1203 }
1204 }
1205
1206 gchar *login=NULL;
1207 entry = g_object_get_data(G_OBJECT(dialog), "FUSE_LOGIN");
1208 if (entry) {
1209 const gchar *c = gtk_entry_get_text (GTK_ENTRY(entry));
1210 if (c && strlen(c)){
1211 login = g_strdup(c);
1212 }
1213 }
1214
1215 gchar *url;
1216 if (login) {
1217 url = g_strdup_printf("%s://%s@%s%s", url_template, login, host,
1218 (rpath)?rpath:"");
1219 } else {
1220 url = g_strdup_printf("%s://%s%s", url_template, host,
1221 (rpath)?rpath:"");
1222 }
1223 entry = g_object_get_data(G_OBJECT(dialog), "FUSE_URL");
1224
1225 gtk_entry_set_text(GTK_ENTRY(entry), url);
1226 g_free(host);
1227 g_free(rpath);
1228 g_free(url);
1229 return FALSE;
1230 }
1231
1232 GKeyFile *
fuse_load_keyfile(void)1233 fuse_load_keyfile(void){
1234 GKeyFile *key_file=NULL;
1235 key_file = g_key_file_new ();
1236 gchar *file = g_build_filename(FUSE_KEY_FILE, NULL);
1237 if (!g_key_file_load_from_file (key_file, file, 0, NULL)){
1238 g_key_file_free(key_file);
1239 key_file=NULL;
1240 }
1241 g_free(file);
1242 return key_file;
1243 }
1244
1245 static void *
fuse_init_dialog_f(gpointer data)1246 fuse_init_dialog_f(gpointer data){
1247 fuse_data_t *fuse_data_p = data;
1248 rfm_global_t *rfm_global_p = rfm_global();
1249 GtkWidget *dialog;
1250
1251
1252 dialog = gtk_dialog_new ();
1253 if (fuse_data_p->widgets_p) {
1254 g_object_set_data(G_OBJECT(dialog),
1255 "widgets_p", fuse_data_p->widgets_p);
1256 view_t *view_p=fuse_data_p->widgets_p->view_p;
1257 if(view_p && view_p->flags.type == DESKVIEW_TYPE) {
1258 gtk_window_set_keep_above (GTK_WINDOW(dialog), TRUE);
1259 gtk_window_stick (GTK_WINDOW(dialog));
1260 } else {
1261 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
1262 gtk_window_set_transient_for (GTK_WINDOW (dialog),
1263 GTK_WINDOW (rfm_global_p->window));
1264 }
1265 } else {
1266 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
1267 }
1268
1269 gtk_window_set_type_hint(GTK_WINDOW(dialog), GDK_WINDOW_TYPE_HINT_DIALOG);
1270
1271 GtkWidget *hbox = rfm_hbox_new (FALSE, 2);
1272 gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area(GTK_DIALOG (dialog))), hbox, FALSE, FALSE, 0);
1273 gtk_widget_show(hbox);
1274
1275 GdkPixbuf *pixbuf;
1276 pixbuf=rfm_get_pixbuf("xffm/stock_dialog-question", 24);
1277 GtkWidget *image=gtk_image_new_from_pixbuf(pixbuf);
1278 g_object_unref(pixbuf);
1279 gtk_widget_show(image);
1280 gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
1281
1282 gchar *text = g_strconcat(_("Options:"), " ",
1283 fuse_data_p->info1, "\n\n",
1284 fuse_data_p->info2, NULL);
1285
1286
1287 /* GtkWidget *label = gtk_label_new("");
1288 gtk_label_set_markup(GTK_LABEL(label), text);
1289 g_free(text);
1290 gtk_widget_show(label);
1291 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);*/
1292
1293 GtkWidget *labelview = gtk_text_view_new();
1294 gtk_text_view_set_editable (GTK_TEXT_VIEW(labelview), FALSE);
1295 gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW(labelview), FALSE);
1296 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW(labelview), GTK_WRAP_WORD);
1297 GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(labelview));
1298 GtkTextIter iter;
1299 gtk_text_buffer_get_start_iter (buffer, &iter);
1300 gtk_text_buffer_insert (buffer,&iter, text, -1);
1301
1302 g_free(text);
1303 gtk_widget_show(labelview);
1304 gtk_box_pack_start (GTK_BOX (hbox), labelview, TRUE, TRUE, 0);
1305
1306
1307 //GtkWidget *tbox = gtk_dialog_get_content_area (GTK_DIALOG(dialog));
1308 GtkWidget *tbox = rfm_vbox_new(FALSE, 0);
1309 gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG(dialog))), tbox, FALSE, FALSE, 0);
1310 GtkWidget *notebook = gtk_notebook_new ();
1311 g_object_set_data(G_OBJECT(dialog), "notebook", notebook);
1312 // gtk_notebook_set_tab_pos ((gtknotebook *)notebook, gtk_pos_bottom);
1313 gtk_notebook_popup_enable (GTK_NOTEBOOK(notebook));
1314 gtk_notebook_set_scrollable (GTK_NOTEBOOK(notebook), TRUE);
1315 g_object_set (notebook,
1316 "enable-popup", TRUE,
1317 "can-focus", FALSE,
1318 "scrollable", TRUE,
1319 "show-border", FALSE,
1320 "show-tabs",
1321 TRUE, "tab-pos",
1322 GTK_POS_TOP, NULL);
1323
1324
1325 gtk_box_pack_start (GTK_BOX (tbox), notebook, TRUE, TRUE, 0);
1326 GtkWidget *vbox = rfm_vbox_new (FALSE, 0);
1327 g_object_set_data(G_OBJECT(dialog), "vbox", vbox);
1328 gtk_widget_show(vbox);
1329
1330 GtkWidget *tab_label = gtk_label_new(_("Login"));
1331 GtkWidget *menu_label = gtk_label_new(_("Login"));
1332
1333 gtk_notebook_insert_page_menu (GTK_NOTEBOOK(notebook), vbox, tab_label, menu_label, 0);
1334 gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK(notebook), vbox, TRUE);
1335
1336 //get action area deprecated... whatever.
1337 //GtkWidget *action_area = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
1338 GtkWidget *action_area = rfm_hbox_new(FALSE, 1);
1339 gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
1340 action_area, FALSE, FALSE, 0);
1341 gtk_widget_show(action_area);
1342
1343
1344
1345 GtkWidget *button = rfm_dialog_button ("xffm/stock_no", _("Cancel"));
1346 gtk_box_pack_start (GTK_BOX (action_area), button, FALSE, FALSE, 0);
1347 //gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, GTK_RESPONSE_NO);
1348 g_object_set_data (G_OBJECT (dialog), "action_FALSE_button", button);
1349
1350
1351 button = rfm_dialog_button ("xffm/stock_save", _("Save"));
1352 g_object_set_data (G_OBJECT (dialog), "action_TRUE_button", button);
1353 gtk_box_pack_start (GTK_BOX (action_area), button, FALSE, FALSE, 0);
1354 //gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, GTK_RESPONSE_APPLY);
1355
1356 button = rfm_dialog_button ("xffm/stock_yes", _("Mount"));
1357 g_object_set_data (G_OBJECT (dialog), "action_MOUNT_button", button);
1358 gtk_box_pack_start (GTK_BOX (action_area), button, FALSE, FALSE, 0);
1359 //gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, GTK_RESPONSE_YES);
1360
1361 gtk_window_set_resizable (GTK_WINDOW(dialog), TRUE);
1362
1363 GKeyFile *key_file = (fuse_data_p->url)? fuse_load_keyfile(): NULL;
1364
1365 g_object_set_data(G_OBJECT(dialog), "url", (void *)(fuse_data_p->url));
1366 g_object_set_data(G_OBJECT(dialog), "key_file", key_file);
1367 return dialog;
1368
1369 }
1370
1371 GtkWidget *
fuse_init_dialog(fuse_data_t * fuse_data_p)1372 fuse_init_dialog(fuse_data_t *fuse_data_p){
1373 GtkWidget *w = rfm_context_function(fuse_init_dialog_f, fuse_data_p);
1374 return w;
1375 }
1376
1377 GtkWidget *
fuse_add_entry(fuse_data_t * fuse_data_p)1378 fuse_add_entry(fuse_data_t *fuse_data_p){
1379
1380 GtkWidget *vbox = g_object_get_data(G_OBJECT(fuse_data_p->dialog), "vbox");
1381 const gchar *url = g_object_get_data(G_OBJECT(fuse_data_p->dialog), "url");
1382 GKeyFile *key_file = g_object_get_data(G_OBJECT(fuse_data_p->dialog), "key_file");
1383
1384 const gchar *separator=" ";
1385 if (fuse_data_p->item_string && !strchr(fuse_data_p->item_string, ':')){
1386 separator = ": ";
1387 }
1388
1389 GtkWidget *hbox = fuse_make_entry_box(fuse_data_p->dialog, fuse_data_p->item_string, fuse_data_p->item_id, separator, TRUE, on_key_press);
1390 if (strcmp(fuse_data_p->item_id, "FUSE_MOUNT_POINT")==0){
1391 g_object_set_data(G_OBJECT(fuse_data_p->dialog), "FUSE_MOUNT_POINT_BOX", hbox);
1392 }
1393
1394
1395 GtkWidget *entry = g_object_get_data(G_OBJECT(fuse_data_p->dialog), fuse_data_p->item_id);
1396 if (strcmp(fuse_data_p->item_id, "FUSE_REMOTE_PATH")==0) {
1397 g_signal_connect(G_OBJECT(entry), "key-release-event", G_CALLBACK(make_absolute), fuse_data_p->dialog);
1398 }
1399 gchar *default_value=NULL;
1400 gchar *user=NULL;
1401 gchar *computer=NULL;
1402 gchar *remote_path=NULL;
1403 gchar *u = NULL;
1404 if (url){
1405 u = g_strdup(url);
1406 gchar *p = strstr(u, "://");
1407 if (p) {
1408 p = p+strlen("://");
1409 if (strchr(p,'/')){
1410 *strchr(p,'/') = 0;
1411 if (strchr(p,'@')) {
1412 user = g_strdup(p);
1413 *strchr(user,'@') = 0;
1414 p = strchr(p,'@') + 1;
1415 }
1416 computer = g_strdup(p);
1417 remote_path = g_strdup_printf("/%s",p + strlen(p) + 1);
1418 }
1419 }
1420 g_free(u);
1421 }
1422
1423 if (strcmp(fuse_data_p->item_id, "FUSE_COMPUTER")==0) {
1424 default_value = g_strdup(computer);
1425 } else if (strcmp(fuse_data_p->item_id, "FUSE_REMOTE_PATH")==0) {
1426 default_value = g_strdup(remote_path);
1427 }
1428 if (strcmp(fuse_data_p->item_id, "FUSE_LOGIN")==0) {
1429 if (user) {
1430 default_value = g_strdup(user);
1431 } else {
1432 if (getenv("USER"))
1433 default_value = g_strdup(getenv("USER"));
1434 else if (getenv("LOGNAME"))
1435 default_value = g_strdup(getenv("LOGNAME"));
1436 else default_value = g_strdup(getenv("GUEST"));
1437 }
1438 }
1439 g_free(user);
1440 g_free(computer);
1441 g_free(remote_path);
1442 if (url && strcmp(fuse_data_p->item_id, "FUSE_MOUNT_POINT")==0) {
1443 default_value = rfm_default_url_mount_point(url);
1444 }
1445
1446 if (!default_value) default_value=g_strdup("");
1447 fuse_set_entry(entry, key_file, url, fuse_data_p->item_id, default_value);
1448 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1449 g_free(default_value);
1450 return hbox;
1451 }
1452
1453
1454 gchar *
fuse_get_combo_text(fuse_data_t * fuse_data_p)1455 fuse_get_combo_text(fuse_data_t *fuse_data_p){
1456 GtkWidget *combo = g_object_get_data(G_OBJECT(fuse_data_p->dialog), fuse_data_p->item_id);
1457 if (!combo) return NULL;
1458 #if GTK_MAJOR_VERSION==2 && GTK_MINOR_VERSION<24
1459 gchar *string = gtk_combo_box_get_active_text (GTK_COMBO_BOX(combo));
1460 #else
1461 gchar *string = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT(combo));
1462 #endif
1463 return string;
1464 }
1465
1466 GtkWidget *
fuse_add_combo(fuse_data_t * fuse_data_p)1467 fuse_add_combo(fuse_data_t *fuse_data_p){
1468 GtkWidget *hbox = rfm_hbox_new(FALSE, 0);
1469 GtkWidget *vbox = g_object_get_data(G_OBJECT(fuse_data_p->dialog), "vbox");
1470 const gchar *url = g_object_get_data(G_OBJECT(fuse_data_p->dialog), "url");
1471 GKeyFile *key_file = g_object_get_data(G_OBJECT(fuse_data_p->dialog), "key_file");
1472
1473 gchar *full_text;
1474 GtkWidget *label = gtk_label_new("");
1475 if (strchr(fuse_data_p->item_string, ':')){
1476 full_text = g_strconcat(fuse_data_p->item_string, " ", NULL);
1477 } else {
1478 full_text = g_strconcat(fuse_data_p->item_string, ": ", NULL);
1479 }
1480 gtk_label_set_markup(GTK_LABEL(label), full_text);
1481 g_free(full_text);
1482
1483 #if GTK_MAJOR_VERSION==2 && GTK_MINOR_VERSION<24
1484 // this is deprecated...
1485 GtkWidget *combobox = gtk_combo_box_new_text ();
1486 #else
1487 GtkWidget *combobox = gtk_combo_box_text_new ();
1488 #endif
1489
1490 g_object_set_data(G_OBJECT(fuse_data_p->dialog), fuse_data_p->item_id, combobox);
1491 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1492 gtk_box_pack_start (GTK_BOX (hbox), combobox, TRUE, TRUE, 0);
1493
1494 // Set default combo value.
1495 gchar *pre_set=NULL;
1496 if (key_file && url) {
1497 pre_set = g_key_file_get_value(key_file, url, fuse_data_p->item_id, NULL);
1498 }
1499
1500 #if GTK_MAJOR_VERSION==2 && GTK_MINOR_VERSION<24
1501 if (pre_set){
1502 gtk_combo_box_prepend_text(GTK_COMBO_BOX(combobox), pre_set);
1503 } else if (fuse_data_p->default_value){
1504 gtk_combo_box_prepend_text(GTK_COMBO_BOX(combobox), fuse_data_p->default_value);
1505 } else {
1506 gtk_widget_set_sensitive(hbox, FALSE);
1507 }
1508 #else
1509 if (pre_set){
1510 gtk_combo_box_text_prepend_text(GTK_COMBO_BOX_TEXT(combobox),pre_set);
1511 gtk_combo_box_set_active (GTK_COMBO_BOX(combobox), 0);
1512 } else if (fuse_data_p->default_value){
1513 gtk_combo_box_text_prepend_text(GTK_COMBO_BOX_TEXT(combobox),fuse_data_p->default_value);
1514 } else {
1515 gtk_widget_set_sensitive(combobox, FALSE);
1516 }
1517
1518 #endif
1519 g_free(pre_set);
1520
1521 gtk_widget_show(hbox);
1522 gtk_widget_show(label);
1523 gtk_widget_show(combobox);
1524 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1525
1526 return hbox;
1527 }
1528
1529 GtkWidget *
fuse_add_check(fuse_data_t * fuse_data_p)1530 fuse_add_check(fuse_data_t *fuse_data_p){
1531 GtkWidget *vbox = g_object_get_data(G_OBJECT(fuse_data_p->dialog), "vbox");
1532 GtkWidget *hbox = rfm_hbox_new(FALSE, 0);
1533
1534
1535 GtkWidget *check;
1536 if (strcmp(fuse_data_p->item_id, "FUSE_BROADBAND")==0) {
1537 check = fuse_make_check_box(fuse_data_p->dialog,
1538 fuse_data_p->item_string,
1539 fuse_data_p->item_id,
1540 toggle_broad);
1541 } else if (strcmp(fuse_data_p->item_id, "FUSE_SECURE_SHELL_KEY")==0) {
1542 check = fuse_make_check_box(fuse_data_p->dialog,
1543 fuse_data_p->item_string,
1544 fuse_data_p->item_id,
1545 toggle_ssh);
1546 }else {
1547 check = fuse_make_check_box(fuse_data_p->dialog,
1548 fuse_data_p->item_string,
1549 fuse_data_p->item_id,
1550 NULL);
1551 }
1552 gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
1553 GtkWidget *label = gtk_label_new("");
1554 if (fuse_data_p->extra_text) {
1555 gchar *c = g_strdup_printf("<i>(%s)</i>", fuse_data_p->extra_text);
1556 gtk_label_set_markup(GTK_LABEL(label), c);
1557 g_free(c);
1558 }
1559 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1560 gtk_widget_show(label);
1561 gtk_widget_show(hbox);
1562 GKeyFile *key_file = g_object_get_data(G_OBJECT(fuse_data_p->dialog),
1563 "key_file");
1564 const gchar *url = g_object_get_data(G_OBJECT(fuse_data_p->dialog),
1565 "url");
1566 fuse_set_check_button_state(fuse_data_p->dialog, key_file, url,
1567 fuse_data_p->item_id, fuse_data_p->item_id,
1568 fuse_data_p->default_state);
1569
1570 if (strcmp(fuse_data_p->item_id, "FUSE_ALLOW_EMPTY_PASSPHRASE")==0){
1571 GtkWidget *t = g_object_get_data(G_OBJECT(fuse_data_p->dialog),
1572 "FUSE_SECURE_SHELL_KEY");
1573 if (t && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(t))){
1574 gtk_widget_set_sensitive(check, TRUE);
1575 } else if (t) {
1576 gtk_widget_set_sensitive(check, FALSE);
1577 }
1578
1579 }
1580 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1581 return hbox;
1582 }
1583
1584 void *
fuse_add_option_page(fuse_data_t * fuse_data_p)1585 fuse_add_option_page(fuse_data_t *fuse_data_p) {
1586 GKeyFile *key_file = g_object_get_data(G_OBJECT(fuse_data_p->dialog),
1587 "key_file");
1588 const gchar *url = g_object_get_data(G_OBJECT(fuse_data_p->dialog),
1589 "url");
1590
1591 GtkWidget *vbox = group_options_box(fuse_data_p->dialog,
1592 fuse_data_p->options_p, key_file, url, fuse_data_p->flag_id);
1593 gtk_widget_show(vbox);
1594 GtkWidget *tab_label = gtk_label_new(fuse_data_p->label);
1595 GtkWidget *menu_label = gtk_label_new(fuse_data_p->label);
1596 GtkWidget *notebook = g_object_get_data(G_OBJECT(fuse_data_p->dialog),
1597 "notebook");
1598 gtk_notebook_append_page_menu (GTK_NOTEBOOK(notebook), vbox, tab_label,
1599 menu_label);
1600 gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK(notebook), vbox, TRUE);
1601 return NULL;
1602 }
1603
1604 void *
fuse_reset_url_field(fuse_data_t * fuse_data_p)1605 fuse_reset_url_field(fuse_data_t *fuse_data_p){
1606 if (!fuse_data_p) return NULL;
1607 GKeyFile *key_file = g_object_get_data(G_OBJECT(fuse_data_p->dialog),
1608 "key_file");
1609
1610 if (key_file) {
1611 on_key_press(NULL, NULL, fuse_data_p->dialog);
1612 g_key_file_free(key_file);
1613 g_object_set_data(G_OBJECT(fuse_data_p->dialog), "key_file", NULL);
1614 }
1615 return NULL;
1616 }
1617
1618
1619 fuse_data_t *
fuse_data_new(fuse_data_t * fuse_data_p)1620 fuse_data_new(fuse_data_t *fuse_data_p){
1621 if (fuse_data_p == NULL) {
1622 fuse_data_p = (fuse_data_t *)malloc(sizeof(fuse_data_t));
1623 if (!fuse_data_p){
1624 g_error("fuse_item_data_new(): cannot malloc item_data_p\n");
1625 }
1626 }
1627 memset(fuse_data_p, 0, sizeof(fuse_data_t));
1628 return fuse_data_p;
1629 }
1630
1631
1632 xfdir_t *
fuse_xfdir(void ** argv)1633 fuse_xfdir (void **argv){
1634 gint argc = 0;
1635 while (argv[argc]) argc++;
1636 if (argc < 6) g_error("fuse_xfdir(): insufficient arguments\n");
1637 return fuse_xfdir_get(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
1638 }
1639
1640 const gchar *
fuse_icon(void ** argv)1641 fuse_icon (void **argv){
1642 gint argc = 0;
1643 while (argv[argc]) argc++;
1644 if (argc < 4) g_error("fuse_icon(): insufficient arguments\n");
1645 return fuse_icon_id(argv[0], argv[1], argv[2], argv[3]);
1646 }
1647
1648 void *
fuse_popup(void ** argv)1649 fuse_popup(void **argv){
1650 gint argc = 0;
1651 while (argv[argc]) argc++;
1652 TRACE( "fuse_popup...\n");
1653 if (argc < 3){
1654 TRACE( "fuse_popup(): insufficient arguments\n");
1655 return NULL;
1656 }
1657
1658 return fuse_private_popup(argv[0], argv[1], argv[2], argv[3]);
1659 }
1660
1661 gboolean
fuse_mkdir(const gchar * mount_point)1662 fuse_mkdir(const gchar *mount_point) {
1663 TRACE( "fuse_mkdir %s\n", mount_point);
1664 if (g_file_test(mount_point, G_FILE_TEST_IS_DIR)) return TRUE;
1665 widgets_t * widgets_p = rfm_get_widget("widgets_p");
1666 if (g_file_test(mount_point, G_FILE_TEST_EXISTS)) {
1667 TRACE( "fuse_mkdir 1\n");
1668 rfm_threaded_diagnostics(widgets_p, "xffm/stock_dialog-error",NULL);
1669 gchar *text = g_strdup_printf(_("The file with pathname \"%s\" is not a directory."), mount_point);
1670 rfm_threaded_diagnostics(widgets_p, "xffm/stock_dialog-error",text);
1671 g_free(text);
1672 return FALSE;
1673 }
1674 if (g_mkdir_with_parents(mount_point, 0700) < 0) {
1675 // XXX try sudo here (with dialog warning)...
1676 TRACE( "fuse_mkdir 21\n");
1677 return FALSE;
1678 }
1679 return TRUE;
1680 }
1681
1682 void *
fuse_test_ini_file(void * p)1683 fuse_test_ini_file(void *p){
1684 widgets_t * widgets_p = rfm_get_widget("widgets_p");
1685
1686 static gint count=1;
1687
1688 struct stat st;
1689 gchar *file = g_build_filename(FUSE_KEY_FILE, NULL);
1690 if (stat(file, &st) < 0 ) return NULL;
1691 g_free(file);
1692 gint mtime = GPOINTER_TO_INT(
1693 g_object_get_data(G_OBJECT(widgets_p->paper), "fuse_mtime")
1694 );
1695
1696 if (mtime == st.st_mtime) return NULL;
1697 g_object_set_data(G_OBJECT(widgets_p->paper), "fuse_mtime",
1698 GINT_TO_POINTER(st.st_mtime));
1699
1700 return GINT_TO_POINTER (++count);
1701 }
1702
1703
1704 typedef struct fuse_dialog_t {
1705 view_t *view_p;
1706 GMutex *mutex;
1707 GCond *signal;
1708 } fuse_dialog_t;
1709
1710 static void *
hold_monitor(void * data)1711 hold_monitor(void *data){
1712 fuse_dialog_t *fuse_dialog_p = data;
1713 view_t *view_p = fuse_dialog_p->view_p;
1714 g_mutex_lock (fuse_dialog_p->mutex);
1715 rfm_rw_lock_reader_lock (&(view_p->mutexes.monitor_lock));
1716 g_cond_wait(fuse_dialog_p->signal, fuse_dialog_p->mutex);
1717 rfm_rw_lock_reader_unlock (&(view_p->mutexes.monitor_lock));
1718 g_mutex_unlock (fuse_dialog_p->mutex);
1719 rfm_mutex_free(fuse_dialog_p->mutex);
1720 rfm_cond_free(fuse_dialog_p->signal);
1721 g_free(fuse_dialog_p);
1722 return NULL;
1723 }
1724
1725 GCond *
fuse_hold_monitor(void)1726 fuse_hold_monitor(void){
1727 widgets_t * widgets_p = rfm_get_widget("widgets_p");
1728 fuse_dialog_t *fuse_dialog_p = (fuse_dialog_t *)malloc(sizeof(fuse_dialog_t));
1729 if (!fuse_dialog_p) g_error("malloc: %s\n", strerror(errno));
1730 rfm_mutex_init(fuse_dialog_p->mutex);
1731 rfm_cond_init(fuse_dialog_p->signal);
1732 fuse_dialog_p->view_p = widgets_p->view_p;
1733 rfm_view_thread_create(fuse_dialog_p->view_p, hold_monitor, fuse_dialog_p, "hold_monitor");
1734 return fuse_dialog_p->signal;
1735 }
1736
1737
1738 static void
button_ok(GtkButton * button,gpointer data)1739 button_ok (GtkButton * button, gpointer data) {
1740 gint *response = data;
1741 *response = GTK_RESPONSE_APPLY;
1742 gtk_main_quit();
1743 }
1744
1745 static void
button_mount(GtkEntry * entry,gpointer data)1746 button_mount (GtkEntry * entry, gpointer data) {
1747 gint *response = data;
1748 *response = GTK_RESPONSE_YES;
1749 gtk_main_quit();
1750 }
1751
1752 static void
button_cancel(GtkButton * button,gpointer data)1753 button_cancel (GtkButton * button, gpointer data) {
1754 gint *response = data;
1755 *response = GTK_RESPONSE_CANCEL;
1756 gtk_main_quit();
1757 }
1758
1759
1760 static gboolean
response_delete(GtkWidget * dialog,GdkEvent * event,gpointer data)1761 response_delete(GtkWidget *dialog, GdkEvent *event, gpointer data){
1762 gint *response = data;
1763 *response = GTK_RESPONSE_CANCEL;
1764 gtk_main_quit();
1765 return TRUE;
1766 }
1767
1768 static void *
confirm_host_f(gpointer data)1769 confirm_host_f (gpointer data){
1770 void **arg = data;
1771 fuse_data_t *(*dialog_f)(const gchar *url) = arg[0];
1772 const gchar *url = arg[1];
1773 const gchar *module_name = arg[2];
1774 g_free(arg);
1775 widgets_t * widgets_p = rfm_get_widget("widgets_p");
1776 GCond *signal = fuse_hold_monitor();
1777 fuse_data_t *fuse_data_p = (*dialog_f) (url);
1778 if(!fuse_data_p || !fuse_data_p->dialog){
1779 return GINT_TO_POINTER(FALSE);
1780 }
1781 gint response = GTK_RESPONSE_CANCEL;
1782 GtkNotebook *notebook =
1783 g_object_get_data(G_OBJECT(fuse_data_p->dialog), "notebook");
1784 gtk_notebook_set_current_page(notebook, 0);
1785
1786 GtkWidget *button;
1787
1788 button = g_object_get_data(G_OBJECT(fuse_data_p->dialog), "action_TRUE_button");
1789 g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (button_ok), &response);
1790 button = g_object_get_data(G_OBJECT(fuse_data_p->dialog), "action_FALSE_button");
1791 g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (button_cancel), &response);
1792 button = g_object_get_data(G_OBJECT(fuse_data_p->dialog), "action_MOUNT_button");
1793 g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (button_mount), &response);
1794
1795 g_signal_connect (G_OBJECT (fuse_data_p->dialog), "delete-event", G_CALLBACK (response_delete), &response);
1796 retry:;
1797
1798 gtk_widget_show_all (fuse_data_p->dialog);
1799 gtk_main();
1800 gtk_widget_hide (fuse_data_p->dialog);
1801
1802 gboolean retval;
1803 if(response == GTK_RESPONSE_YES || response == GTK_RESPONSE_APPLY){
1804 retval = TRUE;
1805 //gchar *new_url = accept(fuse_data_p, url);
1806 gchar *new_url = rfm_rational(PLUGIN_DIR, module_name, fuse_data_p, (void*) url, "accept");
1807 if (!new_url) {
1808 goto retry;
1809 }
1810 if(response == GTK_RESPONSE_YES) {
1811 TRACE( "%s: mount_url\n", module_name);
1812 retval = GPOINTER_TO_INT(rfm_rational(PLUGIN_DIR, module_name, widgets_p, new_url, "mount_url"));
1813 }
1814 view_t *view_p = widgets_p->view_p;
1815 record_entry_t *t_en = rfm_copy_entry(view_p->en);
1816 if(!rodent_refresh (widgets_p, t_en)) {
1817 rfm_destroy_entry(t_en);
1818 }
1819 g_free(new_url);
1820 } else {
1821 retval = FALSE;
1822 }
1823 gtk_widget_destroy (fuse_data_p->dialog);
1824 g_cond_signal(signal);
1825 return GINT_TO_POINTER(retval);
1826 }
1827
1828 static gboolean
confirm_host(fuse_data_t * (* dialog_f)(const gchar * url),const gchar * url,const gchar * module_name)1829 confirm_host (fuse_data_t *(*dialog_f)(const gchar *url), const gchar *url, const gchar *module_name){
1830 void **arg = (void **)malloc(3*sizeof(void *));
1831 if (!arg) g_error("malloc: %s\n", strerror(errno));
1832 arg [0] = dialog_f;
1833 arg [1] = (void *)url;
1834 arg [2] = (void *)module_name;
1835 return GPOINTER_TO_INT(rfm_context_function(confirm_host_f, arg));
1836
1837 }
1838
1839 void *
g_module_check_init(GModule * module)1840 g_module_check_init(GModule *module){
1841 NOOP("domain=(no gettext support)");
1842 GMutex *mutex = rfm_get_widget("fuse_popup_mutex");
1843 if (!mutex){
1844 rfm_mutex_init(mutex);
1845 rfm_set_widget(mutex, "fuse_popup_mutex");
1846 }
1847 rfm_view_thread_create(NULL, thread_popup, NULL, "fuse-common:thread_popup");
1848 return NULL;
1849 }
1850
1851