1
0
mirror of https://github.com/profanity-im/profanity.git synced 2024-06-09 21:30:42 +00:00

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)
This commit is contained in:
Marouane L 2022-09-06 17:29:07 +01:00
parent fc8455ba34
commit f934c5b59f
No known key found for this signature in database
GPG Key ID: 20E0C88A0E7E5AF2
25 changed files with 3688 additions and 7 deletions

View File

@ -20,6 +20,7 @@ core_sources = \
src/xmpp/form.c src/xmpp/form.h \
src/xmpp/avatar.c src/xmpp/avatar.h \
src/xmpp/ox.c src/xmpp/ox.h \
src/xmpp/vcard.c src/xmpp/vcard.h src/xmpp/vcard_funcs.h \
src/event/common.c src/event/common.h \
src/event/server_events.c src/event/server_events.h \
src/event/client_events.c src/event/client_events.h \
@ -37,6 +38,7 @@ core_sources = \
src/ui/privwin.c \
src/ui/confwin.c \
src/ui/xmlwin.c \
src/ui/vcardwin.c \
src/command/cmd_defs.h src/command/cmd_defs.c \
src/command/cmd_funcs.h src/command/cmd_funcs.c \
src/command/cmd_ac.h src/command/cmd_ac.c \
@ -88,6 +90,7 @@ unittest_sources = \
src/omemo/omemo.h \
src/omemo/crypto.h \
src/omemo/store.h \
src/xmpp/vcard.h src/xmpp/vcard_funcs.h \
src/command/cmd_defs.h src/command/cmd_defs.c \
src/command/cmd_funcs.h src/command/cmd_funcs.c \
src/command/cmd_ac.h src/command/cmd_ac.c \
@ -119,11 +122,13 @@ unittest_sources = \
src/event/server_events.c src/event/server_events.h \
src/event/client_events.c src/event/client_events.h \
src/ui/tray.h src/ui/tray.c \
tests/unittests/xmpp/stub_vcard.c \
tests/unittests/xmpp/stub_avatar.c \
tests/unittests/xmpp/stub_ox.c \
tests/unittests/xmpp/stub_xmpp.c \
tests/unittests/xmpp/stub_message.c \
tests/unittests/ui/stub_ui.c tests/unittests/ui/stub_ui.h \
tests/unittests/ui/stub_vcardwin.c \
tests/unittests/log/stub_log.c \
tests/unittests/chatlog/stub_chatlog.c \
tests/unittests/database/stub_database.c \

View File

@ -41,6 +41,7 @@
#include <assert.h>
#include <libgen.h>
#include <dirent.h>
#include <ctype.h>
#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;
}

View File

@ -1268,7 +1268,8 @@ static struct cmd_t command_defs[] = {
"/time all|console|chat|muc|config|private|xml off",
"/time statusbar set <format>",
"/time statusbar off",
"/time lastactivity set <format>")
"/time lastactivity set <format>",
"/time vcard set <format>")
CMD_DESC(
"Configure time display preferences. "
"Time formats are strings supported by g_date_time_format. "
@ -1291,7 +1292,8 @@ static struct cmd_t command_defs[] = {
{ "statusbar set <format>", "Change time format in statusbar." },
{ "statusbar off", "Do not show time in status bar." },
{ "lastactivity set <format>", "Change time format for last activity." },
{ "all set <format>", "Set time for: console, chat, muc, config, private and xml windows." },
{ "vcard set <format>", "Change the time format used to display time/dates in vCard (such as birthdays)" },
{ "all set <format>", "Set time for: console, chat, muc, config, private, and xml windows." },
{ "all off", "Do not show time for: console, chat, muc, config, private and xml windows." })
CMD_EXAMPLES(
"/time console set %H:%M:%S",
@ -1582,6 +1584,124 @@ static struct cmd_t command_defs[] = {
"/autoconnect off")
},
{ "/vcard",
parse_args, 0, 7, NULL,
CMD_SUBFUNCS(
{"add", cmd_vcard_add},
{"remove", cmd_vcard_remove},
{"get", cmd_vcard_get},
{"set", cmd_vcard_set},
{"photo", cmd_vcard_photo},
{"refresh", cmd_vcard_refresh},
{"save", cmd_vcard_save})
CMD_MAINFUNC(cmd_vcard)
CMD_TAGS(
CMD_TAG_CHAT,
CMD_TAG_GROUPCHAT)
CMD_SYN(
"/vcard get [<nick|contact>]",
"/vcard photo open <nick|contact> [<index>]",
"/vcard photo save <nick|contact> [output <filepath>] [index <index>]",
"/vcard set fullname <fullname>",
"/vcard set name family <family>",
"/vcard set name given <given>",
"/vcard set name middle <middle>",
"/vcard set name prefix <prefix>",
"/vcard set name suffix <suffix>",
"/vcard set <index> [<value>]",
"/vcard set <index> pobox <value>",
"/vcard set <index> extaddr <value>",
"/vcard set <index> street <value>",
"/vcard set <index> locality <value>",
"/vcard set <index> region <value>",
"/vcard set <index> pocode <value>",
"/vcard set <index> country <value>",
"/vcard set <index> type domestic|international",
"/vcard set <index> home on|off",
"/vcard set <index> work on|off",
"/vcard set <index> voice on|off",
"/vcard set <index> fax on|off",
"/vcard set <index> pager on|off",
"/vcard set <index> msg on|off",
"/vcard set <index> cell on|off",
"/vcard set <index> video on|off",
"/vcard set <index> bbs on|off",
"/vcard set <index> modem on|off",
"/vcard set <index> isdn on|off",
"/vcard set <index> pcs on|off",
"/vcard set <index> preferred on|off",
"/vcard set <index> parcel on|off",
"/vcard set <index> postal on|off",
"/vcard set <index> internet on|off",
"/vcard set <index> x400 on|off",
"/vcard add nickname <nickname>",
"/vcard add birthday <date>",
"/vcard add address",
"/vcard add tel <number>",
"/vcard add email <userid>",
"/vcard add jid <jid>",
"/vcard add title <title>",
"/vcard add role <role>",
"/vcard add note <note>",
"/vcard add url <url>",
"/vcard remove <index>",
"/vcard refresh",
"/vcard save")
CMD_DESC(
"Read your vCard or a user's vCard, get a user's avatar via their vCard, or modify your vCard. If no arguments are given, your vCard will be displayed in a new window, or an existing vCard window.")
CMD_ARGS(
{ "get [<nick|contact>]", "Get your vCard, if a nickname/contact is provided, get that user's vCard" },
{ "photo open <nick|contact> [<index>]", "Download a user's photo from their vCard to a file, and open it. If index is not specified, download the first photo (usually avatar) from their vCard" },
{ "photo save <nick|contact>", "Download a user's photo from their vCard to a file. If index is not specified, download the first photo (usually avatar) from their vCard. If output is not specified, download the photo to profanity's photos directory." },
{ "photo open-self [<index>]", "Download a photo from your vCard to a file, and open it. If index is not specified, download the first photo (usually avatar) from your vCard" },
{ "photo save-self", "Download a photo from your vCard to a file. If index is not specified, download the first photo (usually avatar) from your vCard. If output is not specified, download the photo to profanity's photos directory. Same arguments as `photo open`" },
{ "set fullname <fullname>", "Set your vCard's fullname to the specified value" },
{ "set name family <family>", "Set your vCard's family name to the specified value" },
{ "set name given <given>", "Set your vCard's given name to the specified value" },
{ "set name middle <middle>", "Set your vCard's middle name to the specified value" },
{ "set name prefix <prefix>", "Set your vCard's prefix name to the specified value" },
{ "set name suffix <suffix>", "Set your vCard's suffix name to the specified value" },
{ "set <index> [<value>]", "Set the main field in a element in your vCard to the specified value, or if no value was specified, modify the field in an editor, This only works in elements that have one field." },
{ "set <index> pobox <value>", "Set the P.O. box in an address element in your vCard to the specified value." },
{ "set <index> extaddr <value>", "Set the extended address in an address element in your vCard to the specified value." },
{ "set <index> street <value>", "Set the street in an address element in your vCard to the specified value." },
{ "set <index> locality <value>", "Set the locality in an address element in your vCard to the specified value." },
{ "set <index> region <value>", "Set the region in an address element in your vCard to the specified value." },
{ "set <index> pocode <value>", "Set the P.O. code in an address element in your vCard to the specified value." },
{ "set <index> type domestic|international", "Set the type in an address element in your vCard to either domestic or international." },
{ "set <index> home on|off", "Set the home option in an element in your vCard. (address, telephone, e-mail only)" },
{ "set <index> work on|off", "Set the work option in an element in your vCard. (address, telephone, e-mail only)" },
{ "set <index> voice on|off", "Set the voice option in a telephone element in your vCard." },
{ "set <index> fax on|off", "Set the fax option in a telephone element in your vCard." },
{ "set <index> pager on|off", "Set the pager option in a telephone element in your vCard." },
{ "set <index> msg on|off", "Set the message option in a telephone element in your vCard." },
{ "set <index> cell on|off", "Set the cellphone option in a telephone element in your vCard." },
{ "set <index> video on|off", "Set the video option in a telephone element in your vCard." },
{ "set <index> bbs on|off", "Set the BBS option in a telephone element in your vCard." },
{ "set <index> modem on|off", "Set the modem option in a telephone element in your vCard." },
{ "set <index> isdn on|off", "Set the ISDN option in a telephone element in your vCard." },
{ "set <index> pcs on|off", "Set the PCS option in a telephone element in your vCard." },
{ "set <index> preferred on|off", "Set the preferred option in an element in your vCard. (address, telephone, e-mail only)" },
{ "set <index> parcel on|off", "Set the parcel option in an address element in your vCard." },
{ "set <index> postal on|off", "Set the postal option in an address element in your vCard." },
{ "set <index> internet on|off", "Set the internet option in an e-mail address in your vCard." },
{ "set <index> x400 on|off", "Set the X400 option in an e-mail address in your vCard." },
{ "add nickname <nickname>", "Add a nickname to your vCard" },
{ "add birthday <date>", "Add a birthday date to your vCard" },
{ "add address", "Add an address to your vCard" },
{ "add tel <number>", "Add a telephone number to your vCard" },
{ "add email <userid>", "Add an e-mail address to your vCard" },
{ "add jid <jid>", "Add a Jabber ID to your vCard" },
{ "add title <title>", "Add a title to your vCard" },
{ "add role <role>", "Add a role to your vCard" },
{ "add note <note>", "Add a note to your vCard" },
{ "add url <url>", "Add a URL to your vCard" },
{ "remove <index>", "Remove a element in your vCard by index" },
{ "refresh", "Refreshes the local copy of the current account's vCard (undoes all your unpublished modifications)" },
{ "save", "Save changes to the server" })
CMD_NOEXAMPLES
},
{ "/vercheck",
parse_args, 0, 1, NULL,
CMD_NOSUBFUNCS
@ -2559,7 +2679,8 @@ static struct cmd_t command_defs[] = {
{ "avatar", cmd_executable_avatar },
{ "urlopen", cmd_executable_urlopen },
{ "urlsave", cmd_executable_urlsave },
{ "editor", cmd_executable_editor })
{ "editor", cmd_executable_editor },
{ "vcard_photo", cmd_executable_vcard_photo })
CMD_NOMAINFUNC
CMD_TAGS(
CMD_TAG_DISCOVERY)
@ -2568,7 +2689,9 @@ static struct cmd_t command_defs[] = {
"/executable urlopen set <cmdtemplate>",
"/executable urlopen default",
"/executable urlsave set <cmdtemplate>",
"/executable urlsave default")
"/executable urlsave default",
"/executable vcard_photo set <cmdtemplate>",
"/executable vcard_photo default")
CMD_DESC(
"Configure executable that should be called upon a certain command.")
CMD_ARGS(
@ -2577,7 +2700,9 @@ static struct cmd_t command_defs[] = {
{ "urlopen default", "Restore to default settings." },
{ "urlsave set", "Set executable that is run by /url save. Takes a command template that replaces %u and %p with the URL and path respectively." },
{ "urlsave default", "Use the built-in download method for saving." },
{ "editor set", "Set editor to be used with /editor. Needs a terminal editor or a script to run a graphical editor." })
{ "editor set", "Set editor to be used with /editor. Needs a terminal editor or a script to run a graphical editor." },
{ "vcard_photo set", "Set executable that is run by /vcard photo open. Takes a command template that replaces %p with the path" },
{ "vcard_photo default", "Restore to default settings." })
CMD_EXAMPLES(
"/executable avatar xdg-open",
"/executable urlopen set \"xdg-open %u\"",
@ -2586,6 +2711,7 @@ static struct cmd_t command_defs[] = {
"/executable urlsave set \"wget %u -O %p\"",
"/executable urlsave set \"curl %u -o %p\"",
"/executable urlsave default",
"/executable vcard_photo set \"feh %p\"",
"/executable editor set vim")
},

File diff suppressed because it is too large Load Diff

View File

@ -246,6 +246,7 @@ gboolean cmd_executable_avatar(ProfWin* window, const char* const command, gchar
gboolean cmd_executable_urlopen(ProfWin* window, const char* const command, gchar** args);
gboolean cmd_executable_urlsave(ProfWin* window, const char* const command, gchar** args);
gboolean cmd_executable_editor(ProfWin* window, const char* const command, gchar** args);
gboolean cmd_executable_vcard_photo(ProfWin* window, const char* const command, gchar** args);
gboolean cmd_mam(ProfWin* window, const char* const command, gchar** args);
gboolean cmd_editor(ProfWin* window, const char* const command, gchar** args);
gboolean cmd_correct_editor(ProfWin* window, const char* const command, gchar** args);
@ -253,5 +254,13 @@ gboolean cmd_silence(ProfWin* window, const char* const command, gchar** args);
gboolean cmd_register(ProfWin* window, const char* const command, gchar** args);
gboolean cmd_mood(ProfWin* window, const char* const command, gchar** args);
gboolean cmd_stamp(ProfWin* window, const char* const command, gchar** args);
gboolean cmd_vcard(ProfWin* window, const char* const command, gchar** args);
gboolean cmd_vcard_add(ProfWin* window, const char* const command, gchar** args);
gboolean cmd_vcard_remove(ProfWin* window, const char* const command, gchar** args);
gboolean cmd_vcard_get(ProfWin* window, const char* const command, gchar** args);
gboolean cmd_vcard_photo(ProfWin* window, const char* const command, gchar** args);
gboolean cmd_vcard_refresh(ProfWin* window, const char* const command, gchar** args);
gboolean cmd_vcard_set(ProfWin* window, const char* const command, gchar** args);
gboolean cmd_vcard_save(ProfWin* window, const char* const command, gchar** args);
#endif

View File

@ -60,6 +60,7 @@
#define DIR_DOWNLOADS "downloads"
#define DIR_EDITOR "editor"
#define DIR_CERTS "certs"
#define DIR_PHOTOS "photos"
void files_create_directories(void);

View File

@ -1770,6 +1770,7 @@ _get_group(preference_t pref)
case PREF_TIME_XMLCONSOLE:
case PREF_TIME_STATUSBAR:
case PREF_TIME_LASTACTIVITY:
case PREF_TIME_VCARD:
case PREF_ROSTER:
case PREF_ROSTER_OFFLINE:
case PREF_ROSTER_RESOURCE:
@ -1850,6 +1851,7 @@ _get_group(preference_t pref)
case PREF_AVATAR_CMD:
case PREF_URL_OPEN_CMD:
case PREF_URL_SAVE_CMD:
case PREF_VCARD_PHOTO_CMD:
return PREF_GROUP_EXECUTABLES;
case PREF_AUTOAWAY_CHECK:
case PREF_AUTOAWAY_MODE:
@ -2029,6 +2031,8 @@ _get_key(preference_t pref)
return "time.statusbar";
case PREF_TIME_LASTACTIVITY:
return "time.lastactivity";
case PREF_TIME_VCARD:
return "time.vcard";
case PREF_ROSTER:
return "roster";
case PREF_ROSTER_OFFLINE:
@ -2159,6 +2163,8 @@ _get_key(preference_t pref)
return "log";
case PREF_MOOD:
return "mood";
case PREF_VCARD_PHOTO_CMD:
return "vcard.photo.cmd";
default:
return NULL;
}
@ -2269,6 +2275,8 @@ _get_default_string(preference_t pref)
return "%H:%M";
case PREF_TIME_LASTACTIVITY:
return "%d/%m/%y %H:%M:%S";
case PREF_TIME_VCARD:
return "%d/%m/%y";
case PREF_PGP_LOG:
return "on";
case PREF_CONSOLE_MUC:
@ -2293,6 +2301,8 @@ _get_default_string(preference_t pref)
return "xdg-open";
case PREF_URL_OPEN_CMD:
return "xdg-open %u";
case PREF_VCARD_PHOTO_CMD:
return "xdg-open %p";
case PREF_COMPOSE_EDITOR:
{
gchar* editor = getenv("EDITOR");

View File

@ -105,6 +105,7 @@ typedef enum {
PREF_TIME_XMLCONSOLE,
PREF_TIME_STATUSBAR,
PREF_TIME_LASTACTIVITY,
PREF_TIME_VCARD,
PREF_STATUSES,
PREF_STATUSES_CONSOLE,
PREF_STATUSES_CHAT,
@ -181,6 +182,7 @@ typedef enum {
PREF_NOTIFY_ROOM_OFFLINE,
PREF_OX_LOG,
PREF_MOOD,
PREF_VCARD_PHOTO_CMD,
} preference_t;
typedef struct prof_alias_t

View File

@ -41,6 +41,7 @@
#include "xmpp/roster_list.h"
#include "xmpp/muc.h"
#include "xmpp/xmpp.h"
#include "xmpp/vcard_funcs.h"
#include "database.h"
#include "tools/bookmark_ignore.h"
@ -73,6 +74,7 @@ ev_disconnect_cleanup(void)
#endif
log_database_close();
bookmark_ignore_on_disconnect();
vcard_user_free();
}
gboolean

View File

@ -61,6 +61,7 @@
#include "xmpp/chat_session.h"
#include "xmpp/roster_list.h"
#include "xmpp/avatar.h"
#include "xmpp/vcard_funcs.h"
#ifdef HAVE_LIBOTR
#include "otr/otr.h"
@ -101,7 +102,7 @@ sv_ev_login_account_success(char* account_name, gboolean secured)
#endif
log_database_init(account);
vcard_user_refresh();
avatar_pep_subscribe();
ui_handle_login_account_success(account, secured);

View File

@ -1517,6 +1517,10 @@ cons_time_setting(void)
char* pref_time_lastactivity = prefs_get_string(PREF_TIME_LASTACTIVITY);
cons_show("Time last activity (/time) : %s", pref_time_lastactivity);
g_free(pref_time_lastactivity);
char* pref_time_vcard = prefs_get_string(PREF_TIME_VCARD);
cons_show("Time vCard (/time) : %s", pref_time_vcard);
g_free(pref_time_vcard);
}
void
@ -2262,6 +2266,10 @@ cons_executable_setting(void)
gchar* editor = prefs_get_string(PREF_COMPOSE_EDITOR);
cons_show("Default '/editor' command (/executable editor) : %s", editor);
g_free(editor);
gchar* vcard_cmd = prefs_get_string(PREF_VCARD_PHOTO_CMD);
cons_show("Default '/vcard photo open' command (/executable vcard_photo) : %s", vcard_cmd);
g_free(vcard_cmd);
}
void

View File

@ -230,6 +230,11 @@ char* confwin_get_string(ProfConfWin* confwin);
void xmlwin_show(ProfXMLWin* xmlwin, const char* const msg);
char* xmlwin_get_string(ProfXMLWin* xmlwin);
// vCard window
void vcardwin_show_vcard_config(ProfVcardWin* vcardwin);
char* vcardwin_get_string(ProfVcardWin* vcardwin);
void vcardwin_update(void);
// Input window
char* inp_readline(void);
void inp_nonblocking(gboolean reset);
@ -371,6 +376,7 @@ ProfWin* win_create_muc(const char* const roomjid);
ProfWin* win_create_config(const char* const title, DataForm* form, ProfConfWinCallback submit, ProfConfWinCallback cancel, const void* userdata);
ProfWin* win_create_private(const char* const fulljid);
ProfWin* win_create_plugin(const char* const plugin_name, const char* const tag);
ProfWin* win_create_vcard(vCard* vcard);
void win_update_virtual(ProfWin* window);
void win_free(ProfWin* window);
gboolean win_notify_remind(ProfWin* window);
@ -396,6 +402,8 @@ void win_show_occupant(ProfWin* window, Occupant* occupant);
void win_show_occupant_info(ProfWin* window, const char* const room, Occupant* occupant);
void win_show_contact(ProfWin* window, PContact contact);
void win_show_info(ProfWin* window, PContact contact);
void win_show_vcard(ProfWin* window, vCard* vcard);
void win_clear(ProfWin* window);
char* win_get_tab_identifier(ProfWin* window);
char* win_to_string(ProfWin* window);

75
src/ui/vcardwin.c Normal file
View File

@ -0,0 +1,75 @@
/*
* vcardwin.c
* vim: expandtab:ts=4:sts=4:sw=4
*
* Copyright (C) 2022 Marouane L. <techmetx11@disroot.org>
*
* 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 "ui/ui.h"
#include "ui/window_list.h"
#include "xmpp/vcard.h"
void
vcardwin_show_vcard_config(ProfVcardWin* vcardwin)
{
ProfWin* window = &vcardwin->window;
win_clear(window);
win_show_vcard(window, vcardwin->vcard);
win_println(window, THEME_DEFAULT, "-", "Use '/vcard save' to save changes.");
win_println(window, THEME_DEFAULT, "-", "Use '/help vcard' for more information.");
}
char*
vcardwin_get_string(ProfVcardWin* vcardwin)
{
GString* string = g_string_new("vCard: ");
char* jid = connection_get_barejid();
g_string_append(string, jid);
if (vcardwin->vcard && vcardwin->vcard->modified) {
g_string_append(string, " (modified)");
}
free(jid);
return g_string_free(string, FALSE);
}
void
vcardwin_update(void)
{
ProfVcardWin* win = wins_get_vcard();
if (win) {
vcardwin_show_vcard_config(win);
}
}

View File

@ -52,6 +52,7 @@
#include "tools/autocomplete.h"
#include "ui/buffer.h"
#include "xmpp/chat_state.h"
#include "xmpp/vcard.h"
#define LAYOUT_SPLIT_MEMCHECK 12345671
#define PROFCHATWIN_MEMCHECK 22374522
@ -60,6 +61,7 @@
#define PROFCONFWIN_MEMCHECK 64334685
#define PROFXMLWIN_MEMCHECK 87333463
#define PROFPLUGINWIN_MEMCHECK 43434777
#define PROFVCARDWIN_MEMCHECK 68947523
typedef enum {
FIELD_HIDDEN,
@ -140,7 +142,8 @@ typedef enum {
WIN_CONFIG,
WIN_PRIVATE,
WIN_XML,
WIN_PLUGIN
WIN_PLUGIN,
WIN_VCARD
} win_type_t;
typedef struct prof_win_t
@ -239,4 +242,11 @@ typedef struct prof_plugin_win_t
unsigned long memcheck;
} ProfPluginWin;
typedef struct prof_vcard_win_t
{
ProfWin window;
vCard* vcard;
unsigned long memcheck;
} ProfVcardWin;
#endif

View File

@ -281,6 +281,19 @@ win_create_plugin(const char* const plugin_name, const char* const tag)
return &new_win->window;
}
ProfWin*
win_create_vcard(vCard* vcard)
{
ProfVcardWin* new_win = malloc(sizeof(ProfVcardWin));
new_win->window.type = WIN_VCARD;
new_win->window.layout = _win_create_simple_layout();
new_win->vcard = vcard;
new_win->memcheck = PROFVCARDWIN_MEMCHECK;
return &new_win->window;
}
char*
win_get_title(ProfWin* window)
{
@ -351,7 +364,22 @@ win_get_title(ProfWin* window)
assert(pluginwin->memcheck == PROFPLUGINWIN_MEMCHECK);
return strdup(pluginwin->tag);
}
if (window->type == WIN_VCARD) {
ProfVcardWin* vcardwin = (ProfVcardWin*)window;
assert(vcardwin->memcheck == PROFVCARDWIN_MEMCHECK);
GString* title = g_string_new("vCard ");
char* jid = connection_get_barejid();
g_string_append(title, jid);
if (vcardwin->vcard->modified) {
g_string_append(title, " *");
}
free(jid);
return g_string_free(title, FALSE);
}
return NULL;
}
@ -474,6 +502,11 @@ win_to_string(ProfWin* window)
g_string_free(gstring, FALSE);
return res;
}
case WIN_VCARD:
{
ProfVcardWin* vcardwin = (ProfVcardWin*)window;
return vcardwin_get_string(vcardwin);
}
default:
return NULL;
}
@ -1082,6 +1115,162 @@ win_show_info(ProfWin* window, PContact contact)
g_list_free(ordered_resources);
}
void
win_show_vcard(ProfWin* window, vCard* vcard)
{
GList* pointer;
int index = 0;
if (vcard->fullname) {
win_println(window, THEME_DEFAULT, "!", "Full name: %s", vcard->fullname);
}
if (vcard->name.family || vcard->name.given || vcard->name.middle || vcard->name.prefix || vcard->name.suffix) {
win_println(window, THEME_DEFAULT, "!", "Name: ");
if (vcard->name.family) {
win_println(window, THEME_DEFAULT, "!", " Family: %s", vcard->name.family);
}
if (vcard->name.given) {
win_println(window, THEME_DEFAULT, "!", " Given: %s", vcard->name.given);
}
if (vcard->name.middle) {
win_println(window, THEME_DEFAULT, "!", " Middle: %s", vcard->name.middle);
}
if (vcard->name.prefix) {
win_println(window, THEME_DEFAULT, "!", " Prefix: %s", vcard->name.prefix);
}
if (vcard->name.suffix) {
win_println(window, THEME_DEFAULT, "!", " Suffix: %s", vcard->name.suffix);
}
}
index = 0;
for (pointer = g_queue_peek_head_link(vcard->elements); pointer != NULL; pointer = pointer->next, index++) {
assert(pointer->data != NULL);
vcard_element_t* element = (vcard_element_t*)pointer->data;
switch (element->type) {
case VCARD_NICKNAME:
{
win_println(window, THEME_DEFAULT, "!", "[%d] Nickname: %s", index, element->nickname);
break;
}
case VCARD_PHOTO:
{
if (element->photo.external) {
win_println(window, THEME_DEFAULT, "!", "[%d] Photo, External value: %s", index, element->photo.extval);
} else {
win_println(window, THEME_DEFAULT, "!", "[%d] Photo (%s), size: %zu", index, element->photo.type, element->photo.length);
}
break;
}
case VCARD_BIRTHDAY:
{
char* date_format = prefs_get_string(PREF_TIME_VCARD);
gchar* date = g_date_time_format(element->birthday, date_format);
g_free(date_format);
assert(date != NULL);
win_println(window, THEME_DEFAULT, "!", "[%d] Birthday: %s", index, date);
g_free(date);
break;
}
case VCARD_ADDRESS:
{
// Print the header with flags
win_println(window, THEME_DEFAULT, "!", "[%d] Address%s%s%s%s%s%s%s", index,
(element->address.options & VCARD_HOME) ? " [home]" : "",
(element->address.options & VCARD_WORK) == VCARD_WORK ? " [work]" : "",
(element->address.options & VCARD_POSTAL) == VCARD_POSTAL ? " [postal]" : "",
(element->address.options & VCARD_PARCEL) == VCARD_PARCEL ? " [parcel]" : "",
(element->address.options & VCARD_INTL) == VCARD_INTL ? " [international]" : "",
(element->address.options & VCARD_DOM) == VCARD_DOM ? " [domestic]" : "",
(element->address.options & VCARD_PREF) == VCARD_PREF ? " [preferred]" : "");
if (element->address.pobox) {
win_println(window, THEME_DEFAULT, "!", " P.O. Box: %s", element->address.pobox);
}
if (element->address.extaddr) {
win_println(window, THEME_DEFAULT, "!", " Extended address: %s", element->address.extaddr);
}
if (element->address.street) {
win_println(window, THEME_DEFAULT, "!", " Street: %s", element->address.street);
}
if (element->address.locality) {
win_println(window, THEME_DEFAULT, "!", " Locality: %s", element->address.locality);
}
if (element->address.region) {
win_println(window, THEME_DEFAULT, "!", " Region: %s", element->address.region);
}
if (element->address.pcode) {
win_println(window, THEME_DEFAULT, "!", " Postal code: %s", element->address.pcode);
}
if (element->address.country) {
win_println(window, THEME_DEFAULT, "!", " Country: %s", element->address.country);
}
break;
}
case VCARD_TELEPHONE:
{
// Print the header with flags
win_println(window, THEME_DEFAULT, "!", "[%d] Telephone%s%s%s%s%s%s%s%s%s%s%s%s%s", index,
(element->telephone.options & VCARD_HOME) ? " [home]" : "",
(element->telephone.options & VCARD_WORK) == VCARD_WORK ? " [work]" : "",
(element->telephone.options & VCARD_TEL_VOICE) == VCARD_TEL_VOICE ? " [voice]" : "",
(element->telephone.options & VCARD_TEL_FAX) == VCARD_TEL_FAX ? " [fax]" : "",
(element->telephone.options & VCARD_TEL_PAGER) == VCARD_TEL_PAGER ? " [pager]" : "",
(element->telephone.options & VCARD_TEL_MSG) == VCARD_TEL_MSG ? " [msg]" : "",
(element->telephone.options & VCARD_TEL_CELL) == VCARD_TEL_CELL ? " [cell]" : "",
(element->telephone.options & VCARD_TEL_VIDEO) == VCARD_TEL_VIDEO ? " [video]" : "",
(element->telephone.options & VCARD_TEL_BBS) == VCARD_TEL_BBS ? " [bbs]" : "",
(element->telephone.options & VCARD_TEL_MODEM) == VCARD_TEL_MODEM ? " [modem]" : "",
(element->telephone.options & VCARD_TEL_ISDN) == VCARD_TEL_ISDN ? " [isdn]" : "",
(element->telephone.options & VCARD_TEL_PCS) == VCARD_TEL_PCS ? " [pcs]" : "",
(element->telephone.options & VCARD_PREF) == VCARD_PREF ? " [preferred]" : "");
if (element->telephone.number) {
win_println(window, THEME_DEFAULT, "!", " Number: %s", element->telephone.number);
}
break;
}
case VCARD_EMAIL:
{
// Print the header with flags
win_println(window, THEME_DEFAULT, "!", "[%d] E-mail%s%s%s%s%s", index,
(element->email.options & VCARD_HOME) ? " [home]" : "",
(element->email.options & VCARD_WORK) == VCARD_WORK ? " [work]" : "",
(element->email.options & VCARD_EMAIL_X400) == VCARD_EMAIL_X400 ? " [x400]" : "",
(element->email.options & VCARD_EMAIL_INTERNET) == VCARD_EMAIL_INTERNET ? " [internet]" : "",
(element->email.options & VCARD_PREF) == VCARD_PREF ? " [preferred]" : "");
if (element->email.userid) {
win_println(window, THEME_DEFAULT, "!", " ID: %s", element->email.userid);
}
break;
}
case VCARD_JID:
{
win_println(window, THEME_DEFAULT, "!", "[%d] Jabber ID: %s", index, element->jid);
break;
}
case VCARD_TITLE:
{
win_println(window, THEME_DEFAULT, "!", "[%d] Title: %s", index, element->title);
break;
}
case VCARD_ROLE:
{
win_println(window, THEME_DEFAULT, "!", "[%d] Role: %s", index, element->role);
break;
}
case VCARD_NOTE:
{
win_println(window, THEME_DEFAULT, "!", "[%d] Note: %s", index, element->note);
break;
}
case VCARD_URL:
win_println(window, THEME_DEFAULT, "!", "[%d] URL: %s", index, element->url);
break;
}
}
}
void
win_show_status_string(ProfWin* window, const char* const from,
const char* const show, const char* const status,

View File

@ -711,6 +711,18 @@ wins_new_plugin(const char* const plugin_name, const char* const tag)
return newwin;
}
ProfWin*
wins_new_vcard(vCard* vcard)
{
GList* keys = g_hash_table_get_keys(windows);
int result = _wins_get_next_available_num(keys);
g_list_free(keys);
ProfWin* newwin = win_create_vcard(vcard);
g_hash_table_insert(windows, GINT_TO_POINTER(result), newwin);
return newwin;
}
gboolean
wins_do_notify_remind(void)
{
@ -805,6 +817,27 @@ wins_get_xmlconsole(void)
return NULL;
}
ProfVcardWin*
wins_get_vcard(void)
{
GList* values = g_hash_table_get_values(windows);
GList* curr = values;
while (curr) {
ProfWin* window = curr->data;
if (window->type == WIN_VCARD) {
ProfVcardWin* vcardwin = (ProfVcardWin*)window;
assert(vcardwin->memcheck == PROFVCARDWIN_MEMCHECK);
g_list_free(values);
return vcardwin;
}
curr = g_list_next(curr);
}
g_list_free(values);
return NULL;
}
GSList*
wins_get_chat_recipients(void)
{

View File

@ -46,6 +46,7 @@ ProfWin* wins_new_muc(const char* const roomjid);
ProfWin* wins_new_config(const char* const roomjid, DataForm* form, ProfConfWinCallback submit, ProfConfWinCallback cancel, const void* userdata);
ProfWin* wins_new_private(const char* const fulljid);
ProfWin* wins_new_plugin(const char* const plugin_name, const char* const tag);
ProfWin* wins_new_vcard(vCard* vcard);
gboolean wins_chat_exists(const char* const barejid);
GList* wins_get_private_chats(const char* const roomjid);
@ -61,6 +62,7 @@ ProfConfWin* wins_get_conf(const char* const roomjid);
ProfPrivateWin* wins_get_private(const char* const fulljid);
ProfPluginWin* wins_get_plugin(const char* const tag);
ProfXMLWin* wins_get_xmlconsole(void);
ProfVcardWin* wins_get_vcard(void);
void wins_close_plugin(char* tag);

View File

@ -2687,6 +2687,25 @@ stanza_create_avatar_metadata_publish_iq(xmpp_ctx_t* ctx, const char* img_data,
return iq;
}
xmpp_stanza_t*
stanza_create_vcard_request_iq(xmpp_ctx_t* ctx, const char* const jid, const char* const stanza_id)
{
xmpp_stanza_t* iq = xmpp_iq_new(ctx, STANZA_TYPE_GET, stanza_id);
xmpp_stanza_set_from(iq, connection_get_fulljid());
if (jid) {
xmpp_stanza_set_to(iq, jid);
}
xmpp_stanza_t* vcard = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(vcard, STANZA_NAME_VCARD);
xmpp_stanza_set_ns(vcard, STANZA_NS_VCARD);
xmpp_stanza_add_child(iq, vcard);
xmpp_stanza_release(vcard);
return iq;
}
xmpp_stanza_t*
stanza_attach_correction(xmpp_ctx_t* ctx, xmpp_stanza_t* stanza, const char* const replace_id)
{

View File

@ -123,6 +123,7 @@
#define STANZA_NAME_MOOD "mood"
#define STANZA_NAME_RECEIVED "received"
#define STANZA_NAME_SENT "sent"
#define STANZA_NAME_VCARD "vCard"
// error conditions
#define STANZA_NAME_BAD_REQUEST "bad-request"
@ -249,6 +250,7 @@
#define STANZA_NS_MOOD_NOTIFY "http://jabber.org/protocol/mood+notify"
#define STANZA_NS_STREAMS "http://etherx.jabber.org/streams"
#define STANZA_NS_XMPP_STREAMS "urn:ietf:params:xml:ns:xmpp-streams"
#define STANZA_NS_VCARD "vcard-temp"
#define STANZA_DATAFORM_SOFTWARE "urn:xmpp:dataforms:softwareinfo"
@ -413,6 +415,7 @@ void stanza_free_caps(XMPPCaps* caps);
xmpp_stanza_t* stanza_create_avatar_retrieve_data_request(xmpp_ctx_t* ctx, const char* stanza_id, const char* const item_id, const char* const jid);
xmpp_stanza_t* stanza_create_avatar_data_publish_iq(xmpp_ctx_t* ctx, const char* img_data, gsize len);
xmpp_stanza_t* stanza_create_avatar_metadata_publish_iq(xmpp_ctx_t* ctx, const char* img_data, gsize len, int height, int width);
xmpp_stanza_t* stanza_create_vcard_request_iq(xmpp_ctx_t* ctx, const char* const jid, const char* const stanza_id);
xmpp_stanza_t* stanza_create_mam_iq(xmpp_ctx_t* ctx, const char* const jid, const char* const startdate, const char* const lastid);
xmpp_stanza_t* stanza_change_password(xmpp_ctx_t* ctx, const char* const user, const char* const password);
xmpp_stanza_t* stanza_register_new_account(xmpp_ctx_t* ctx, const char* const user, const char* const password);

1613
src/xmpp/vcard.c Normal file

File diff suppressed because it is too large Load Diff

171
src/xmpp/vcard.h Normal file
View File

@ -0,0 +1,171 @@
/*
* vcard.h
* vim: expandtab:ts=4:sts=4:sw=4
*
* Copyright (C) 2022 Marouane L. <techmetx11@disroot.org>
*
* 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 XMPP_VCARD_H
#define XMPP_VCARD_H
#include <glib.h>
// 17 bits are currently used, out of (a possible) 32 bits
typedef enum {
VCARD_HOME = 1,
VCARD_WORK = 2,
VCARD_POSTAL = 4,
VCARD_PARCEL = 8,
VCARD_INTL = 16,
VCARD_PREF = 32,
VCARD_TEL_VOICE = 64,
VCARD_TEL_FAX = 128,
VCARD_TEL_PAGER = 256,
VCARD_TEL_MSG = 512,
VCARD_TEL_CELL = 1024,
VCARD_TEL_VIDEO = 2048,
VCARD_TEL_BBS = 4096,
VCARD_TEL_MODEM = 8192,
VCARD_TEL_ISDN = 16384,
VCARD_TEL_PCS = 32768,
VCARD_EMAIL_X400 = 65536,
VCARD_EMAIL_INTERNET = 131072,
VCARD_DOM = 262144
} vcard_element_options_t;
typedef struct _vcard_name
{
char *family, *given, *middle, *prefix, *suffix;
} vcard_name_t;
typedef struct _vcard_element_photo
{
union {
struct
{
guchar* data;
char* type;
gsize length;
};
char* extval;
};
gboolean external;
} vcard_element_photo_t;
typedef struct _vcard_element_address
{
char *pobox, *extaddr, *street, *locality, *region, *pcode, *country;
// Options used:
// VCARD_HOME
// VCARD_WORK
// VCARD_POSTAL
// VCARD_PARCEL
// VCARD_DOM
// VCARD_INTL
// VCARD_PREF
vcard_element_options_t options;
} vcard_element_address_t;
typedef struct _vcard_element_telephone
{
char* number;
// Options used:
// VCARD_HOME
// VCARD_WORK
// VCARD_TEL_VOICE
// VCARD_TEL_FAX
// VCARD_TEL_PAGER
// VCARD_TEL_MSG
// VCARD_TEL_CELL
// VCARD_TEL_VIDEO
// VCARD_TEL_BBS
// VCARD_TEL_MODEM
// VCARD_TEL_ISDN
// VCARD_TEL_PCS
// VCARD_PREF
vcard_element_options_t options;
} vcard_element_telephone_t;
typedef struct _vcard_element_email
{
char* userid;
// Options used:
// VCARD_HOME
// VCARD_WORK
// VCARD_EMAIL_X400
// VCARD_PREF
vcard_element_options_t options;
} vcard_element_email_t;
typedef enum _vcard_element_type {
VCARD_NICKNAME,
VCARD_PHOTO,
VCARD_BIRTHDAY,
VCARD_ADDRESS,
VCARD_TELEPHONE,
VCARD_EMAIL,
VCARD_JID,
VCARD_TITLE,
VCARD_ROLE,
VCARD_NOTE,
VCARD_URL
} vcard_element_type;
typedef struct _vcard_element
{
vcard_element_type type;
union {
char *nickname, *jid, *title, *role, *note, *url;
vcard_element_photo_t photo;
GDateTime* birthday;
vcard_element_address_t address;
vcard_element_telephone_t telephone;
vcard_element_email_t email;
};
} vcard_element_t;
typedef struct _vcard
{
// These elements are only meant to appear once (per DTD)
vcard_name_t name;
char* fullname;
gboolean modified;
// GQueue of vcard_element*
GQueue* elements;
} vCard;
#endif

66
src/xmpp/vcard_funcs.h Normal file
View File

@ -0,0 +1,66 @@
/*
* vcard_funcs.h
* vim: expandtab:ts=4:sts=4:sw=4
*
* Copyright (C) 2022 Marouane L. <techmetx11@disroot.org>
*
* 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 XMPP_VCARD_FUNCS_H
#define XMPP_VCARD_FUNCS_H
#include "ui/win_types.h"
#include "xmpp/vcard.h"
vCard* vcard_new();
void vcard_free(vCard* vcard);
void vcard_free_full(vCard* vcard);
gboolean vcard_parse(xmpp_stanza_t* vcard_xml, vCard* vcard);
void vcard_print(xmpp_ctx_t* ctx, ProfWin* window, char* jid);
void vcard_photo(xmpp_ctx_t* ctx, char* jid, char* filename, int index, gboolean open);
void vcard_user_refresh(void);
void vcard_user_save(void);
void vcard_user_set_fullname(char* fullname);
void vcard_user_set_name_family(char* family);
void vcard_user_set_name_given(char* given);
void vcard_user_set_name_middle(char* middle);
void vcard_user_set_name_prefix(char* prefix);
void vcard_user_set_name_suffix(char* suffix);
void vcard_user_add_element(vcard_element_t* element);
void vcard_user_remove_element(unsigned int index);
vcard_element_t* vcard_user_get_element_index(unsigned int index);
ProfWin* vcard_user_create_win();
void vcard_user_free(void);
#endif

View File

@ -1256,6 +1256,11 @@ win_create_plugin(const char* const plugin_name, const char* const tag)
{
return NULL;
}
ProfWin*
win_create_vcard(vCard* vcard)
{
return NULL;
}
char*
win_get_tab_identifier(ProfWin* window)

View File

@ -0,0 +1,4 @@
void
vcardwin_update(void)
{
}

View File

@ -0,0 +1,79 @@
#include "ui/ui.h"
#include "xmpp/vcard.h"
ProfWin*
vcard_user_create_win()
{
return NULL;
}
void
vcard_user_add_element(vcard_element_t* element)
{
}
void
vcard_user_remove_element(unsigned int index)
{
}
void
vcard_print(xmpp_ctx_t* ctx, ProfWin* window, char* jid)
{
}
void
vcard_photo(xmpp_ctx_t* ctx, char* jid, char* filename, int index, gboolean open)
{
}
void
vcard_user_refresh(void)
{
}
void
vcard_user_save(void)
{
}
void
vcard_user_set_fullname(char* fullname)
{
}
void
vcard_user_set_name_family(char* family)
{
}
void
vcard_user_set_name_given(char* given)
{
}
void
vcard_user_set_name_middle(char* middle)
{
}
void
vcard_user_set_name_prefix(char* prefix)
{
}
void
vcard_user_set_name_suffix(char* suffix)
{
}
vcard_element_t*
vcard_user_get_element_index(unsigned int index)
{
return NULL;
}
void
vcard_user_free(void)
{
}