diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/command/cmd_ac.c | 7 | ||||
-rw-r--r-- | src/command/cmd_defs.c | 4 | ||||
-rw-r--r-- | src/command/cmd_funcs.c | 104 | ||||
-rw-r--r-- | src/common.c | 36 | ||||
-rw-r--r-- | src/common.h | 3 | ||||
-rw-r--r-- | src/config/files.c | 58 | ||||
-rw-r--r-- | src/config/files.h | 3 | ||||
-rw-r--r-- | src/database.c | 22 | ||||
-rw-r--r-- | src/log.c | 76 | ||||
-rw-r--r-- | src/omemo/omemo.c | 17 | ||||
-rw-r--r-- | src/otr/otr.c | 36 | ||||
-rw-r--r-- | src/pgp/gpg.c | 24 | ||||
-rw-r--r-- | src/tools/editor.c | 125 | ||||
-rw-r--r-- | src/tools/editor.h | 44 | ||||
-rw-r--r-- | src/ui/inputwin.c | 57 | ||||
-rw-r--r-- | src/xmpp/connection.c | 12 |
16 files changed, 324 insertions, 304 deletions
diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c index 9635211d..bb703cfb 100644 --- a/src/command/cmd_ac.c +++ b/src/command/cmd_ac.c @@ -780,6 +780,7 @@ cmd_ac_init(void) subject_ac = autocomplete_new(); autocomplete_add(subject_ac, "set"); autocomplete_add(subject_ac, "edit"); + autocomplete_add(subject_ac, "editor"); autocomplete_add(subject_ac, "prepend"); autocomplete_add(subject_ac, "append"); autocomplete_add(subject_ac, "clear"); @@ -3637,11 +3638,7 @@ _subject_autocomplete(ProfWin* window, const char* const input, gboolean previou char* result = NULL; if (window->type == WIN_MUC) { - if ((g_strcmp0(input, "/subject e") == 0) - || (g_strcmp0(input, "/subject ed") == 0) - || (g_strcmp0(input, "/subject edi") == 0) - || (g_strcmp0(input, "/subject edit") == 0) - || (g_strcmp0(input, "/subject edit ") == 0) + if ((g_strcmp0(input, "/subject edit ") == 0) || (g_strcmp0(input, "/subject edit \"") == 0)) { ProfMucWin* mucwin = (ProfMucWin*)window; assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c index 359f47d0..750e533d 100644 --- a/src/command/cmd_defs.c +++ b/src/command/cmd_defs.c @@ -676,6 +676,7 @@ static struct cmd_t command_defs[] = { CMD_SYN( "/subject set <subject>", "/subject edit <subject>", + "/subject editor", "/subject prepend <text>", "/subject append <text>", "/subject clear") @@ -684,6 +685,7 @@ static struct cmd_t command_defs[] = { CMD_ARGS( { "set <subject>", "Set the room subject." }, { "edit <subject>", "Edit the current room subject, tab autocompletion will display the subject to edit." }, + { "editor", "Edit the current room subject in external editor." }, { "prepend <text>", "Prepend text to the current room subject, use double quotes if a trailing space is needed." }, { "append <text>", "Append text to the current room subject, use double quotes if a preceding space is needed." }, { "clear", "Clear the room subject." }) @@ -3002,7 +3004,7 @@ command_mangen(void) cmds = g_list_insert_sorted(cmds, pcmd, (GCompareFunc)_cmp_command); } - mkdir_recursive("docs"); + create_dir("docs"); GDateTime* now = g_date_time_new_now_local(); gchar* date = g_date_time_format(now, "%F"); diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index be469c28..b1aadbf0 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -77,6 +77,7 @@ #include "tools/autocomplete.h" #include "tools/parser.h" #include "tools/bookmark_ignore.h" +#include "tools/editor.h" #include "plugins/plugins.h" #include "ui/ui.h" #include "ui/window_list.h" @@ -4095,6 +4096,22 @@ cmd_subject(ProfWin* window, const char* const command, gchar** args) return TRUE; } + if (g_strcmp0(args[0], "editor") == 0) { + gchar* message = NULL; + char* subject = muc_subject(mucwin->roomjid); + + if (get_message_from_editor(subject, &message)) { + return TRUE; + } + + if (message) { + message_send_groupchat_subject(mucwin->roomjid, message); + } else { + cons_bad_cmd_usage(command); + } + return TRUE; + } + if (g_strcmp0(args[0], "prepend") == 0) { if (args[1]) { char* old_subject = muc_subject(mucwin->roomjid); @@ -9452,89 +9469,6 @@ cmd_change_password(ProfWin* window, const char* const command, gchar** args) return TRUE; } -// Returns true if an error occurred -gboolean -_get_message_from_editor(gchar* message, gchar** returned_message) -{ - // create editor dir if not present - char* jid = connection_get_barejid(); - gchar* path = files_get_account_data_path(DIR_EDITOR, jid); - free(jid); - if (g_mkdir_with_parents(path, S_IRWXU) != 0) { - cons_show_error("Failed to create directory at '%s' with error '%s'", path, strerror(errno)); - g_free(path); - return TRUE; - } - - // build temp file name. Example: /home/user/.local/share/profanity/editor/jid/compose.md - char* filename = g_strdup_printf("%s/compose.md", path); - g_free(path); - - GError* creation_error = NULL; - GFile* file = g_file_new_for_path(filename); - GFileOutputStream* fos = g_file_create(file, G_FILE_CREATE_PRIVATE, NULL, &creation_error); - - free(filename); - - if (message != NULL && strlen(message) > 0) { - int fd_output_file = open(g_file_get_path(file), O_WRONLY); - if (fd_output_file < 0) { - cons_show_error("Editor: Could not open file '%s': %s", file, strerror(errno)); - return TRUE; - } - if (-1 == write(fd_output_file, message, strlen(message))) { - cons_show_error("Editor: failed to write '%s' to file: %s", message, strerror(errno)); - return TRUE; - } - close(fd_output_file); - } - - if (creation_error) { - cons_show_error("Editor: could not create temp file"); - return TRUE; - } - g_object_unref(fos); - - char* editor = prefs_get_string(PREF_COMPOSE_EDITOR); - - // Fork / exec - pid_t pid = fork(); - if (pid == 0) { - int x = execlp(editor, editor, g_file_get_path(file), (char*)NULL); - if (x == -1) { - cons_show_error("Editor:Failed to exec %s", editor); - } - _exit(EXIT_FAILURE); - } else { - if (pid == -1) { - return TRUE; - } - int status = 0; - waitpid(pid, &status, 0); - int fd_input_file = open(g_file_get_path(file), O_RDONLY); - const size_t COUNT = 8192; - char buf[COUNT]; - ssize_t size_read = read(fd_input_file, buf, COUNT); - if (size_read > 0 && size_read <= COUNT) { - buf[size_read - 1] = '\0'; - GString* text = g_string_new(buf); - *returned_message = g_strdup(text->str); - g_string_free(text, TRUE); - } - close(fd_input_file); - - GError* deletion_error = NULL; - g_file_delete(file, NULL, &deletion_error); - if (deletion_error) { - cons_show("Editor: error during file deletion"); - return TRUE; - } - g_object_unref(file); - } - - return FALSE; -} - gboolean cmd_editor(ProfWin* window, const char* const command, gchar** args) { @@ -9547,7 +9481,7 @@ cmd_editor(ProfWin* window, const char* const command, gchar** args) gchar* message = NULL; - if (_get_message_from_editor(NULL, &message)) { + if (get_message_from_editor(NULL, &message)) { return TRUE; } @@ -9570,7 +9504,7 @@ cmd_correct_editor(ProfWin* window, const char* const command, gchar** args) gchar* initial_message = win_get_last_sent_message(window); gchar* message = NULL; - if (_get_message_from_editor(initial_message, &message)) { + if (get_message_from_editor(initial_message, &message)) { return TRUE; } diff --git a/src/common.c b/src/common.c index 6020b8c3..5e0fabf6 100644 --- a/src/common.c +++ b/src/common.c @@ -71,44 +71,16 @@ struct curl_data_t static size_t _data_callback(void* ptr, size_t size, size_t nmemb, void* data); gboolean -create_dir(char* name) +create_dir(const char* name) { - struct stat sb; - - if (stat(name, &sb) != 0) { - if (errno != ENOENT || mkdir(name, S_IRWXU) != 0) { - return FALSE; - } - } else { - if ((sb.st_mode & S_IFDIR) != S_IFDIR) { - log_debug("create_dir: %s exists and is not a directory!", name); - return FALSE; - } + if (g_mkdir_with_parents(name, S_IRWXU) != 0) { + log_error("Failed to create directory at '%s' with error '%s'", name, strerror(errno)); + return FALSE; } - return TRUE; } gboolean -mkdir_recursive(const char* dir) -{ - gboolean result = TRUE; - - for (int i = 1; i <= strlen(dir); i++) { - if (dir[i] == '/' || dir[i] == '\0') { - gchar* next_dir = g_strndup(dir, i); - result = create_dir(next_dir); - g_free(next_dir); - if (!result) { - break; - } - } - } - - return result; -} - -gboolean copy_file(const char* const sourcepath, const char* const targetpath, const gboolean overwrite_existing) { GFile* source = g_file_new_for_path(sourcepath); diff --git a/src/common.h b/src/common.h index bd33bf90..b97ef401 100644 --- a/src/common.h +++ b/src/common.h @@ -80,8 +80,7 @@ typedef enum { RESOURCE_XA } resource_presence_t; -gboolean create_dir(char* name); -gboolean mkdir_recursive(const char* dir); +gboolean create_dir(const char* name); gboolean copy_file(const char* const src, const char* const target, const gboolean overwrite_existing); char* str_replace(const char* string, const char* substr, const char* replacement); gboolean strtoi_range(char* str, int* saveptr, int min, int max, char** err_msg); diff --git a/src/config/files.c b/src/config/files.c index ce3f1196..7e24dee9 100644 --- a/src/config/files.c +++ b/src/config/files.c @@ -38,6 +38,8 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <fcntl.h> +#include <errno.h> #include <glib.h> #include "common.h" @@ -65,19 +67,19 @@ files_create_directories(void) GString* plugins_dir = g_string_new(xdg_data); g_string_append(plugins_dir, "/profanity/plugins"); - if (!mkdir_recursive(themes_dir->str)) { + if (!create_dir(themes_dir->str)) { log_error("Error while creating directory %s", themes_dir->str); } - if (!mkdir_recursive(icons_dir->str)) { + if (!create_dir(icons_dir->str)) { log_error("Error while creating directory %s", icons_dir->str); } - if (!mkdir_recursive(chatlogs_dir->str)) { + if (!create_dir(chatlogs_dir->str)) { log_error("Error while creating directory %s", chatlogs_dir->str); } - if (!mkdir_recursive(logs_dir->str)) { + if (!create_dir(logs_dir->str)) { log_error("Error while creating directory %s", logs_dir->str); } - if (!mkdir_recursive(plugins_dir->str)) { + if (!create_dir(plugins_dir->str)) { log_error("Error while creating directory %s", plugins_dir->str); } @@ -120,7 +122,7 @@ files_get_log_file(const char* const log_file) if (log_file) { gchar* log_path = g_path_get_dirname(log_file); - if (!mkdir_recursive(log_path)) { + if (!create_dir(log_path)) { log_error("Error while creating directory %s", log_path); } g_free(log_path); @@ -149,13 +151,8 @@ gchar* files_get_config_path(const char* const config_base) { gchar* xdg_config = _files_get_xdg_config_home(); - GString* file_str = g_string_new(xdg_config); - g_string_append(file_str, "/profanity/"); - g_string_append(file_str, config_base); - gchar* result = g_strdup(file_str->str); + gchar* result = g_strdup_printf("%s/profanity/%s", xdg_config, config_base); g_free(xdg_config); - g_string_free(file_str, TRUE); - return result; } @@ -163,13 +160,8 @@ gchar* files_get_data_path(const char* const data_base) { gchar* xdg_data = _files_get_xdg_data_home(); - GString* file_str = g_string_new(xdg_data); - g_string_append(file_str, "/profanity/"); - g_string_append(file_str, data_base); - gchar* result = g_strdup(file_str->str); + gchar* result = g_strdup_printf("%s/profanity/%s", xdg_data, data_base); g_free(xdg_data); - g_string_free(file_str, TRUE); - return result; } @@ -177,20 +169,34 @@ gchar* files_get_account_data_path(const char* const specific_dir, const char* const jid) { gchar* data_dir = files_get_data_path(specific_dir); - GString* result_dir = g_string_new(data_dir); - g_free(data_dir); - gchar* account_dir = str_replace(jid, "@", "_at_"); - g_string_append(result_dir, "/"); - g_string_append(result_dir, account_dir); - g_free(account_dir); - gchar* result = g_strdup(result_dir->str); - g_string_free(result_dir, TRUE); + gchar* result = g_strdup_printf("%s/%s", data_dir, account_dir); + + g_free(account_dir); + g_free(data_dir); return result; } +gchar* +files_file_in_account_data_path(const char* const specific_dir, const char* const jid, const char* const file_name) +{ + gchar* data_path = files_get_account_data_path(specific_dir, jid); + + if (!create_dir(data_path)) { + g_free(data_path); + return NULL; + } + + if (!file_name) { + return data_path; + } + gchar* filename = g_strdup_printf("%s/%s", data_path, file_name); + g_free(data_path); + return filename; +} + static char* _files_get_xdg_config_home(void) { diff --git a/src/config/files.h b/src/config/files.h index a6b5a730..c0000ce1 100644 --- a/src/config/files.h +++ b/src/config/files.h @@ -69,4 +69,7 @@ gchar* files_get_account_data_path(const char* const specific_dir, const char* c gchar* files_get_log_file(const char* const log_file); gchar* files_get_inputrc_file(void); +gchar* +files_file_in_account_data_path(const char* const specific_dir, const char* const jid, const char* const file_name); + #endif diff --git a/src/database.c b/src/database.c index c04dcff9..4656ae79 100644 --- a/src/database.c +++ b/src/database.c @@ -56,27 +56,7 @@ static prof_msg_type_t _get_message_type_type(const char* const type); static char* _get_db_filename(ProfAccount* account) { - gchar* database_dir = files_get_account_data_path(DIR_DATABASE, account->jid); - - int res = g_mkdir_with_parents(database_dir, S_IRWXU); - if (res == -1) { - const char* errmsg = strerror(errno); - if (errmsg) { - log_error("DATABASE: error creating directory: %s, %s", database_dir, errmsg); - } else { - log_error("DATABASE: creating directory: %s", database_dir); - } - g_free(database_dir); - return NULL; - } - - GString* chatlog_filename = g_string_new(database_dir); - g_string_append(chatlog_filename, "/chatlog.db"); - gchar* result = g_strdup(chatlog_filename->str); - g_string_free(chatlog_filename, TRUE); - g_free(database_dir); - - return result; + return files_file_in_account_data_path(DIR_DATABASE, account->jid, "chatlog.db"); } gboolean diff --git a/src/log.c b/src/log.c index 8249d70a..546f7804 100644 --- a/src/log.c +++ b/src/log.c @@ -90,9 +90,7 @@ static struct dated_chat_log* _create_log(const char* const other, const char* c static struct dated_chat_log* _create_groupchat_log(const char* const room, const char* const login); static void _free_chat_log(struct dated_chat_log* dated_log); static gboolean _key_equals(void* key1, void* key2); -static char* _get_log_filename(const char* const other, const char* const login, GDateTime* dt, gboolean create); -static char* _get_groupchat_log_filename(const char* const room, const char* const login, GDateTime* dt, - gboolean create); +static char* _get_log_filename(const char* const other, const char* const login, GDateTime* dt, gboolean is_room); static void _rotate_log_file(void); static char* _log_string_from_level(log_level_t level); static void _chat_log_chat(const char* const login, const char* const other, const gchar* const msg, @@ -612,7 +610,7 @@ static struct dated_chat_log* _create_log(const char* const other, const char* const login) { GDateTime* now = g_date_time_new_now_local(); - char* filename = _get_log_filename(other, login, now, TRUE); + char* filename = _get_log_filename(other, login, now, FALSE); struct dated_chat_log* new_log = malloc(sizeof(struct dated_chat_log)); new_log->filename = strdup(filename); @@ -627,7 +625,7 @@ static struct dated_chat_log* _create_groupchat_log(const char* const room, const char* const login) { GDateTime* now = g_date_time_new_now_local(); - char* filename = _get_groupchat_log_filename(room, login, now, TRUE); + char* filename = _get_log_filename(room, login, now, TRUE); struct dated_chat_log* new_log = malloc(sizeof(struct dated_chat_log)); new_log->filename = strdup(filename); @@ -677,70 +675,16 @@ _key_equals(void* key1, void* key2) } static char* -_get_log_filename(const char* const other, const char* const login, GDateTime* dt, gboolean create) +_get_log_filename(const char* const other, const char* const login, GDateTime* dt, gboolean is_room) { - char* chatlogs_dir = files_get_data_path(DIR_CHATLOGS); - GString* log_file = g_string_new(chatlogs_dir); - free(chatlogs_dir); + gchar* chatlogs_dir = files_file_in_account_data_path(DIR_CHATLOGS, login, is_room ? "rooms" : NULL); + gchar* logfile_name = g_date_time_format(dt, "%Y_%m_%d.log"); + gchar* logfile_path = files_file_in_account_data_path(chatlogs_dir, other, logfile_name); - gchar* login_dir = str_replace(login, "@", "_at_"); - g_string_append_printf(log_file, "/%s", login_dir); - if (create) { - create_dir(log_file->str); - } - free(login_dir); - - gchar* other_file = str_replace(other, "@", "_at_"); - g_string_append_printf(log_file, "/%s", other_file); - if (create) { - create_dir(log_file->str); - } - free(other_file); - - gchar* date = g_date_time_format(dt, "/%Y_%m_%d.log"); - g_string_append(log_file, date); - g_free(date); - - char* result = strdup(log_file->str); - g_string_free(log_file, TRUE); - - return result; -} - -static char* -_get_groupchat_log_filename(const char* const room, const char* const login, GDateTime* dt, gboolean create) -{ - char* chatlogs_dir = files_get_data_path(DIR_CHATLOGS); - GString* log_file = g_string_new(chatlogs_dir); - free(chatlogs_dir); - - gchar* login_dir = str_replace(login, "@", "_at_"); - g_string_append_printf(log_file, "/%s", login_dir); - if (create) { - create_dir(log_file->str); - } - free(login_dir); - - g_string_append(log_file, "/rooms"); - if (create) { - create_dir(log_file->str); - } + g_free(logfile_name); + g_free(chatlogs_dir); - gchar* room_file = str_replace(room, "@", "_at_"); - g_string_append_printf(log_file, "/%s", room_file); - if (create) { - create_dir(log_file->str); - } - free(room_file); - - gchar* date = g_date_time_format(dt, "/%Y_%m_%d.log"); - g_string_append(log_file, date); - g_free(date); - - char* result = strdup(log_file->str); - g_string_free(log_file, TRUE); - - return result; + return logfile_path; } static char* diff --git a/src/omemo/omemo.c b/src/omemo/omemo.c index 87599de0..c46714d6 100644 --- a/src/omemo/omemo.c +++ b/src/omemo/omemo.c @@ -231,7 +231,11 @@ omemo_on_connect(ProfAccount* account) omemo_ctx.device_list_handler = g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL); omemo_ctx.known_devices = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)_g_hash_table_free); - gchar* omemo_dir = files_get_account_data_path(DIR_OMEMO, account->jid); + gchar* omemo_dir = files_file_in_account_data_path(DIR_OMEMO, account->jid, NULL); + if (!omemo_dir) { + log_error("[OMEMO] failed creating directory"); + return; + } omemo_ctx.identity_filename = g_string_new(omemo_dir); g_string_append(omemo_ctx.identity_filename, "/identity.txt"); @@ -242,17 +246,6 @@ omemo_on_connect(ProfAccount* account) omemo_ctx.known_devices_filename = g_string_new(omemo_dir); g_string_append(omemo_ctx.known_devices_filename, "/known_devices.txt"); - errno = 0; - int res = g_mkdir_with_parents(omemo_dir, S_IRWXU); - if (res == -1) { - const char* errmsg = strerror(errno); - if (errmsg) { - log_error("[OMEMO] error creating directory: %s, %s", omemo_dir, errmsg); - } else { - log_error("[OMEMO] creating directory: %s", omemo_dir); - } - } - g_free(omemo_dir); omemo_devicelist_subscribe(); diff --git a/src/otr/otr.c b/src/otr/otr.c index 5f45e23c..562914a2 100644 --- a/src/otr/otr.c +++ b/src/otr/otr.c @@ -129,19 +129,20 @@ static void cb_write_fingerprints(void* opdata) { gcry_error_t err = 0; - gchar* otr_dir = files_get_account_data_path(DIR_OTR, jid); - - GString* fpsfilename = g_string_new(otr_dir); - g_string_append(fpsfilename, "/fingerprints.txt"); + gchar* fpsfilename = files_file_in_account_data_path(DIR_OTR, jid, "fingerprints.txt"); + if (!fpsfilename) { + log_error("Failed to create fingerprints file"); + cons_show_error("Failed to create fingerprints file"); + return; + } - err = otrl_privkey_write_fingerprints(user_state, fpsfilename->str); + err = otrl_privkey_write_fingerprints(user_state, fpsfilename); if (err != GPG_ERR_NO_ERROR) { log_error("Failed to write fingerprints file"); - cons_show_error("Failed to create fingerprints file"); + cons_show_error("Failed to write fingerprints file"); } - g_free(otr_dir); - g_string_free(fpsfilename, TRUE); + g_free(fpsfilename); } static void @@ -212,12 +213,10 @@ otr_on_connect(ProfAccount* account) jid = strdup(account->jid); log_info("Loading OTR key for %s", jid); - gchar* otr_dir = files_get_account_data_path(DIR_OTR, jid); - - if (!mkdir_recursive(otr_dir)) { - log_error("Could not create %s for account %s.", otr_dir, jid); - cons_show_error("Could not create %s for account %s.", otr_dir, jid); - g_free(otr_dir); + gchar* otr_dir = files_file_in_account_data_path(DIR_OTR, jid, NULL); + if (!otr_dir) { + log_error("Could not create directory for account %s.", jid); + cons_show_error("Could not create directory for account %s.", jid); return; } @@ -381,12 +380,11 @@ otr_keygen(ProfAccount* account) jid = strdup(account->jid); log_info("Generating OTR key for %s", jid); - gchar* otr_dir = files_get_account_data_path(DIR_OTR, jid); + gchar* otr_dir = files_file_in_account_data_path(DIR_OTR, jid, NULL); - if (!mkdir_recursive(otr_dir)) { - log_error("Could not create %s for account %s.", otr_dir, jid); - cons_show_error("Could not create %s for account %s.", otr_dir, jid); - g_free(otr_dir); + if (!otr_dir) { + log_error("Could not create directory for account %s.", jid); + cons_show_error("Could not create directory for account %s.", jid); return; } diff --git a/src/pgp/gpg.c b/src/pgp/gpg.c index a56b34e3..99d37c64 100644 --- a/src/pgp/gpg.c +++ b/src/pgp/gpg.c @@ -161,27 +161,13 @@ p_gpg_close(void) void p_gpg_on_connect(const char* const barejid) { - gchar* pubsfile = files_get_account_data_path(DIR_PGP, barejid); - - // mkdir if doesn't exist for account - errno = 0; - int res = g_mkdir_with_parents(pubsfile, S_IRWXU); - if (res == -1) { - const char* errmsg = strerror(errno); - if (errmsg) { - log_error("Error creating directory: %s, %s", pubsfile, errmsg); - } else { - log_error("Error creating directory: %s", pubsfile); - } + pubsloc = files_file_in_account_data_path(DIR_PGP, barejid, "pubkeys"); + if (!pubsloc) { + log_error("Could not create directory for account %s.", barejid); + cons_show_error("Could not create directory for account %s.", barejid); + return; } - // create or read publickeys - GString* pubtmp = g_string_new(pubsfile); - g_string_append(pubtmp, "/pubkeys"); - pubsloc = pubtmp->str; - g_string_free(pubtmp, FALSE); - g_free(pubsfile); - if (g_file_test(pubsloc, G_FILE_TEST_EXISTS)) { g_chmod(pubsloc, S_IRUSR | S_IWUSR); } diff --git a/src/tools/editor.c b/src/tools/editor.c new file mode 100644 index 00000000..f8dc5b22 --- /dev/null +++ b/src/tools/editor.c @@ -0,0 +1,125 @@ +/* + * editor.c + * vim: expandtab:ts=4:sts=4:sw=4 + * + * Copyright (C) 2022 Michael Vetter <jubalh@iodoru.org> + * Copyright (C) 2022 MarcoPolo PasTonMolo <marcopolopastonmolo@protonmail.com> + * Copyright (C) 2022 Steffen Jaeckel <jaeckel-floss@eyet-services.de> + * + * This file is part of Profanity. + * + * Profanity is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Profanity is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Profanity. If not, see <https://www.gnu.org/licenses/>. + * + * In addition, as a special exception, the copyright holders give permission to + * link the code of portions of this program with the OpenSSL library under + * certain conditions as described in each individual source file, and + * distribute linked combinations including the two. + * + * You must obey the GNU General Public License in all respects for all of the + * code used other than OpenSSL. If you modify file(s) with this exception, you + * may extend this exception to your version of the file(s), but you are not + * obligated to do so. If you do not wish to do so, delete this exception + * statement from your version. If you delete this exception statement from all + * source files in the program, then also delete it here. + * + */ + +#include <fcntl.h> +#include <glib.h> +#include <errno.h> +#include <sys/wait.h> +#include <unistd.h> + +#include "config/files.h" +#include "config/preferences.h" +#include "log.h" + +// Returns true if an error occurred +gboolean +get_message_from_editor(gchar* message, gchar** returned_message) +{ + /* Make sure that there's no junk in the return-pointer in error cases */ + *returned_message = NULL; + + gchar* filename = NULL; + GError* glib_error = NULL; + char* jid = connection_get_barejid(); + if (jid) { + filename = files_file_in_account_data_path(DIR_EDITOR, jid, "compose.md"); + } else { + log_debug("[Editor] could not get JID"); + gchar* data_dir = files_get_data_path(DIR_EDITOR); + if (!create_dir(data_dir)) { + return TRUE; + } + filename = g_strdup_printf("%s/compose.md", data_dir); + g_free(data_dir); + } + if (!filename) { + log_error("[Editor] something went wrong while creating compose file"); + return TRUE; + } + + gsize messagelen = strlen(message); + if (!g_file_set_contents(filename, message, messagelen, &glib_error)) { + log_error("[Editor] could not write to %s: %s", filename, glib_error ? glib_error->message : "No GLib error given"); + if (glib_error) { + g_error_free(glib_error); + } + g_free(filename); + return TRUE; + } + + char* editor = prefs_get_string(PREF_COMPOSE_EDITOR); + + // Fork / exec + pid_t pid = fork(); + if (pid == 0) { + int x = execlp(editor, editor, filename, (char*)NULL); + if (x == -1) { + log_error("[Editor] Failed to exec %s", editor); + } + _exit(EXIT_FAILURE); + } else { + if (pid == -1) { + return TRUE; + } + waitpid(pid, NULL, 0); + + gchar* contents; + gsize length; + if (!g_file_get_contents(filename, &contents, &length, &glib_error)) { + log_error("[Editor] could not read from %s: %s", filename, glib_error ? glib_error->message : "No GLib error given"); + if (glib_error) { + g_error_free(glib_error); + } + g_free(filename); + g_free(editor); + return TRUE; + } + /* Remove all trailing new-line characters */ + g_strchomp(contents); + *returned_message = contents; + if (remove(filename) != 0) { + log_error("[Editor] error during file deletion of %s", filename); + } else { + log_debug("[Editor] deleted file: %s", filename); + } + g_free(filename); + } + + g_free(editor); + + return FALSE; +} diff --git a/src/tools/editor.h b/src/tools/editor.h new file mode 100644 index 00000000..4b239a5b --- /dev/null +++ b/src/tools/editor.h @@ -0,0 +1,44 @@ +/* + * editor.h + * vim: expandtab:ts=4:sts=4:sw=4 + * + * Copyright (C) 2022 Michael Vetter <jubalh@iodoru.org> + * Copyright (C) 2022 MarcoPolo PasTonMolo <marcopolopastonmolo@protonmail.com> + * + * This file is part of Profanity. + * + * Profanity is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Profanity is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Profanity. If not, see <https://www.gnu.org/licenses/>. + * + * In addition, as a special exception, the copyright holders give permission to + * link the code of portions of this program with the OpenSSL library under + * certain conditions as described in each individual source file, and + * distribute linked combinations including the two. + * + * You must obey the GNU General Public License in all respects for all of the + * code used other than OpenSSL. If you modify file(s) with this exception, you + * may extend this exception to your version of the file(s), but you are not + * obligated to do so. If you do not wish to do so, delete this exception + * statement from your version. If you delete this exception statement from all + * source files in the program, then also delete it here. + * + */ + +#ifndef TOOLS_EDITOR_H +#define TOOLS_EDITOR_H + +#include <glib.h> + +gboolean get_message_from_editor(gchar* message, gchar** returned_message); + +#endif diff --git a/src/ui/inputwin.c b/src/ui/inputwin.c index 4ea773c8..9e34c0b6 100644 --- a/src/ui/inputwin.c +++ b/src/ui/inputwin.c @@ -74,6 +74,7 @@ #include "xmpp/muc.h" #include "xmpp/roster_list.h" #include "xmpp/chat_state.h" +#include "tools/editor.h" static WINDOW* inp_win; static int pad_start = 0; @@ -133,6 +134,7 @@ static int _inp_rl_subwin_pageup_handler(int count, int key); static int _inp_rl_subwin_pagedown_handler(int count, int key); static int _inp_rl_startup_hook(void); static int _inp_rl_down_arrow_handler(int count, int key); +static int _inp_rl_send_to_editor(int count, int key); void create_input_window(void) @@ -434,6 +436,7 @@ _inp_rl_addfuncs(void) rl_add_funmap_entry("prof_subwin_pagedown", _inp_rl_subwin_pagedown_handler); rl_add_funmap_entry("prof_win_clear", _inp_rl_win_clear_handler); rl_add_funmap_entry("prof_win_close", _inp_rl_win_close_handler); + rl_add_funmap_entry("prof_send_to_editor", _inp_rl_send_to_editor); } // Readline callbacks @@ -484,6 +487,7 @@ _inp_rl_startup_hook(void) rl_bind_keyseq("\\ea", _inp_rl_win_next_unread_handler); rl_bind_keyseq("\\ev", _inp_rl_win_attention_handler); rl_bind_keyseq("\\em", _inp_rl_win_attention_next_handler); + rl_bind_keyseq("\\ec", _inp_rl_send_to_editor); rl_bind_keyseq("\\e\\e[5~", _inp_rl_subwin_pageup_handler); rl_bind_keyseq("\\e[5;3~", _inp_rl_subwin_pageup_handler); @@ -582,17 +586,20 @@ _inp_rl_tab_handler(int count, int key) return 0; } - ProfWin* current = wins_get_current(); - if ((strncmp(rl_line_buffer, "/", 1) != 0) && (current->type == WIN_MUC)) { - char* result = muc_autocomplete(current, rl_line_buffer, FALSE); + if (strncmp(rl_line_buffer, "/", 1) == 0) { + ProfWin* window = wins_get_current(); + char* result = cmd_ac_complete(window, rl_line_buffer, FALSE); if (result) { rl_replace_line(result, 1); rl_point = rl_end; free(result); + return 0; } - } else if (strncmp(rl_line_buffer, "/", 1) == 0) { - ProfWin* window = wins_get_current(); - char* result = cmd_ac_complete(window, rl_line_buffer, FALSE); + } + + ProfWin* current = wins_get_current(); + if (current->type == WIN_MUC) { + char* result = muc_autocomplete(current, rl_line_buffer, FALSE); if (result) { rl_replace_line(result, 1); rl_point = rl_end; @@ -600,6 +607,7 @@ _inp_rl_tab_handler(int count, int key) } } + return 0; } @@ -610,17 +618,20 @@ _inp_rl_shift_tab_handler(int count, int key) return 0; } - ProfWin* current = wins_get_current(); - if ((strncmp(rl_line_buffer, "/", 1) != 0) && (current->type == WIN_MUC)) { - char* result = muc_autocomplete(current, rl_line_buffer, TRUE); + if (strncmp(rl_line_buffer, "/", 1) == 0) { + ProfWin* window = wins_get_current(); + char* result = cmd_ac_complete(window, rl_line_buffer, TRUE); if (result) { rl_replace_line(result, 1); rl_point = rl_end; free(result); + return 0; } - } else if (strncmp(rl_line_buffer, "/", 1) == 0) { - ProfWin* window = wins_get_current(); - char* result = cmd_ac_complete(window, rl_line_buffer, TRUE); + } + + ProfWin* current = wins_get_current(); + if (current->type == WIN_MUC) { + char* result = muc_autocomplete(current, rl_line_buffer, TRUE); if (result) { rl_replace_line(result, 1); rl_point = rl_end; @@ -877,3 +888,25 @@ _inp_rl_down_arrow_handler(int count, int key) rl_redisplay(); return 0; } + +static int +_inp_rl_send_to_editor(int count, int key) +{ + if (!rl_line_buffer) { + return 0; + } + + gchar* message = NULL; + + if (get_message_from_editor(rl_line_buffer, &message)) { + return 0; + } + + rl_replace_line(message, 0); + ui_resize(); + rl_point = rl_end; + rl_forced_update_display(); + g_free(message); + + return 0; +} diff --git a/src/xmpp/connection.c b/src/xmpp/connection.c index c5475258..d601de22 100644 --- a/src/xmpp/connection.c +++ b/src/xmpp/connection.c @@ -747,6 +747,8 @@ connection_get_ctx(void) const char* connection_get_fulljid(void) { + if (!conn.xmpp_conn) + return NULL; const char* jid = xmpp_conn_get_bound_jid(conn.xmpp_conn); if (jid) { return jid; @@ -759,10 +761,11 @@ char* connection_get_barejid(void) { const char* jid = connection_get_fulljid(); - char* result; + if (!jid) + return NULL; Jid* jidp = jid_create(jid); - result = strdup(jidp->barejid); + char* result = strdup(jidp->barejid); jid_destroy(jidp); return result; @@ -772,8 +775,9 @@ char* connection_get_user(void) { const char* jid = connection_get_fulljid(); - char* result; - result = strdup(jid); + if (!jid) + return NULL; + char* result = strdup(jid); char* split = strchr(result, '@'); *split = '\0'; |