From f934c5b59f2fe2c3c00a50135add4aec55ac4024 Mon Sep 17 00:00:00 2001 From: Marouane L Date: Tue, 6 Sep 2022 17:29:07 +0100 Subject: Add vCard support Only nicknames, photos, birthdays, addresses, telephone numbers, emails, JIDs, titles, roles, notes, and URLs are supported Due to the synopsis array not having enough space, `/vcard photo open-self` and `/vcard photo save-self` are not documented properly in the synopsis section of the `/vcard` command, but they are documented in the arguments section Fixed memory leak in vcard autocomplete (thanks to debXwoody) --- src/command/cmd_ac.c | 250 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) (limited to 'src/command/cmd_ac.c') diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c index 93a503d1..9a839258 100644 --- a/src/command/cmd_ac.c +++ b/src/command/cmd_ac.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "common.h" #include "config/preferences.h" @@ -131,6 +132,7 @@ static char* _lastactivity_autocomplete(ProfWin* window, const char* const input static char* _intype_autocomplete(ProfWin* window, const char* const input, gboolean previous); static char* _mood_autocomplete(ProfWin* window, const char* const input, gboolean previous); static char* _adhoc_cmd_autocomplete(ProfWin* window, const char* const input, gboolean previous); +static char* _vcard_autocomplete(ProfWin* window, const char* const input, gboolean previous); static char* _script_autocomplete_func(const char* const prefix, gboolean previous, void* context); @@ -276,6 +278,15 @@ static Autocomplete mood_ac; static Autocomplete mood_type_ac; static Autocomplete adhoc_cmd_ac; static Autocomplete lastactivity_ac; +static Autocomplete vcard_ac; +static Autocomplete vcard_photo_ac; +static Autocomplete vcard_element_ac; +static Autocomplete vcard_set_ac; +static Autocomplete vcard_name_ac; +static Autocomplete vcard_set_param_ac; +static Autocomplete vcard_togglable_param_ac; +static Autocomplete vcard_toggle_ac; +static Autocomplete vcard_address_type_ac; /*! * \brief Initialization of auto completion for commands. @@ -1181,6 +1192,89 @@ cmd_ac_init(void) lastactivity_ac = autocomplete_new(); autocomplete_add(lastactivity_ac, "set"); autocomplete_add(lastactivity_ac, "get"); + + vcard_ac = autocomplete_new(); + autocomplete_add(vcard_ac, "get"); + autocomplete_add(vcard_ac, "photo"); + autocomplete_add(vcard_ac, "set"); + autocomplete_add(vcard_ac, "add"); + autocomplete_add(vcard_ac, "remove"); + autocomplete_add(vcard_ac, "save"); + + vcard_photo_ac = autocomplete_new(); + autocomplete_add(vcard_photo_ac, "open"); + autocomplete_add(vcard_photo_ac, "save"); + + vcard_element_ac = autocomplete_new(); + autocomplete_add(vcard_element_ac, "nickname"); + autocomplete_add(vcard_element_ac, "birthday"); + autocomplete_add(vcard_element_ac, "address"); + autocomplete_add(vcard_element_ac, "tel"); + autocomplete_add(vcard_element_ac, "email"); + autocomplete_add(vcard_element_ac, "jid"); + autocomplete_add(vcard_element_ac, "title"); + autocomplete_add(vcard_element_ac, "role"); + autocomplete_add(vcard_element_ac, "note"); + autocomplete_add(vcard_element_ac, "url"); + + vcard_set_ac = autocomplete_new(); + autocomplete_add(vcard_set_ac, "fullname"); + autocomplete_add(vcard_set_ac, "name"); + + vcard_name_ac = autocomplete_new(); + autocomplete_add(vcard_name_ac, "family"); + autocomplete_add(vcard_name_ac, "given"); + autocomplete_add(vcard_name_ac, "middle"); + autocomplete_add(vcard_name_ac, "prefix"); + autocomplete_add(vcard_name_ac, "suffix"); + + vcard_set_param_ac = autocomplete_new(); + autocomplete_add(vcard_set_param_ac, "pobox"); + autocomplete_add(vcard_set_param_ac, "extaddr"); + autocomplete_add(vcard_set_param_ac, "street"); + autocomplete_add(vcard_set_param_ac, "locality"); + autocomplete_add(vcard_set_param_ac, "region"); + autocomplete_add(vcard_set_param_ac, "pocode"); + autocomplete_add(vcard_set_param_ac, "country"); + autocomplete_add(vcard_set_param_ac, "type"); + autocomplete_add(vcard_set_param_ac, "home"); + autocomplete_add(vcard_set_param_ac, "work"); + autocomplete_add(vcard_set_param_ac, "voice"); + autocomplete_add(vcard_set_param_ac, "fax"); + autocomplete_add(vcard_set_param_ac, "pager"); + autocomplete_add(vcard_set_param_ac, "msg"); + autocomplete_add(vcard_set_param_ac, "cell"); + autocomplete_add(vcard_set_param_ac, "video"); + autocomplete_add(vcard_set_param_ac, "bbs"); + autocomplete_add(vcard_set_param_ac, "modem"); + autocomplete_add(vcard_set_param_ac, "isdn"); + autocomplete_add(vcard_set_param_ac, "pcs"); + autocomplete_add(vcard_set_param_ac, "preferred"); + autocomplete_add(vcard_set_param_ac, "x400"); + + vcard_togglable_param_ac = autocomplete_new(); + autocomplete_add(vcard_togglable_param_ac, "home"); + autocomplete_add(vcard_togglable_param_ac, "work"); + autocomplete_add(vcard_togglable_param_ac, "voice"); + autocomplete_add(vcard_togglable_param_ac, "fax"); + autocomplete_add(vcard_togglable_param_ac, "pager"); + autocomplete_add(vcard_togglable_param_ac, "msg"); + autocomplete_add(vcard_togglable_param_ac, "cell"); + autocomplete_add(vcard_togglable_param_ac, "video"); + autocomplete_add(vcard_togglable_param_ac, "bbs"); + autocomplete_add(vcard_togglable_param_ac, "modem"); + autocomplete_add(vcard_togglable_param_ac, "isdn"); + autocomplete_add(vcard_togglable_param_ac, "pcs"); + autocomplete_add(vcard_togglable_param_ac, "preferred"); + autocomplete_add(vcard_togglable_param_ac, "x400"); + + vcard_toggle_ac = autocomplete_new(); + autocomplete_add(vcard_toggle_ac, "on"); + autocomplete_add(vcard_toggle_ac, "off"); + + vcard_address_type_ac = autocomplete_new(); + autocomplete_add(vcard_address_type_ac, "domestic"); + autocomplete_add(vcard_address_type_ac, "international"); } void @@ -1502,6 +1596,17 @@ cmd_ac_reset(ProfWin* window) autocomplete_reset(mood_ac); autocomplete_reset(mood_type_ac); autocomplete_reset(adhoc_cmd_ac); + + autocomplete_reset(vcard_ac); + autocomplete_reset(vcard_photo_ac); + autocomplete_reset(vcard_element_ac); + autocomplete_reset(vcard_set_ac); + autocomplete_reset(vcard_name_ac); + autocomplete_reset(vcard_set_param_ac); + autocomplete_reset(vcard_togglable_param_ac); + autocomplete_reset(vcard_toggle_ac); + autocomplete_reset(vcard_address_type_ac); + autocomplete_reset(script_ac); autocomplete_reset(lastactivity_ac); @@ -1672,6 +1777,15 @@ cmd_ac_uninit(void) autocomplete_free(intype_ac); autocomplete_free(adhoc_cmd_ac); autocomplete_free(lastactivity_ac); + autocomplete_free(vcard_ac); + autocomplete_free(vcard_photo_ac); + autocomplete_free(vcard_element_ac); + autocomplete_free(vcard_set_ac); + autocomplete_free(vcard_name_ac); + autocomplete_free(vcard_set_param_ac); + autocomplete_free(vcard_togglable_param_ac); + autocomplete_free(vcard_toggle_ac); + autocomplete_free(vcard_address_type_ac); } static void @@ -1944,6 +2058,7 @@ _cmd_ac_complete_params(ProfWin* window, const char* const input, gboolean previ g_hash_table_insert(ac_funcs, "/intype", _intype_autocomplete); g_hash_table_insert(ac_funcs, "/mood", _mood_autocomplete); g_hash_table_insert(ac_funcs, "/cmd", _adhoc_cmd_autocomplete); + g_hash_table_insert(ac_funcs, "/vcard", _vcard_autocomplete); int len = strlen(input); char parsed[len + 1]; @@ -4322,3 +4437,138 @@ _adhoc_cmd_autocomplete(ProfWin* window, const char* const input, gboolean previ return result; } + +static char* +_vcard_autocomplete(ProfWin* window, const char* const input, gboolean previous) +{ + char* result = NULL; + + gboolean parse_result = FALSE; + gchar** args = parse_args(input, 0, 7, &parse_result); + + if (parse_result && (g_strcmp0(args[0], "set") == 0)) { + gboolean space_at_end = g_str_has_suffix(input, " "); + int num_args = g_strv_length(args); + gboolean is_num = TRUE; + + if (num_args >= 2) { + for (int i = 0; i < strlen(args[1]); i++) { + if (!isdigit((int)args[1][i])) { + is_num = FALSE; + break; + } + } + } + + if ((num_args == 2 && space_at_end && is_num) || (num_args == 3 && !space_at_end && is_num)) { + GString* beginning = g_string_new("/vcard"); + g_string_append_printf(beginning, " %s %s", args[0], args[1]); + result = autocomplete_param_with_ac(input, beginning->str, vcard_set_param_ac, TRUE, previous); + g_string_free(beginning, TRUE); + if (result) { + g_strfreev(args); + return result; + } + } else if ((num_args == 3 && space_at_end && is_num && (g_strcmp0(args[2], "type") == 0)) || (num_args == 4 && !space_at_end && is_num && (g_strcmp0(args[2], "type") == 0))) { + GString* beginning = g_string_new("/vcard"); + g_string_append_printf(beginning, " %s %s %s", args[0], args[1], args[2]); + result = autocomplete_param_with_ac(input, beginning->str, vcard_address_type_ac, TRUE, previous); + g_string_free(beginning, TRUE); + if (result) { + g_strfreev(args); + return result; + } + } else if ((num_args == 3 && space_at_end && is_num && autocomplete_contains(vcard_togglable_param_ac, args[2])) || (num_args == 4 && !space_at_end && is_num && autocomplete_contains(vcard_togglable_param_ac, args[2]))) { + GString* beginning = g_string_new("/vcard"); + g_string_append_printf(beginning, " %s %s %s", args[0], args[1], args[2]); + result = autocomplete_param_with_ac(input, beginning->str, vcard_toggle_ac, TRUE, previous); + g_string_free(beginning, TRUE); + if (result) { + g_strfreev(args); + return result; + } + } else { + result = autocomplete_param_with_ac(input, "/vcard set name", vcard_name_ac, TRUE, previous); + + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/vcard set", vcard_set_ac, TRUE, previous); + + if (result) { + return result; + } + } + } + + result = autocomplete_param_with_ac(input, "/vcard add", vcard_element_ac, TRUE, previous); + + if (result) { + return result; + } + + if (window->type == WIN_MUC) { + char* unquoted = strip_arg_quotes(input); + + ProfMucWin* mucwin = (ProfMucWin*)window; + assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); + Autocomplete nick_ac = muc_roster_ac(mucwin->roomjid); + + if (nick_ac) { + result = autocomplete_param_with_ac(unquoted, "/vcard get", nick_ac, TRUE, previous); + if (result) { + free(unquoted); + return result; + } + + result = autocomplete_param_with_ac(unquoted, "/vcard photo open", nick_ac, TRUE, previous); + if (result) { + free(unquoted); + return result; + } + + result = autocomplete_param_with_ac(unquoted, "/vcard photo save", nick_ac, TRUE, previous); + if (result) { + free(unquoted); + return result; + } + } + free(unquoted); + } else { + char* unquoted = strip_arg_quotes(input); + + result = autocomplete_param_with_func(unquoted, "/vcard get", roster_contact_autocomplete, previous, NULL); + if (result) { + free(unquoted); + return result; + } + + result = autocomplete_param_with_func(unquoted, "/vcard photo open", roster_contact_autocomplete, previous, NULL); + if (result) { + free(unquoted); + return result; + } + + result = autocomplete_param_with_func(unquoted, "/vcard photo save", roster_contact_autocomplete, previous, NULL); + if (result) { + free(unquoted); + return result; + } + free(unquoted); + } + + result = autocomplete_param_with_ac(input, "/vcard photo", vcard_photo_ac, TRUE, previous); + + if (result) { + return result; + } + + result = autocomplete_param_with_ac(input, "/vcard", vcard_ac, TRUE, previous); + + if (result) { + return result; + } + + return result; +} -- cgit 1.4.1-2-gfad0