5 #include <Ecore_Getopt.h>
7 #include <Efreet_Mime.h>
12 xdg_defaults_get(const char *path, const char *mime)
17 if (access(path, R_OK) != 0)
20 ini = efreet_ini_new(path);
24 efreet_ini_section_set(ini, "Default Applications");
25 str = eina_stringshare_add(efreet_ini_string_get(ini, mime));
31 static Efreet_Desktop *
32 xdg_desktop_from_string_list(const char *strlist)
34 Efreet_Desktop *desktop = NULL;
35 char **array = eina_str_split(strlist, ";", 0);
41 for (i = 0; array[i] != NULL; i++)
43 const char *name = array[i];
45 desktop = efreet_desktop_new(name);
47 desktop = efreet_util_desktop_file_id_find(name);
51 if (desktop->exec) break;
54 efreet_desktop_free(desktop);
66 static Efreet_Desktop *
67 desktop_first_free_others(Eina_List *lst)
69 Efreet_Desktop *desktop, *d;
74 efreet_desktop_ref(desktop);
76 EINA_LIST_FREE(lst, d)
77 efreet_desktop_free(d);
82 static Efreet_Desktop *
83 handler_find(const char *mime)
85 Efreet_Desktop *desktop = NULL;
89 snprintf(path, sizeof(path), "%s/applications/defaults.list",
90 efreet_data_home_get());
91 name = xdg_defaults_get(path, mime);
94 const Eina_List *n, *dirs = efreet_data_dirs_get();
96 EINA_LIST_FOREACH(dirs, n, d)
98 snprintf(path, sizeof(path), "%s/applications/defaults.list", d);
99 name = xdg_defaults_get(path, mime);
107 desktop = xdg_desktop_from_string_list(name);
108 eina_stringshare_del(name);
112 desktop = desktop_first_free_others(efreet_util_desktop_mime_list(mime));
118 get_command(void *data, Efreet_Desktop *desktop __UNUSED__, char *command, int remaining __UNUSED__)
120 Eina_List **p_cmd = data;
121 *p_cmd = eina_list_append(*p_cmd, command);
126 mime_open(const char *mime, const char * const *argv, int argc)
128 Efreet_Desktop *desktop = handler_find(mime);
129 Eina_List *files = NULL;
130 Eina_List *cmds = NULL;
136 for (; argc > 0; argc--, argv++)
137 files = eina_list_append(files, *argv);
139 efreet_desktop_command_get(desktop, files, get_command, &cmds);
141 if (!cmds) ret = NULL;
146 ret = calloc(eina_list_count(cmds) + 1, sizeof(char *));
150 EINA_LIST_FREE(cmds, c)
152 ret[i] = c; /* was strdup by efreet_desktop_command_get() */
159 EINA_LIST_FREE(cmds, c)
164 eina_list_free(files);
170 append_single_quote_escaped(Eina_Strbuf *b, const char *str)
172 const char *itr = str;
173 for (; *itr != '\0'; itr++)
176 eina_strbuf_append_char(b, *itr);
178 eina_strbuf_append(b, "\\'");
183 single_command_open(const char *command, const char * const *argv, int argc)
185 char **ret = calloc(2, sizeof(char *));
192 b = eina_strbuf_new();
198 eina_strbuf_append(b, command);
200 for (i = 0; i < argc; i++)
202 Eina_Bool has_space = EINA_FALSE;
203 int s_idx_sq = -1, s_idx_dq = -1;
204 int l_idx_sq = -1, l_idx_dq = -1;
208 for (idx = 0, itr = argv[i]; *itr != '\0'; itr++, idx++)
210 if ((!has_space) && (isspace(*itr)))
211 has_space = EINA_TRUE;
229 eina_strbuf_append_char(b, ' ');
231 ((s_idx_sq == 0) && (l_idx_sq == idx)) ||
232 ((s_idx_dq == 0) && (l_idx_dq == idx)))
233 eina_strbuf_append(b, argv[i]);
237 if ((s_idx_sq >= 0) && (s_idx_dq < 0))
239 else if ((s_idx_sq < 0) && (s_idx_dq >= 0))
246 eina_strbuf_append_char(b, c);
247 eina_strbuf_append(b, argv[i]);
248 eina_strbuf_append_char(b, c);
252 eina_strbuf_append_char(b, '\'');
253 append_single_quote_escaped(b, argv[i]);
254 eina_strbuf_append_char(b, '\'');
259 ret[0] = eina_strbuf_string_steal(b);
265 static Efreet_Desktop *
266 _terminal_get(const char *defaults_list)
268 Efreet_Desktop *tdesktop = NULL;
272 ini = efreet_ini_new(defaults_list);
273 if ((ini) && (ini->data) &&
274 (efreet_ini_section_set(ini, "Default Applications")) &&
277 s = efreet_ini_string_get(ini, "x-scheme-handler/terminal");
278 if (s) tdesktop = efreet_util_desktop_file_id_find(s);
280 if (ini) efreet_ini_free(ini);
287 const char *terms[] =
289 "terminology.desktop",
292 "gnome-terimnal.desktop",
297 char buf[PATH_MAX], **ret;
298 Efreet_Desktop *tdesktop = NULL, *td;
302 s = efreet_data_home_get();
305 snprintf(buf, sizeof(buf), "%s/applications/defaults.list", s);
306 tdesktop = _terminal_get(buf);
308 if (tdesktop) goto have_desktop;
309 EINA_LIST_FOREACH(efreet_data_dirs_get(), l, s)
311 snprintf(buf, sizeof(buf), "%s/applications/defaults.list", s);
312 tdesktop = _terminal_get(buf);
313 if (tdesktop) goto have_desktop;
316 for (i = 0; terms[i]; i++)
318 tdesktop = efreet_util_desktop_file_id_find(terms[i]);
319 if (tdesktop) goto have_desktop;
323 l = efreet_util_desktop_category_list("TerminalEmulator");
326 // just take first one since above list doesn't work.
328 EINA_LIST_FREE(l, td)
330 // free/unref the desktosp we are not going to use
331 if (td != tdesktop) efreet_desktop_free(td);
335 if (!tdesktop) return NULL;
339 efreet_desktop_free(tdesktop);
342 ret = malloc(sizeof(char *) * 2);
343 if (!ret) return NULL;
344 ret[0] = strdup(tdesktop->exec);
349 efreet_desktop_free(tdesktop);
352 efreet_desktop_free(tdesktop);
357 browser_open(const char * const *argv, int argc)
359 const char *env = getenv("BROWSER");
360 if (env) return single_command_open(env, argv, argc);
361 return mime_open("x-scheme-handler/http", argv, argc);
365 local_open(const char *path)
367 const char *mime = efreet_mime_type_get(path);
370 char **ret = mime_open(mime, &path, 1);
373 return single_command_open("enlightenment_filemanager", &path, 1);
376 fprintf(stderr, "ERROR: Could not get mime type for: %s\n", path);
381 protocol_open(const char *str)
383 Efreet_Uri *uri = efreet_uri_decode(str);
388 fprintf(stderr, "ERROR: Could not decode uri: %s\n", str);
393 fprintf(stderr, "ERROR: Could not get protocol from uri: %s\n", str);
394 else if (strcmp(uri->protocol, "file") == 0)
395 ret = local_open(uri->path);
399 snprintf(mime, sizeof(mime), "x-scheme-handler/%s", uri->protocol);
400 ret = mime_open(mime, &str, 1);
402 efreet_uri_free(uri);
406 static const struct type_mime {
410 /* {"browser", "x-scheme-handler/http"}, */
411 {"mail", "x-scheme-handler/mailto"},
412 /* {"terminal", NULL}, */
413 {"filemanager", "x-scheme-handler/file"},
414 {"image", "image/jpeg"},
415 {"video", "video/x-mpeg"},
416 {"music", "audio/mp3"},
420 static const char *type_choices[] = {
431 static const Ecore_Getopt options = {
432 "enlightenment_open",
433 "%prog [options] <file-or-folder-or-url>",
435 "(C) 2012 Gustavo Sverzut Barbieri and others",
437 "Opens the file using Enlightenment standards.",
440 ECORE_GETOPT_CHOICE('t', "type", "Choose program type to launch.",
442 ECORE_GETOPT_VERSION('V', "version"),
443 ECORE_GETOPT_COPYRIGHT('C', "copyright"),
444 ECORE_GETOPT_LICENSE('L', "license"),
445 ECORE_GETOPT_HELP('h', "help"),
446 ECORE_GETOPT_SENTINEL
451 main(int argc, char *argv[])
453 Eina_Bool quit_option = EINA_FALSE;
455 Ecore_Getopt_Value values[] = {
456 ECORE_GETOPT_VALUE_STR(type),
457 ECORE_GETOPT_VALUE_BOOL(quit_option),
458 ECORE_GETOPT_VALUE_BOOL(quit_option),
459 ECORE_GETOPT_VALUE_BOOL(quit_option),
460 ECORE_GETOPT_VALUE_BOOL(quit_option),
461 ECORE_GETOPT_VALUE_NONE
466 args = ecore_getopt_parse(&options, values, argc, argv);
469 fputs("ERROR: Could not parse command line options.\n", stderr);
472 if (quit_option) return EXIT_SUCCESS;
474 if ((type == NULL) && (args == argc))
476 fputs("ERROR: Missing file, directory or URL or --type.\n", stderr);
485 if (strcmp(type, "terminal") == 0)
486 cmds = terminal_open();
487 else if (strcmp(type, "browser") == 0)
488 cmds = browser_open((const char * const *)argv + args, argc - args);
491 const struct type_mime *itr;
493 for (itr = type_mimes; itr->type != NULL; itr++)
495 if (strcmp(type, itr->type) == 0)
497 cmds = mime_open(itr->mime,
498 (const char * const *)argv + args,
505 fprintf(stderr, "ERROR: type not supported %s\n", type);
510 else if (strstr(argv[args], "://"))
511 cmds = protocol_open(argv[args]);
513 cmds = local_open(argv[args]);
515 efreet_mime_shutdown();
519 /* No EFL, plain boring sequential system() calls */
525 int ret = EXIT_SUCCESS;
527 for (itr = cmds; *itr != NULL; itr++)
529 /* Question: should we execute them in parallel? */
530 int r = system(*itr);
532 fprintf(stderr, "ERROR: %s executing %s\n", strerror(errno),
535 if (r > 0) /* Question: should we stop the loop on first faiure? */