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