forked from enlightenment/efl
efreet: split desktop command to separate file
SVN revision: 48025
This commit is contained in:
parent
3939026032
commit
6b1bb18738
|
@ -20,6 +20,7 @@ efreet_icon.c \
|
|||
efreet_xml.c \
|
||||
efreet_ini.c \
|
||||
efreet_desktop.c \
|
||||
efreet_desktop_command.c \
|
||||
efreet_menu.c \
|
||||
efreet_utils.c \
|
||||
efreet_uri.c
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <libgen.h>
|
||||
|
@ -37,61 +35,6 @@ struct _Efreet_Event_Cache_Data
|
|||
Eet_File *cache;
|
||||
};
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* The different types of commands in an Exec entry
|
||||
*/
|
||||
typedef enum Efreet_Desktop_Command_Flag
|
||||
{
|
||||
EFREET_DESKTOP_EXEC_FLAG_FULLPATH = 0x0001,
|
||||
EFREET_DESKTOP_EXEC_FLAG_URI = 0x0002
|
||||
} Efreet_Desktop_Command_Flag;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Efreet_Desktop_Command
|
||||
*/
|
||||
typedef struct Efreet_Desktop_Command Efreet_Desktop_Command;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Holds information on a desktop Exec command entry
|
||||
*/
|
||||
struct Efreet_Desktop_Command
|
||||
{
|
||||
Efreet_Desktop *desktop;
|
||||
int num_pending;
|
||||
|
||||
Efreet_Desktop_Command_Flag flags;
|
||||
|
||||
Efreet_Desktop_Command_Cb cb_command;
|
||||
Efreet_Desktop_Progress_Cb cb_progress;
|
||||
void *data;
|
||||
|
||||
Eina_List *files; /**< list of Efreet_Desktop_Command_File */
|
||||
};
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Efreet_Desktop_Command_File
|
||||
*/
|
||||
typedef struct Efreet_Desktop_Command_File Efreet_Desktop_Command_File;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Stores information on a file passed to the desktop Exec command
|
||||
*/
|
||||
struct Efreet_Desktop_Command_File
|
||||
{
|
||||
Efreet_Desktop_Command *command;
|
||||
char *dir;
|
||||
char *file;
|
||||
char *fullpath;
|
||||
char *uri;
|
||||
|
||||
int pending;
|
||||
};
|
||||
|
||||
/**
|
||||
* The current desktop environment (e.g. "Enlightenment" or "Gnome")
|
||||
*/
|
||||
|
@ -113,11 +56,6 @@ static Eina_List *efreet_desktop_types = NULL;
|
|||
*/
|
||||
static Eina_List *efreet_desktop_dirs = NULL;
|
||||
|
||||
/**
|
||||
* A unique id for each tmp file created while building a command
|
||||
*/
|
||||
static int efreet_desktop_command_file_id = 0;
|
||||
|
||||
/**
|
||||
* A job pointer for cache updates
|
||||
*/
|
||||
|
@ -140,7 +78,7 @@ static Eina_Hash *change_monitors = NULL;
|
|||
#endif
|
||||
|
||||
#define EFREET_MODULE_LOG_DOM _efreet_desktop_log_dom
|
||||
static int _efreet_desktop_log_dom = -1;
|
||||
int _efreet_desktop_log_dom = -1;
|
||||
|
||||
EAPI int EFREET_DESKTOP_TYPE_APPLICATION = 0;
|
||||
EAPI int EFREET_DESKTOP_TYPE_LINK = 0;
|
||||
|
@ -186,44 +124,7 @@ static Eina_Bool efreet_desktop_x_fields_save(const Eina_Hash *hash,
|
|||
void *value,
|
||||
void *fdata);
|
||||
static int efreet_desktop_environment_check(Efreet_Ini *ini);
|
||||
static char *efreet_string_append(char *dest, int *size,
|
||||
int *len, const char *src);
|
||||
static char *efreet_string_append_char(char *dest, int *size,
|
||||
int *len, char c);
|
||||
static Eina_List *efreet_desktop_command_build(Efreet_Desktop_Command *command);
|
||||
static void efreet_desktop_command_free(Efreet_Desktop_Command *command);
|
||||
static char *efreet_desktop_command_append_quoted(char *dest, int *size,
|
||||
int *len, char *src);
|
||||
static char *efreet_desktop_command_append_icon(char *dest, int *size, int *len,
|
||||
Efreet_Desktop *desktop);
|
||||
static char *efreet_desktop_command_append_single(char *dest, int *size, int *len,
|
||||
Efreet_Desktop_Command_File *file,
|
||||
char type);
|
||||
static char *efreet_desktop_command_append_multiple(char *dest, int *size, int *len,
|
||||
Efreet_Desktop_Command *command,
|
||||
char type);
|
||||
|
||||
static char *efreet_desktop_command_path_absolute(const char *path);
|
||||
static Efreet_Desktop_Command_File *efreet_desktop_command_file_process(
|
||||
Efreet_Desktop_Command *command,
|
||||
const char *file);
|
||||
static const char *efreet_desktop_command_file_uri_process(const char *uri);
|
||||
static void efreet_desktop_command_file_free(Efreet_Desktop_Command_File *file);
|
||||
|
||||
static void efreet_desktop_cb_download_complete(void *data, const char *file,
|
||||
int status);
|
||||
static int efreet_desktop_cb_download_progress(void *data, const char *file,
|
||||
long int dltotal, long int dlnow,
|
||||
long int ultotal, long int ulnow);
|
||||
|
||||
|
||||
static void *efreet_desktop_exec_cb(void *data, Efreet_Desktop *desktop,
|
||||
char *exec, int remaining);
|
||||
|
||||
static void efreet_desktop_type_info_free(Efreet_Desktop_Type_Info *info);
|
||||
static int efreet_desktop_command_flags_get(Efreet_Desktop *desktop);
|
||||
static void *efreet_desktop_command_execs_process(Efreet_Desktop_Command *command, Eina_List *execs);
|
||||
|
||||
static void efreet_desktop_update_cache_dirs(void);
|
||||
static void efreet_desktop_cache_update(void *data, Ecore_File_Monitor *em,
|
||||
Ecore_File_Event event, const char *path);
|
||||
|
@ -861,30 +762,6 @@ efreet_desktop_free(Efreet_Desktop *desktop)
|
|||
FREE(desktop);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param desktop: The desktop file to work with
|
||||
* @param files: The files to be substituted into the exec line
|
||||
* @param data: The data pointer to pass
|
||||
* @return Returns the Ecore_Exce for @a desktop
|
||||
* @brief Parses the @a desktop exec line and returns an Ecore_Exe.
|
||||
*/
|
||||
EAPI void
|
||||
efreet_desktop_exec(Efreet_Desktop *desktop, Eina_List *files, void *data)
|
||||
{
|
||||
efreet_desktop_command_get(desktop, files, efreet_desktop_exec_cb, data);
|
||||
}
|
||||
|
||||
static void *
|
||||
efreet_desktop_exec_cb(void *data, Efreet_Desktop *desktop __UNUSED__,
|
||||
char *exec, int remaining __UNUSED__)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
ecore_exe_run(exec, data);
|
||||
free(exec);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param environment: the environment name
|
||||
* @brief sets the global desktop environment name
|
||||
|
@ -1405,725 +1282,6 @@ efreet_desktop_environment_check(Efreet_Ini *ini)
|
|||
return !found;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param desktop: the desktop entry
|
||||
* @param files: an eina list of file names to execute, as either absolute paths,
|
||||
* relative paths, or uris
|
||||
* @param func: a callback to call for each prepared command line
|
||||
* @param data: user data passed to the callback
|
||||
* @return Returns the return value of @p func on success or NULL on failure
|
||||
* @brief Get a command to use to execute a desktop entry.
|
||||
*/
|
||||
EAPI void *
|
||||
efreet_desktop_command_get(Efreet_Desktop *desktop, Eina_List *files,
|
||||
Efreet_Desktop_Command_Cb func, void *data)
|
||||
{
|
||||
return efreet_desktop_command_progress_get(desktop, files, func, NULL, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param desktop: the desktop entry
|
||||
* @param files an eina list of local files, as absolute paths, local paths, or file:// uris (or NULL to get exec string with no files appended)
|
||||
* @return Returns an eina list of exec strings
|
||||
* @brief Get the command to use to execute a desktop entry
|
||||
*
|
||||
* The returned list and each of its elements must be freed.
|
||||
*/
|
||||
EAPI Eina_List *
|
||||
efreet_desktop_command_local_get(Efreet_Desktop *desktop, Eina_List *files)
|
||||
{
|
||||
Efreet_Desktop_Command *command;
|
||||
char *file;
|
||||
Eina_List *execs, *l;
|
||||
|
||||
if (!desktop || !desktop->exec) return NULL;
|
||||
|
||||
command = NEW(Efreet_Desktop_Command, 1);
|
||||
if (!command) return 0;
|
||||
|
||||
command->desktop = desktop;
|
||||
|
||||
command->flags = efreet_desktop_command_flags_get(desktop);
|
||||
/* get the required info for each file passed in */
|
||||
if (files)
|
||||
{
|
||||
EINA_LIST_FOREACH(files, l, file)
|
||||
{
|
||||
Efreet_Desktop_Command_File *dcf;
|
||||
|
||||
dcf = efreet_desktop_command_file_process(command, file);
|
||||
if (!dcf) continue;
|
||||
if (dcf->pending)
|
||||
{
|
||||
efreet_desktop_command_file_free(dcf);
|
||||
continue;
|
||||
}
|
||||
command->files = eina_list_append(command->files, dcf);
|
||||
}
|
||||
}
|
||||
|
||||
execs = efreet_desktop_command_build(command);
|
||||
efreet_desktop_command_free(command);
|
||||
|
||||
return execs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param desktop: the desktop entry
|
||||
* @param files: an eina list of file names to execute, as either absolute paths,
|
||||
* relative paths, or uris
|
||||
* @param cb_command: a callback to call for each prepared command line
|
||||
* @param cb_progress: a callback to get progress for the downloads
|
||||
* @param data: user data passed to the callback
|
||||
* @return Returns 1 on success or 0 on failure
|
||||
* @brief Get a command to use to execute a desktop entry, and receive progress
|
||||
* updates for downloading of remote URI's passed in.
|
||||
*/
|
||||
EAPI void *
|
||||
efreet_desktop_command_progress_get(Efreet_Desktop *desktop, Eina_List *files,
|
||||
Efreet_Desktop_Command_Cb cb_command,
|
||||
Efreet_Desktop_Progress_Cb cb_progress,
|
||||
void *data)
|
||||
{
|
||||
Efreet_Desktop_Command *command;
|
||||
Eina_List *l;
|
||||
char *file;
|
||||
void *ret = NULL;
|
||||
|
||||
if (!desktop || !cb_command || !desktop->exec) return NULL;
|
||||
|
||||
command = NEW(Efreet_Desktop_Command, 1);
|
||||
if (!command) return NULL;
|
||||
|
||||
command->cb_command = cb_command;
|
||||
command->cb_progress = cb_progress;
|
||||
command->data = data;
|
||||
command->desktop = desktop;
|
||||
|
||||
command->flags = efreet_desktop_command_flags_get(desktop);
|
||||
/* get the required info for each file passed in */
|
||||
if (files)
|
||||
{
|
||||
EINA_LIST_FOREACH(files, l, file)
|
||||
{
|
||||
Efreet_Desktop_Command_File *dcf;
|
||||
|
||||
dcf = efreet_desktop_command_file_process(command, file);
|
||||
if (!dcf) continue;
|
||||
command->files = eina_list_append(command->files, dcf);
|
||||
command->num_pending += dcf->pending;
|
||||
}
|
||||
}
|
||||
|
||||
if (command->num_pending == 0)
|
||||
{
|
||||
Eina_List *execs;
|
||||
|
||||
execs = efreet_desktop_command_build(command);
|
||||
ret = efreet_desktop_command_execs_process(command, execs);
|
||||
eina_list_free(execs);
|
||||
efreet_desktop_command_free(command);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Determine which file related field codes are present in the Exec string of a .desktop
|
||||
* @params desktop and Efreet Desktop
|
||||
* @return a bitmask of file field codes present in exec string
|
||||
*/
|
||||
static int
|
||||
efreet_desktop_command_flags_get(Efreet_Desktop *desktop)
|
||||
{
|
||||
int flags = 0;
|
||||
const char *p;
|
||||
/* first, determine which fields are present in the Exec string */
|
||||
p = strchr(desktop->exec, '%');
|
||||
while (p)
|
||||
{
|
||||
p++;
|
||||
switch(*p)
|
||||
{
|
||||
case 'f':
|
||||
case 'F':
|
||||
flags |= EFREET_DESKTOP_EXEC_FLAG_FULLPATH;
|
||||
break;
|
||||
case 'u':
|
||||
case 'U':
|
||||
flags |= EFREET_DESKTOP_EXEC_FLAG_URI;
|
||||
break;
|
||||
case '%':
|
||||
p++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
p = strchr(p, '%');
|
||||
}
|
||||
#ifdef SLOPPY_SPEC
|
||||
/* NON-SPEC!!! this is to work around LOTS of 'broken' .desktop files that
|
||||
* do not specify %U/%u, %F/F etc. etc. at all. just a command. this is
|
||||
* unlikely to be fixed in distributions etc. in the long run as gnome/kde
|
||||
* seem to have workarounds too so no one notices.
|
||||
*/
|
||||
if (!flags) flags |= EFREET_DESKTOP_EXEC_FLAG_FULLPATH;
|
||||
#endif
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Call the command callback for each exec in the list
|
||||
* @param command
|
||||
* @param execs
|
||||
*/
|
||||
static void *
|
||||
efreet_desktop_command_execs_process(Efreet_Desktop_Command *command, Eina_List *execs)
|
||||
{
|
||||
Eina_List *l;
|
||||
char *exec;
|
||||
int num;
|
||||
void *ret = NULL;
|
||||
|
||||
num = eina_list_count(execs);
|
||||
EINA_LIST_FOREACH(execs, l, exec)
|
||||
{
|
||||
ret = command->cb_command(command->data, command->desktop, exec, --num);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Builds the actual exec string from the raw string and a list of
|
||||
* processed filename information. The callback passed in to
|
||||
* efreet_desktop_command_get is called for each exec string created.
|
||||
*
|
||||
* @param command: the command to build
|
||||
* @return a list of executable strings
|
||||
*/
|
||||
static Eina_List *
|
||||
efreet_desktop_command_build(Efreet_Desktop_Command *command)
|
||||
{
|
||||
Eina_List *execs = NULL;
|
||||
const Eina_List *l;
|
||||
char *exec;
|
||||
|
||||
/* if the Exec field appends multiple, that will run the list to the end,
|
||||
* causing this loop to only run once. otherwise, this loop will generate a
|
||||
* command for each file in the list. if the list is empty, this
|
||||
* will run once, removing any file field codes */
|
||||
l = command->files;
|
||||
do
|
||||
{
|
||||
const char *p;
|
||||
int len = 0;
|
||||
int size = PATH_MAX;
|
||||
int file_added = 0;
|
||||
Efreet_Desktop_Command_File *file = eina_list_data_get(l);
|
||||
|
||||
exec = malloc(size);
|
||||
p = command->desktop->exec;
|
||||
len = 0;
|
||||
|
||||
while (*p)
|
||||
{
|
||||
if (len >= size - 1)
|
||||
{
|
||||
size = len + 1024;
|
||||
exec = realloc(exec, size);
|
||||
}
|
||||
|
||||
/* XXX handle fields inside quotes? */
|
||||
if (*p == '%')
|
||||
{
|
||||
p++;
|
||||
switch (*p)
|
||||
{
|
||||
case 'f':
|
||||
case 'u':
|
||||
case 'd':
|
||||
case 'n':
|
||||
if (file)
|
||||
{
|
||||
exec = efreet_desktop_command_append_single(exec, &size,
|
||||
&len, file, *p);
|
||||
file_added = 1;
|
||||
}
|
||||
break;
|
||||
case 'F':
|
||||
case 'U':
|
||||
case 'D':
|
||||
case 'N':
|
||||
if (file)
|
||||
{
|
||||
exec = efreet_desktop_command_append_multiple(exec, &size,
|
||||
&len, command, *p);
|
||||
file_added = 1;
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
exec = efreet_desktop_command_append_icon(exec, &size, &len,
|
||||
command->desktop);
|
||||
break;
|
||||
case 'c':
|
||||
exec = efreet_desktop_command_append_quoted(exec, &size, &len,
|
||||
command->desktop->name);
|
||||
break;
|
||||
case 'k':
|
||||
exec = efreet_desktop_command_append_quoted(exec, &size, &len,
|
||||
command->desktop->orig_path);
|
||||
break;
|
||||
case 'v':
|
||||
case 'm':
|
||||
WRN("[Efreet]: Deprecated conversion char: '%c' in file '%s'",
|
||||
*p, command->desktop->orig_path);
|
||||
break;
|
||||
case '%':
|
||||
exec[len++] = *p;
|
||||
break;
|
||||
default:
|
||||
#ifdef STRICT_SPEC
|
||||
WRN("[Efreet_desktop]: Unknown conversion character: '%c'", *p);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
else exec[len++] = *p;
|
||||
p++;
|
||||
}
|
||||
|
||||
#ifdef SLOPPY_SPEC
|
||||
/* NON-SPEC!!! this is to work around LOTS of 'broken' .desktop files that
|
||||
* do not specify %U/%u, %F/F etc. etc. at all. just a command. this is
|
||||
* unlikely to be fixed in distributions etc. in the long run as gnome/kde
|
||||
* seem to have workarounds too so no one notices.
|
||||
*/
|
||||
if ((file) && (!file_added))
|
||||
{
|
||||
WRN("Efreet_desktop: %s\n"
|
||||
" command: %s\n"
|
||||
" has no file path/uri spec info for executing this app WITH a\n"
|
||||
" file/uri as a parameter. This is unlikely to be the intent.\n"
|
||||
" please check the .desktop file and fix it by adding a %%U or %%F\n"
|
||||
" or something appropriate.",
|
||||
command->desktop->orig_path, command->desktop->exec);
|
||||
if (len >= size - 1)
|
||||
{
|
||||
size = len + 1024;
|
||||
exec = realloc(exec, size);
|
||||
}
|
||||
exec[len++] = ' ';
|
||||
exec = efreet_desktop_command_append_multiple(exec, &size,
|
||||
&len, command, 'F');
|
||||
file_added = 1;
|
||||
}
|
||||
#endif
|
||||
exec[len++] = '\0';
|
||||
|
||||
execs = eina_list_append(execs, exec);
|
||||
|
||||
/* If no file was added, then the Exec field doesn't contain any file
|
||||
* fields (fFuUdDnN). We only want to run the app once in this case. */
|
||||
if (!file_added) break;
|
||||
}
|
||||
while ((l = eina_list_next(l)) != NULL);
|
||||
|
||||
return execs;
|
||||
}
|
||||
|
||||
static void
|
||||
efreet_desktop_command_free(Efreet_Desktop_Command *command)
|
||||
{
|
||||
Efreet_Desktop_Command_File *dcf;
|
||||
|
||||
if (!command) return;
|
||||
|
||||
while (command->files)
|
||||
{
|
||||
dcf = eina_list_data_get(command->files);
|
||||
efreet_desktop_command_file_free(dcf);
|
||||
command->files = eina_list_remove_list(command->files,
|
||||
command->files);
|
||||
}
|
||||
FREE(command);
|
||||
}
|
||||
|
||||
static char *
|
||||
efreet_desktop_command_append_quoted(char *dest, int *size, int *len, char *src)
|
||||
{
|
||||
if (!src) return dest;
|
||||
dest = efreet_string_append(dest, size, len, "'");
|
||||
|
||||
/* single quotes in src need to be escaped */
|
||||
if (strchr(src, '\''))
|
||||
{
|
||||
char *p;
|
||||
p = src;
|
||||
while (*p)
|
||||
{
|
||||
if (*p == '\'')
|
||||
dest = efreet_string_append(dest, size, len, "\'\\\'");
|
||||
|
||||
dest = efreet_string_append_char(dest, size, len, *p);
|
||||
p++;
|
||||
}
|
||||
}
|
||||
else
|
||||
dest = efreet_string_append(dest, size, len, src);
|
||||
|
||||
dest = efreet_string_append(dest, size, len, "'");
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
static char *
|
||||
efreet_desktop_command_append_multiple(char *dest, int *size, int *len,
|
||||
Efreet_Desktop_Command *command,
|
||||
char type)
|
||||
{
|
||||
Efreet_Desktop_Command_File *file;
|
||||
Eina_List *l;
|
||||
int first = 1;
|
||||
|
||||
if (!command->files) return dest;
|
||||
|
||||
EINA_LIST_FOREACH(command->files, l, file)
|
||||
{
|
||||
if (first)
|
||||
first = 0;
|
||||
else
|
||||
dest = efreet_string_append_char(dest, size, len, ' ');
|
||||
|
||||
dest = efreet_desktop_command_append_single(dest, size, len,
|
||||
file, tolower(type));
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
static char *
|
||||
efreet_desktop_command_append_single(char *dest, int *size, int *len,
|
||||
Efreet_Desktop_Command_File *file,
|
||||
char type)
|
||||
{
|
||||
char *str;
|
||||
switch(type)
|
||||
{
|
||||
case 'f':
|
||||
str = file->fullpath;
|
||||
break;
|
||||
case 'u':
|
||||
str = file->uri;
|
||||
break;
|
||||
case 'd':
|
||||
str = file->dir;
|
||||
break;
|
||||
case 'n':
|
||||
str = file->file;
|
||||
break;
|
||||
default:
|
||||
ERR("Invalid type passed to efreet_desktop_command_append_single:"
|
||||
" '%c'", type);
|
||||
return dest;
|
||||
}
|
||||
|
||||
if (!str) return dest;
|
||||
|
||||
dest = efreet_desktop_command_append_quoted(dest, size, len, str);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
static char *
|
||||
efreet_desktop_command_append_icon(char *dest, int *size, int *len,
|
||||
Efreet_Desktop *desktop)
|
||||
{
|
||||
if (!desktop->icon || !desktop->icon[0]) return dest;
|
||||
|
||||
dest = efreet_string_append(dest, size, len, "--icon ");
|
||||
dest = efreet_desktop_command_append_quoted(dest, size, len, desktop->icon);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Append a string to a buffer, reallocating as necessary.
|
||||
*/
|
||||
static char *
|
||||
efreet_string_append(char *dest, int *size, int *len, const char *src)
|
||||
{
|
||||
int l;
|
||||
int off = 0;
|
||||
|
||||
l = eina_strlcpy(dest + *len, src, *size - *len);
|
||||
|
||||
while (l > *size - *len)
|
||||
{
|
||||
/* we successfully appended this much */
|
||||
off += *size - *len - 1;
|
||||
*len = *size - 1;
|
||||
*size += 1024;
|
||||
dest = realloc(dest, *size);
|
||||
*(dest + *len) = '\0';
|
||||
|
||||
l = eina_strlcpy(dest + *len, src + off, *size - *len);
|
||||
}
|
||||
*len += l;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
static char *
|
||||
efreet_string_append_char(char *dest, int *size, int *len, char c)
|
||||
{
|
||||
if (*len >= *size - 1)
|
||||
{
|
||||
*size += 1024;
|
||||
dest = realloc(dest, *size);
|
||||
}
|
||||
|
||||
dest[(*len)++] = c;
|
||||
dest[*len] = '\0';
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param command: the Efreet_Desktop_Comand that this file is for
|
||||
* @param file: the filname as either an absolute path, relative path, or URI
|
||||
*/
|
||||
static Efreet_Desktop_Command_File *
|
||||
efreet_desktop_command_file_process(Efreet_Desktop_Command *command, const char *file)
|
||||
{
|
||||
Efreet_Desktop_Command_File *f;
|
||||
const char *uri, *base;
|
||||
int nonlocal = 0;
|
||||
/*
|
||||
DBG("FLAGS: %d, %d, %d, %d\n",
|
||||
command->flags & EFREET_DESKTOP_EXEC_FLAG_FULLPATH ? 1 : 0,
|
||||
command->flags & EFREET_DESKTOP_EXEC_FLAG_URI ? 1 : 0);
|
||||
*/
|
||||
f = NEW(Efreet_Desktop_Command_File, 1);
|
||||
if (!f) return NULL;
|
||||
|
||||
f->command = command;
|
||||
|
||||
/* handle uris */
|
||||
if (!strncmp(file, "http://", 7) || !strncmp(file, "ftp://", 6))
|
||||
{
|
||||
uri = file;
|
||||
base = ecore_file_file_get(file);
|
||||
|
||||
nonlocal = 1;
|
||||
}
|
||||
else if (!strncmp(file, "file:", 5))
|
||||
{
|
||||
file = efreet_desktop_command_file_uri_process(file);
|
||||
if (!file)
|
||||
{
|
||||
efreet_desktop_command_file_free(f);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (nonlocal)
|
||||
{
|
||||
/* process non-local uri */
|
||||
if (command->flags & EFREET_DESKTOP_EXEC_FLAG_FULLPATH)
|
||||
{
|
||||
char buf[PATH_MAX];
|
||||
|
||||
snprintf(buf, sizeof(buf), "/tmp/%d-%d-%s", getpid(),
|
||||
efreet_desktop_command_file_id++, base);
|
||||
f->fullpath = strdup(buf);
|
||||
f->pending = 1;
|
||||
|
||||
ecore_file_download(uri, f->fullpath, efreet_desktop_cb_download_complete,
|
||||
efreet_desktop_cb_download_progress, f, NULL);
|
||||
}
|
||||
|
||||
if (command->flags & EFREET_DESKTOP_EXEC_FLAG_URI)
|
||||
f->uri = strdup(uri);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *absol = efreet_desktop_command_path_absolute(file);
|
||||
/* process local uri/path */
|
||||
if (command->flags & EFREET_DESKTOP_EXEC_FLAG_FULLPATH)
|
||||
f->fullpath = strdup(absol);
|
||||
|
||||
if (command->flags & EFREET_DESKTOP_EXEC_FLAG_URI)
|
||||
{
|
||||
char buf[PATH_MAX];
|
||||
snprintf(buf, sizeof(buf), "file://%s", absol);
|
||||
f->uri = strdup(buf);
|
||||
}
|
||||
|
||||
free(absol);
|
||||
}
|
||||
#if 0
|
||||
INF(" fullpath: %s", f->fullpath);
|
||||
INF(" uri: %s", f->uri);
|
||||
INF(" dir: %s", f->dir);
|
||||
INF(" file: %s", f->file);
|
||||
#endif
|
||||
return f;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Find the local path portion of a file uri.
|
||||
* @param uri: a uri beginning with "file:"
|
||||
* @return the location of the path portion of the uri,
|
||||
* or NULL if the file is not on this machine
|
||||
*/
|
||||
static const char *
|
||||
efreet_desktop_command_file_uri_process(const char *uri)
|
||||
{
|
||||
const char *path = NULL;
|
||||
int len = strlen(uri);
|
||||
|
||||
/* uri:foo/bar => relative path foo/bar*/
|
||||
if (len >= 4 && uri[5] != '/')
|
||||
path = uri + strlen("file:");
|
||||
|
||||
/* uri:/foo/bar => absolute path /foo/bar */
|
||||
else if (len >= 5 && uri[6] != '/')
|
||||
path = uri + strlen("file:");
|
||||
|
||||
/* uri://foo/bar => absolute path /bar on machine foo */
|
||||
else if (len >= 6 && uri[7] != '/')
|
||||
{
|
||||
char *tmp, *p;
|
||||
char hostname[PATH_MAX];
|
||||
size_t len2;
|
||||
|
||||
len2 = strlen(uri + 7) + 1;
|
||||
tmp = alloca(len2);
|
||||
memcpy(tmp, uri + 7, len2);
|
||||
p = strchr(tmp, '/');
|
||||
if (p)
|
||||
{
|
||||
*p = '\0';
|
||||
if (!strcmp(tmp, "localhost"))
|
||||
path = uri + strlen("file://localhost");
|
||||
else
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = gethostname(hostname, PATH_MAX);
|
||||
if ((ret == 0) && !strcmp(tmp, hostname))
|
||||
path = uri + strlen("file://") + strlen(hostname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* uri:///foo/bar => absolute path /foo/bar on local machine */
|
||||
else if (len >= 7)
|
||||
path = uri + strlen("file://");
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
static void
|
||||
efreet_desktop_command_file_free(Efreet_Desktop_Command_File *file)
|
||||
{
|
||||
if (!file) return;
|
||||
|
||||
IF_FREE(file->fullpath);
|
||||
IF_FREE(file->uri);
|
||||
IF_FREE(file->dir);
|
||||
IF_FREE(file->file);
|
||||
|
||||
FREE(file);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
efreet_desktop_cb_download_complete(void *data, const char *file __UNUSED__,
|
||||
int status __UNUSED__)
|
||||
{
|
||||
Efreet_Desktop_Command_File *f;
|
||||
|
||||
f = data;
|
||||
|
||||
/* XXX check status... error handling, etc */
|
||||
f->pending = 0;
|
||||
f->command->num_pending--;
|
||||
|
||||
if (f->command->num_pending <= 0)
|
||||
{
|
||||
Eina_List *execs;
|
||||
|
||||
execs = efreet_desktop_command_build(f->command);
|
||||
/* TODO: Need to handle the return value from efreet_desktop_command_execs_process */
|
||||
efreet_desktop_command_execs_process(f->command, execs);
|
||||
eina_list_free(execs);
|
||||
efreet_desktop_command_free(f->command);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
efreet_desktop_cb_download_progress(void *data,
|
||||
const char *file __UNUSED__,
|
||||
long int dltotal, long int dlnow,
|
||||
long int ultotal __UNUSED__,
|
||||
long int ulnow __UNUSED__)
|
||||
{
|
||||
Efreet_Desktop_Command_File *dcf;
|
||||
|
||||
dcf = data;
|
||||
if (dcf->command->cb_progress)
|
||||
return dcf->command->cb_progress(dcf->command->data,
|
||||
dcf->command->desktop,
|
||||
dcf->uri, dltotal, dlnow);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Build an absolute path from an absolute or relative one.
|
||||
* @param path: an absolute or relative path
|
||||
* @return an allocated absolute path (must be freed)
|
||||
*/
|
||||
static char *
|
||||
efreet_desktop_command_path_absolute(const char *path)
|
||||
{
|
||||
char *buf;
|
||||
int size = PATH_MAX;
|
||||
int len = 0;
|
||||
|
||||
/* relative url */
|
||||
if (path[0] != '/')
|
||||
{
|
||||
if (!(buf = malloc(size))) return NULL;
|
||||
if (!getcwd(buf, size))
|
||||
{
|
||||
FREE(buf);
|
||||
return NULL;
|
||||
}
|
||||
len = strlen(buf);
|
||||
|
||||
if (buf[len-1] != '/') buf = efreet_string_append(buf, &size, &len, "/");
|
||||
buf = efreet_string_append(buf, &size, &len, path);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* just dup an already absolute buffer */
|
||||
return strdup(path);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
efreet_desktop_x_field_set(Efreet_Desktop *desktop, const char *key, const char *data)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue