diff options
author | Dominik Heidler <dominik@heidler.eu> | 2016-04-11 20:13:18 +0200 |
---|---|---|
committer | Dominik Heidler <dominik@heidler.eu> | 2016-04-26 23:50:55 +0200 |
commit | 1b0ce852bba81c3bbed1f7cbf04d0b60f1f0961b (patch) | |
tree | 6a611a76d29452910014f9cee4060b372145ece4 /src/command | |
parent | 28e260c7da7bddebcb7b08003174eb16b9a6f596 (diff) | |
download | profani-tty-1b0ce852bba81c3bbed1f7cbf04d0b60f1f0961b.tar.gz |
Implement XEP-0363: HTTP File Upload
Diffstat (limited to 'src/command')
-rw-r--r-- | src/command/command.c | 131 | ||||
-rw-r--r-- | src/command/commands.c | 71 | ||||
-rw-r--r-- | src/command/commands.h | 1 |
3 files changed, 195 insertions, 8 deletions
diff --git a/src/command/command.c b/src/command/command.c index 984812f5..1ac87374 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -42,6 +42,10 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <libgen.h> + +#include <dirent.h> +#include <sys/types.h> #include <glib.h> @@ -120,6 +124,7 @@ static char* _console_autocomplete(ProfWin *window, const char *const input); static char* _win_autocomplete(ProfWin *window, const char *const input); static char* _close_autocomplete(ProfWin *window, const char *const input); static char* _plugins_autocomplete(ProfWin *window, const char *const input); +static char* _sendfile_autocomplete(ProfWin *window, const char *const input); GHashTable *commands = NULL; @@ -795,6 +800,22 @@ static struct cmd_t command_defs[] = "/disco info myfriend@server.com/laptop") }, + { "/sendfile", + cmd_sendfile, parse_args_with_freetext, 1, 1, NULL, + CMD_TAGS( + CMD_TAG_CHAT, + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/sendfile <file>") + CMD_DESC( + "Send a file using XEP-0363 HTTP file transfer.") + CMD_ARGS( + { "<file>", "Path to the file." }) + CMD_EXAMPLES( + "/sendfile /etc/hosts", + "/sendfile ~/images/sweet_cat.jpg") + }, + { "/lastactivity", cmd_lastactivity, parse_args, 0, 1, NULL, CMD_TAGS( @@ -2043,6 +2064,7 @@ static Autocomplete console_msg_ac; static Autocomplete autoping_ac; static Autocomplete plugins_ac; static Autocomplete plugins_load_ac; +static Autocomplete sendfile_ac; /* * Initialise command autocompleter and history @@ -2597,6 +2619,8 @@ cmd_init(void) plugins_ac = autocomplete_new(); autocomplete_add(plugins_ac, "load"); + + sendfile_ac = autocomplete_new(); } void @@ -2686,6 +2710,7 @@ cmd_uninit(void) autocomplete_free(autoping_ac); autocomplete_free(plugins_ac); autocomplete_free(plugins_load_ac); + autocomplete_free(sendfile_ac); } gboolean @@ -2834,6 +2859,7 @@ cmd_reset_autocomplete(ProfWin *window) autocomplete_reset(notify_mention_ac); autocomplete_reset(notify_trigger_ac); autocomplete_reset(sub_ac); + autocomplete_reset(sendfile_ac); autocomplete_reset(who_room_ac); autocomplete_reset(who_roster_ac); @@ -3191,6 +3217,7 @@ _cmd_complete_parameters(ProfWin *window, const char *const input) g_hash_table_insert(ac_funcs, "/win", _win_autocomplete); g_hash_table_insert(ac_funcs, "/close", _close_autocomplete); g_hash_table_insert(ac_funcs, "/plugins", _plugins_autocomplete); + g_hash_table_insert(ac_funcs, "/sendfile", _sendfile_autocomplete); int len = strlen(input); char parsed[len+1]; @@ -4590,6 +4617,110 @@ _close_autocomplete(ProfWin *window, const char *const input) } static char* +_sendfile_autocomplete(ProfWin *window, const char *const input) +{ + static char* last_directory = NULL; + + unsigned int output_off = 0; + + char *result = NULL; + char *tmp; + + // strip command + char *inpcp = (char*)input + 9; + while (*inpcp == ' ') { + inpcp++; + } + + inpcp = strdup(inpcp); + + // strip quotes + if (*inpcp == '"') { + tmp = strchr(inpcp+1, '"'); + if (tmp) { + *tmp = '\0'; + } + tmp = strdup(inpcp+1); + free(inpcp); + inpcp = tmp; + } + + // expand ~ to $HOME + if (inpcp[0] == '~' && inpcp[1] == '/') { + if (asprintf(&tmp, "%s/%sfoo", getenv("HOME"), inpcp+2) == -1) { + return NULL; + } + output_off = strlen(getenv("HOME"))+1; + } else { + if (asprintf(&tmp, "%sfoo", inpcp) == -1) { + return NULL; + } + } + free(inpcp); + inpcp = tmp; + + char* inpcp2 = strdup(inpcp); + char* foofile = strdup(basename(inpcp2)); + char* directory = strdup(dirname(inpcp)); + free(inpcp); + free(inpcp2); + + if (!last_directory || strcmp(last_directory, directory) != 0) { + free(last_directory); + last_directory = directory; + autocomplete_reset(sendfile_ac); + + struct dirent *dir; + + DIR *d = opendir(directory); + if (d) { + while ((dir = readdir(d)) != NULL) { + if (strcmp(dir->d_name, ".") == 0) { + continue; + } else if (strcmp(dir->d_name, "..") == 0) { + continue; + } else if (*(dir->d_name) == '.' && *foofile != '.') { + // only show hidden files on explicit request + continue; + } + char * acstring; + if (output_off) { + if (asprintf(&tmp, "%s/%s", directory, dir->d_name) == -1) { + return NULL; + } + if (asprintf(&acstring, "~/%s", tmp+output_off) == -1) { + return NULL; + } + free(tmp); + } else if (strcmp(directory, "/") == 0) { + if (asprintf(&acstring, "/%s", dir->d_name) == -1) { + return NULL; + } + } else { + if (asprintf(&acstring, "%s/%s", directory, dir->d_name) == -1) { + return NULL; + } + } + autocomplete_add(sendfile_ac, acstring); + free(acstring); + } + closedir(d); + } + } else { + free(foofile); + free(directory); + } + + result = autocomplete_param_with_ac(input, "/sendfile", sendfile_ac, TRUE); + if (result) { + return result; + } + + return NULL; +} + + +static char* _subject_autocomplete(ProfWin *window, const char *const input) { char *result = NULL; diff --git a/src/command/commands.c b/src/command/commands.c index 50877227..257b8b5c 100644 --- a/src/command/commands.c +++ b/src/command/commands.c @@ -32,10 +32,13 @@ * */ +#define _GNU_SOURCE 1 + #include "config.h" #include <string.h> #include <stdlib.h> +#include <stdio.h> #include <errno.h> #include <assert.h> #include <glib.h> @@ -80,6 +83,7 @@ #ifdef HAVE_GTK #include "tray.h" #endif +#include "tools/http_upload.h" static void _update_presence(const resource_presence_t presence, const char *const show, gchar **args); @@ -128,21 +132,21 @@ cmd_execute_default(ProfWin *window, const char *inp) { ProfChatWin *chatwin = (ProfChatWin*)window; assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK); - cl_ev_send_msg(chatwin, inp); + cl_ev_send_msg(chatwin, inp, NULL); break; } case WIN_PRIVATE: { ProfPrivateWin *privatewin = (ProfPrivateWin*)window; assert(privatewin->memcheck == PROFPRIVATEWIN_MEMCHECK); - cl_ev_send_priv_msg(privatewin, inp); + cl_ev_send_priv_msg(privatewin, inp, NULL); break; } case WIN_MUC: { ProfMucWin *mucwin = (ProfMucWin*)window; assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); - cl_ev_send_muc_msg(mucwin, inp); + cl_ev_send_muc_msg(mucwin, inp, NULL); break; } case WIN_XML: @@ -1903,7 +1907,7 @@ cmd_msg(ProfWin *window, const char *const command, gchar **args) ui_focus_win((ProfWin*)privwin); if (msg) { - cl_ev_send_priv_msg(privwin, msg); + cl_ev_send_priv_msg(privwin, msg, NULL); } g_string_free(full_jid, TRUE); @@ -1928,7 +1932,7 @@ cmd_msg(ProfWin *window, const char *const command, gchar **args) ui_focus_win((ProfWin*)chatwin); if (msg) { - cl_ev_send_msg(chatwin, msg); + cl_ev_send_msg(chatwin, msg, NULL); } else { #ifdef HAVE_LIBOTR if (otr_is_secure(barejid)) { @@ -4225,6 +4229,57 @@ cmd_disco(ProfWin *window, const char *const command, gchar **args) } gboolean +cmd_sendfile(ProfWin *window, const char *const command, gchar **args) +{ + jabber_conn_status_t conn_status = jabber_get_connection_status(); + char *filename = args[0]; + + // expand ~ to $HOME + if (filename[0] == '~' && filename[1] == '/') { + if (asprintf(&filename, "%s/%s", getenv("HOME"), filename+2) == -1) { + return TRUE; + } + } else { + filename = strdup(filename); + } + + if (conn_status != JABBER_CONNECTED) { + cons_show("You are not currently connected."); + free(filename); + return TRUE; + } + + if (window->type != WIN_CHAT && window->type != WIN_PRIVATE && window->type != WIN_MUC) { + cons_show_error("Unsupported window for file transmission."); + free(filename); + return TRUE; + } + + if (access(filename, R_OK) != 0) { + cons_show_error("Uploading '%s' failed: File not found!", filename); + free(filename); + return TRUE; + } + + if (!is_regular_file(filename)) { + cons_show_error("Uploading '%s' failed: Not a file!", filename); + free(filename); + return TRUE; + } + + HTTPUpload *upload = malloc(sizeof(HTTPUpload)); + upload->window = window; + + upload->filename = filename; + upload->filesize = file_size(filename); + upload->mime_type = file_mime_type(filename); + + iq_http_upload_request(upload); + + return TRUE; +} + +gboolean cmd_lastactivity(ProfWin *window, const char *const command, gchar **args) { if ((g_strcmp0(args[0], "on") == 0) || (g_strcmp0(args[0], "off") == 0)) { @@ -4375,21 +4430,21 @@ cmd_tiny(ProfWin *window, const char *const command, gchar **args) { ProfChatWin *chatwin = (ProfChatWin*)window; assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK); - cl_ev_send_msg(chatwin, tiny); + cl_ev_send_msg(chatwin, tiny, NULL); break; } case WIN_PRIVATE: { ProfPrivateWin *privatewin = (ProfPrivateWin*)window; assert(privatewin->memcheck == PROFPRIVATEWIN_MEMCHECK); - cl_ev_send_priv_msg(privatewin, tiny); + cl_ev_send_priv_msg(privatewin, tiny, NULL); break; } case WIN_MUC: { ProfMucWin *mucwin = (ProfMucWin*)window; assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); - cl_ev_send_muc_msg(mucwin, tiny); + cl_ev_send_muc_msg(mucwin, tiny, NULL); break; } default: diff --git a/src/command/commands.h b/src/command/commands.h index cfa9d966..da958bea 100644 --- a/src/command/commands.h +++ b/src/command/commands.h @@ -85,6 +85,7 @@ gboolean cmd_connect(ProfWin *window, const char *const command, gchar **args); gboolean cmd_tls(ProfWin *window, const char *const command, gchar **args); gboolean cmd_decline(ProfWin *window, const char *const command, gchar **args); gboolean cmd_disco(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_sendfile(ProfWin *window, const char *const command, gchar **args); gboolean cmd_lastactivity(ProfWin *window, const char *const command, gchar **args); gboolean cmd_disconnect(ProfWin *window, const char *const command, gchar **args); gboolean cmd_dnd(ProfWin *window, const char *const command, gchar **args); |