enlightenment/src/modules/fileman/e_mod_dbus.c

331 lines
8.6 KiB
C
Raw Normal View History

#include "e_mod_main.h"
static const char E_FILEMAN_BUS_NAME[] = "org.enlightenment.FileManager";
static const char E_FILEMAN_INTERFACE[] = "org.enlightenment.FileManager";
static const char E_FILEMAN_ERROR[] = "org.enlightenment.FileManager.Error";
static const char E_FILEMAN_PATH[] = "/org/enlightenment/FileManager";
typedef struct _E_Fileman_DBus_Daemon E_Fileman_DBus_Daemon;
struct _E_Fileman_DBus_Daemon
{
EDBus_Connection *conn;
EDBus_Service_Interface *iface;
};
static EDBus_Message * _e_fileman_dbus_daemon_open_directory_cb(const EDBus_Service_Interface *iface, const EDBus_Message *msg);
static EDBus_Message *_e_fileman_dbus_daemon_open_file_cb(const EDBus_Service_Interface *iface, const EDBus_Message *msg);
static EDBus_Message *
_e_fileman_dbus_daemon_error(const EDBus_Message *msg,
const char *error_msg)
{
return edbus_message_error_new(msg, E_FILEMAN_ERROR, error_msg);
}
static const EDBus_Method methods[] = {
{ "OpenDirectory", EDBUS_ARGS({"s", "directory"}), NULL,
_e_fileman_dbus_daemon_open_directory_cb },
{ "OpenFile", EDBUS_ARGS({"s", "file"}), NULL,
_e_fileman_dbus_daemon_open_file_cb },
{ }
};
static const EDBus_Service_Interface_Desc desc = {
E_FILEMAN_INTERFACE, methods
};
static void
_e_fileman_dbus_daemon_object_init(E_Fileman_DBus_Daemon *d)
{
d->iface = edbus_service_interface_register(d->conn, E_FILEMAN_PATH, &desc);
if (!d->iface)
{
fprintf(stderr, "ERROR: cannot add object to %s\n", E_FILEMAN_PATH);
return;
}
}
static void
_e_fileman_dbus_daemon_free(E_Fileman_DBus_Daemon *d)
{
if (d->iface)
edbus_service_object_unregister(d->iface);
if (d->conn)
edbus_connection_unref(d->conn);
free(d);
}
static EDBus_Message *
_e_fileman_dbus_daemon_open_directory_cb(const EDBus_Service_Interface *iface __UNUSED__,
const EDBus_Message *msg)
{
const char *directory = NULL, *p;
char *dev, *to_free = NULL;
E_Zone *zone;
if (!edbus_message_arguments_get(msg, "s", &directory))
{
fprintf(stderr, "Error: getting arguments of OpenDirectory call.\n");
return edbus_message_method_return_new(msg);
}
if ((!directory) || (directory[0] == '\0'))
return _e_fileman_dbus_daemon_error(msg, "no directory provided.");
zone = e_util_zone_current_get(e_manager_current_get());
if (!zone)
return _e_fileman_dbus_daemon_error(msg, "could not find a zone.");
if (strstr(directory, "://"))
{
Efreet_Uri *uri = efreet_uri_decode(directory);
directory = NULL;
if (uri)
{
if ((uri->protocol) && (strcmp(uri->protocol, "file") == 0))
directory = to_free = strdup(uri->path);
efreet_uri_free(uri);
}
if (!directory)
return _e_fileman_dbus_daemon_error(msg, "unsupported protocol");
}
p = strchr(directory, '/');
if (p)
{
int len = p - directory + 1;
dev = malloc(len + 1);
if (!dev)
{
free(to_free);
return _e_fileman_dbus_daemon_error(msg,
"could not allocate memory.");
}
memcpy(dev, directory, len);
dev[len] = '\0';
if ((dev[0] != '/') && (dev[0] != '~'))
dev[len - 1] = '\0'; /* remove trailing '/' */
directory += p - directory;
}
else
{
dev = strdup(directory);
directory = "/";
}
e_fwin_new(zone->container, dev, directory);
free(dev);
free(to_free);
return edbus_message_method_return_new(msg);
}
static Eina_Bool
_mime_shell_script_check(const char *mime)
{
static const struct sh_script_map {
const char *str;
size_t len;
} options[] = {
#define O(x) {x, sizeof(x) - 1}
O("application/x-sh"),
O("application/x-shellscript"),
O("text/x-sh"),
#undef O
{NULL, 0}
};
const struct sh_script_map *itr;
size_t mimelen = strlen(mime);
for (itr = options; itr->str != NULL; itr++)
if ((mimelen == itr->len) && (memcmp(mime, itr->str, mimelen) == 0))
return EINA_TRUE;
return EINA_FALSE;
}
static EDBus_Message*
_e_fileman_dbus_daemon_open_file_cb(const EDBus_Service_Interface *iface __UNUSED__,
const EDBus_Message *msg)
{
Eina_List *handlers;
const char *param_file = NULL, *mime, *errmsg = "unknow error";
char *real_file, *to_free = NULL;
E_Zone *zone;
if (!edbus_message_arguments_get(msg, "s", &param_file))
{
fprintf(stderr, "ERROR: getting arguments of OpenFile call.\n");
return edbus_message_method_return_new(msg);
}
if ((!param_file) || (param_file[0] == '\0'))
return _e_fileman_dbus_daemon_error(msg, "no file provided.");
zone = e_util_zone_current_get(e_manager_current_get());
if (!zone)
return _e_fileman_dbus_daemon_error(msg, "could not find a zone.");
if (!strstr(param_file, "://"))
{
real_file = ecore_file_realpath(param_file);
if (!real_file)
{
errmsg = "couldn't get realpath for file.";
goto error;
}
}
else
{
Efreet_Uri *uri = efreet_uri_decode(param_file);
real_file = NULL;
if (uri)
{
if ((uri->protocol) && (strcmp(uri->protocol, "file") == 0))
{
real_file = ecore_file_realpath(uri->path);
param_file = to_free = strdup(uri->path);
}
efreet_uri_free(uri);
}
if (!real_file)
{
errmsg = "unsupported protocol";
goto error;
}
}
mime = efreet_mime_type_get(real_file);
if (!mime)
{
errmsg = "couldn't find mime-type";
goto error;
}
if (strcmp(mime, "application/x-desktop") == 0)
{
Efreet_Desktop *desktop = efreet_desktop_new(real_file);
if (!desktop)
{
errmsg = "couldn't open desktop file";
goto error;
}
e_exec(zone, desktop, NULL, NULL, NULL);
efreet_desktop_free(desktop);
goto end;
}
else if ((strcmp(mime, "application/x-executable") == 0) ||
ecore_file_can_exec(param_file))
{
e_exec(zone, NULL, param_file, NULL, NULL);
goto end;
}
else if (_mime_shell_script_check(mime))
{
Eina_Strbuf *b = eina_strbuf_new();
const char *shell = getenv("SHELL");
if (!shell)
{
uid_t uid = getuid();
struct passwd *pw = getpwuid(uid);
if (pw) shell = pw->pw_shell;
}
if (!shell) shell = "/bin/sh";
eina_strbuf_append_printf(b, "%s %s %s",
e_config->exebuf_term_cmd,
shell,
param_file);
e_exec(zone, NULL, eina_strbuf_string_get(b), NULL, NULL);
eina_strbuf_free(b);
goto end;
}
handlers = efreet_util_desktop_mime_list(mime);
if (!handlers)
{
errmsg = "no handlers for given file";
goto end;
}
else
{
Efreet_Desktop *desktop = handlers->data;
Eina_List *files = eina_list_append(NULL, param_file);
e_exec(zone, desktop, NULL, files, NULL);
eina_list_free(files);
EINA_LIST_FREE(handlers, desktop)
efreet_desktop_free(desktop);
}
end:
free(real_file);
free(to_free);
return edbus_message_method_return_new(msg);
error:
free(real_file);
free(to_free);
return _e_fileman_dbus_daemon_error(msg, errmsg);
}
static E_Fileman_DBus_Daemon *
_e_fileman_dbus_daemon_new(void)
{
E_Fileman_DBus_Daemon *d;
d = calloc(1, sizeof(E_Fileman_DBus_Daemon));
if (!d)
{
perror("ERROR: FILEMAN: cannot allocate fileman dbus daemon memory.");
return NULL;
}
d->conn = edbus_connection_get(EDBUS_CONNECTION_TYPE_SESSION);
if (!d->conn)
goto error;
_e_fileman_dbus_daemon_object_init(d);
edbus_name_request(d->conn, E_FILEMAN_BUS_NAME,
EDBUS_NAME_REQUEST_FLAG_REPLACE_EXISTING, NULL, NULL);
return d;
error:
fprintf(stderr, "ERROR: FILEMAN: failed to create daemon at %p\n", d);
_e_fileman_dbus_daemon_free(d);
return NULL;
}
static E_Fileman_DBus_Daemon *_daemon = NULL;
void
e_fileman_dbus_init(void)
{
if (_daemon)
return;
edbus_init();
_daemon = _e_fileman_dbus_daemon_new();
}
void
e_fileman_dbus_shutdown(void)
{
if (!_daemon)
return;
_e_fileman_dbus_daemon_free(_daemon);
_daemon = NULL;
edbus_shutdown();
}