mirror of
https://github.com/bqv/weechat-xmpp/
synced 2024-11-18 03:25:37 +00:00
nicklist stuff
This commit is contained in:
parent
d566f45c6a
commit
d3ffc19378
2
.envrc
2
.envrc
@ -50,6 +50,7 @@ use_guix()
|
||||
libstrophe # Dep (strophe)
|
||||
libgcrypt # Dep (gcrypt)
|
||||
libsignal-protocol-c # Dep (libsignal)
|
||||
lmdb # Dep (lmdb)
|
||||
rnp # Dep (rnpgp)
|
||||
)
|
||||
|
||||
@ -63,5 +64,6 @@ use guix \
|
||||
--with-debug-info=weechat\
|
||||
--with-debug-info=libstrophe\
|
||||
--with-debug-info=libsignal-protocol-c\
|
||||
--with-debug-info=lmdb\
|
||||
--with-debug-info=rnp\
|
||||
clang:extra gdb
|
||||
|
2
Makefile
2
Makefile
@ -7,7 +7,7 @@ FIND=find
|
||||
INCLUDES=-Ilibstrophe $(shell xml2-config --cflags) $(shell pkg-config --cflags librnp-0) $(shell pkg-config --cflags libsignal-protocol-c)
|
||||
CFLAGS+=$(DBGCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -gdwarf-4 -Wall -Wextra -Werror-implicit-function-declaration -Wno-missing-field-initializers -D_XOPEN_SOURCE=700 $(INCLUDES)
|
||||
LDFLAGS+=$(DBGLDFLAGS) -shared -g $(DBGCFLAGS)
|
||||
LDLIBS=-lstrophe -lpthread $(shell xml2-config --libs) $(shell pkg-config --libs librnp-0) $(shell pkg-config --libs libsignal-protocol-c) -lgcrypt
|
||||
LDLIBS=-lstrophe -lpthread $(shell xml2-config --libs) $(shell pkg-config --libs librnp-0) $(shell pkg-config --libs libsignal-protocol-c) -lgcrypt -llmdb
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
LIBDIR ?= $(PREFIX)/lib
|
||||
|
10
README.org
10
README.org
@ -116,14 +116,16 @@
|
||||
* [X] [#B] Leaves
|
||||
* [X] [#B] Tracking
|
||||
* [X] [#B] Set/show topic
|
||||
* [-] OMEMO (libsignal-protocol-c / axc)
|
||||
* [-] OMEMO (libsignal-protocol-c)
|
||||
* [-] Presence
|
||||
* [X] Disco
|
||||
* [X] Disco response
|
||||
* [-] Key Generation / storage (secured_data?)
|
||||
* [-] Key Generation / storage (lmdb)
|
||||
* [X] Generation
|
||||
* [X] Storage
|
||||
* [ ] Announce
|
||||
* [?] Storage
|
||||
* [-] Announce
|
||||
* [X] Device ID
|
||||
* [ ] Bundles
|
||||
* [ ] Messages
|
||||
* [ ] [#C] MUC PMs
|
||||
* [X] [#A] Send typing notifications
|
||||
|
@ -507,7 +507,7 @@ void account__disconnect(struct t_account *account, int reconnect)
|
||||
account__set_lag(account);
|
||||
*/ // lag based on xmpp ping
|
||||
|
||||
account->disconnected = 1;
|
||||
account->disconnected = !reconnect;
|
||||
|
||||
/* send signal "account_disconnected" with account name */
|
||||
(void) weechat_hook_signal_send("xmpp_account_disconnected",
|
||||
@ -572,8 +572,6 @@ void account__close_connection(struct t_account *account)
|
||||
|
||||
int account__connect(struct t_account *account)
|
||||
{
|
||||
account->disconnected = 0;
|
||||
|
||||
if (!account->buffer)
|
||||
{
|
||||
if (!account__create_buffer(account))
|
||||
@ -587,7 +585,7 @@ int account__connect(struct t_account *account)
|
||||
connection__connect(account, &account->connection, account_jid(account),
|
||||
account_password(account), account_tls(account));
|
||||
|
||||
(void) weechat_hook_signal_send("xmpp_account_connected",
|
||||
(void) weechat_hook_signal_send("xmpp_account_connecting",
|
||||
WEECHAT_HOOK_SIGNAL_STRING, account->name);
|
||||
|
||||
return account->is_connected;
|
||||
@ -608,6 +606,7 @@ int account__timer_cb(const void *pointer, void *data, int remaining_calls)
|
||||
&& (xmpp_conn_is_connecting(ptr_account->connection)
|
||||
|| xmpp_conn_is_connected(ptr_account->connection)))
|
||||
connection__process(ptr_account->context, ptr_account->connection, 10);
|
||||
else if (ptr_account->disconnected);
|
||||
else if (ptr_account->reconnect_start > 0
|
||||
&& ptr_account->reconnect_start < time(NULL))
|
||||
{
|
||||
|
6
buffer.c
6
buffer.c
@ -155,7 +155,7 @@ int buffer__close_cb(const void *pointer, void *data,
|
||||
{
|
||||
if (ptr_account)
|
||||
{
|
||||
if (!ptr_account->disconnected)
|
||||
if (ptr_account->is_connected)
|
||||
{
|
||||
account__disconnect(ptr_account, 0);
|
||||
}
|
||||
@ -167,7 +167,7 @@ int buffer__close_cb(const void *pointer, void *data,
|
||||
{
|
||||
if (ptr_account && ptr_channel)
|
||||
{
|
||||
if (!ptr_account->disconnected)
|
||||
if (ptr_account->is_connected)
|
||||
{
|
||||
channel__free(ptr_account, ptr_channel);
|
||||
}
|
||||
@ -177,7 +177,7 @@ int buffer__close_cb(const void *pointer, void *data,
|
||||
{
|
||||
if (ptr_account && ptr_channel)
|
||||
{
|
||||
if (!ptr_account->disconnected)
|
||||
if (ptr_account->is_connected)
|
||||
{
|
||||
channel__free(ptr_account, ptr_channel);
|
||||
}
|
||||
|
135
channel.c
135
channel.c
@ -211,12 +211,28 @@ void channel__add_nicklist_groups(struct t_account *account,
|
||||
|
||||
ptr_buffer = channel ? channel->buffer : account->buffer;
|
||||
|
||||
snprintf(str_group, sizeof(str_group), "%03d|%s",
|
||||
000, "+");
|
||||
snprintf(str_group, sizeof(str_group), "%03d|%s", 000, "~");
|
||||
weechat_nicklist_add_group(ptr_buffer, NULL, str_group,
|
||||
"weechat.color.nicklist_group", 1);
|
||||
snprintf(str_group, sizeof(str_group), "%03d|%s",
|
||||
999, "...");
|
||||
snprintf(str_group, sizeof(str_group), "%03d|%s", 001, "&");
|
||||
weechat_nicklist_add_group(ptr_buffer, NULL, str_group,
|
||||
"weechat.color.nicklist_group", 1);
|
||||
snprintf(str_group, sizeof(str_group), "%03d|%s", 002, "@");
|
||||
weechat_nicklist_add_group(ptr_buffer, NULL, str_group,
|
||||
"weechat.color.nicklist_group", 1);
|
||||
snprintf(str_group, sizeof(str_group), "%03d|%s", 003, "%");
|
||||
weechat_nicklist_add_group(ptr_buffer, NULL, str_group,
|
||||
"weechat.color.nicklist_group", 1);
|
||||
snprintf(str_group, sizeof(str_group), "%03d|%s", 004, "+");
|
||||
weechat_nicklist_add_group(ptr_buffer, NULL, str_group,
|
||||
"weechat.color.nicklist_group", 1);
|
||||
snprintf(str_group, sizeof(str_group), "%03d|%s", 005, "?");
|
||||
weechat_nicklist_add_group(ptr_buffer, NULL, str_group,
|
||||
"weechat.color.nicklist_group", 1);
|
||||
snprintf(str_group, sizeof(str_group), "%03d|%s", 006, "!");
|
||||
weechat_nicklist_add_group(ptr_buffer, NULL, str_group,
|
||||
"weechat.color.nicklist_group", 1);
|
||||
snprintf(str_group, sizeof(str_group), "%03d|%s", 999, "...");
|
||||
weechat_nicklist_add_group(ptr_buffer, NULL, str_group,
|
||||
"weechat.color.nicklist_group", 1);
|
||||
}
|
||||
@ -290,6 +306,8 @@ struct t_channel *channel__new(struct t_account *account,
|
||||
account->channels = new_channel;
|
||||
account->last_channel = new_channel;
|
||||
|
||||
channel__add_nicklist_groups(account, new_channel);
|
||||
|
||||
if (type != CHANNEL_TYPE_MUC)
|
||||
{
|
||||
time_t start = time(NULL);
|
||||
@ -818,15 +836,14 @@ void channel__update_topic(struct t_channel *channel,
|
||||
|
||||
struct t_channel_member *channel__add_member(struct t_account *account,
|
||||
struct t_channel *channel,
|
||||
const char *id, const char *client,
|
||||
const char *status)
|
||||
const char *id, const char *client)
|
||||
{
|
||||
struct t_channel_member *member;
|
||||
struct t_user *user;
|
||||
|
||||
user = user__search(account, id);
|
||||
|
||||
if (weechat_strcasecmp(user->id, channel->id) == 0
|
||||
if (user && weechat_strcasecmp(user->id, channel->id) == 0
|
||||
&& channel->type == CHANNEL_TYPE_MUC)
|
||||
{
|
||||
weechat_printf_date_tags(channel->buffer, 0, "log2", "%sMUC: %s",
|
||||
@ -835,6 +852,8 @@ struct t_channel_member *channel__add_member(struct t_account *account,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(member = channel__member_search(channel, id)))
|
||||
{
|
||||
member = malloc(sizeof(struct t_channel_member));
|
||||
member->id = strdup(id);
|
||||
|
||||
@ -848,6 +867,9 @@ struct t_channel_member *channel__add_member(struct t_account *account,
|
||||
else
|
||||
channel->members = member;
|
||||
channel->last_member = member;
|
||||
}
|
||||
else if (user)
|
||||
user__nicklist_remove(account, channel, user);
|
||||
|
||||
if (user)
|
||||
user__nicklist_add(account, channel, user);
|
||||
@ -856,28 +878,45 @@ struct t_channel_member *channel__add_member(struct t_account *account,
|
||||
char *jid_resource = xmpp_jid_resource(account->context, user->id);
|
||||
if (weechat_strcasecmp(jid_bare, channel->id) == 0
|
||||
&& channel->type == CHANNEL_TYPE_MUC)
|
||||
weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,enter,log4", "%s%s %s%s%s %sentered%s %s %s%s%s",
|
||||
weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,enter,log4", "%s%s%s%s%s %s%s%s%s %s%s%s%s%s%s%s%s%s%s%s%s%s%s",
|
||||
weechat_prefix("join"),
|
||||
user__as_prefix_raw(account, jid_resource),
|
||||
client ? "(" : "", client, client ? ")" : "",
|
||||
client ? " (" : "",
|
||||
client ? client : "",
|
||||
client ? ")" : "",
|
||||
user->profile.status ? "is " : "",
|
||||
weechat_color("irc.color.message_join"),
|
||||
user->profile.status ? user->profile.status : "entered",
|
||||
weechat_color("reset"),
|
||||
channel->id,
|
||||
status ? "[" : "",
|
||||
status ? status : "",
|
||||
status ? "]" : "");
|
||||
user->profile.status_text ? " [" : "",
|
||||
user->profile.status_text ? user->profile.status_text : "",
|
||||
user->profile.status_text ? "]" : "",
|
||||
weechat_color("yellow"), " as ", weechat_color("reset"),
|
||||
user->profile.affiliation ? user->profile.affiliation : "",
|
||||
user->profile.affiliation ? " " : "",
|
||||
user->profile.role,
|
||||
user->profile.pgp_id ? weechat_color("gray") : "",
|
||||
user->profile.pgp_id ? " with PGP:" : "",
|
||||
user->profile.pgp_id ? user->profile.pgp_id : "",
|
||||
user->profile.pgp_id ? weechat_color("reset") : "");
|
||||
else
|
||||
weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,enter,log4", "%s%s (%s) %sentered%s %s %s%s%s",
|
||||
weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,enter,log4", "%s%s (%s) %s%s%s%s %s%s%s%s%s%s%s%s",
|
||||
weechat_prefix("join"),
|
||||
user__as_prefix_raw(account,
|
||||
xmpp_jid_bare(account->context, user->id)),
|
||||
xmpp_jid_resource(account->context, user->id),
|
||||
jid_resource ? user__as_prefix_raw(account, jid_bare) : "You",
|
||||
jid_resource ? jid_resource : user__as_prefix_raw(account, jid_bare),
|
||||
user->profile.status ? "is " : "",
|
||||
weechat_color("irc.color.message_join"),
|
||||
user->profile.status ? user->profile.status : "entered",
|
||||
weechat_color("reset"),
|
||||
channel->id,
|
||||
status ? "[" : "",
|
||||
status ? status : "",
|
||||
status ? "]" : "");
|
||||
user->profile.status_text ? " [" : "",
|
||||
user->profile.status_text ? user->profile.status_text : "",
|
||||
user->profile.status_text ? "]" : "",
|
||||
user->profile.pgp_id ? weechat_color("gray") : "",
|
||||
user->profile.pgp_id ? " with PGP:" : "",
|
||||
user->profile.pgp_id ? user->profile.pgp_id : "",
|
||||
user->profile.pgp_id ? weechat_color("reset") : "");
|
||||
|
||||
return member;
|
||||
}
|
||||
@ -900,56 +939,16 @@ struct t_channel_member *channel__member_search(struct t_channel *channel,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int channel__set_member_role(struct t_account *account,
|
||||
struct t_channel *channel,
|
||||
const char *id, const char *role)
|
||||
{
|
||||
struct t_channel_member *member;
|
||||
struct t_user *user;
|
||||
|
||||
user = user__search(account, id);
|
||||
if (!user)
|
||||
return 0;
|
||||
|
||||
member = channel__member_search(channel, id);
|
||||
if (!member)
|
||||
return 0;
|
||||
|
||||
member->role = strdup(role);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int channel__set_member_affiliation(struct t_account *account,
|
||||
struct t_channel *channel,
|
||||
const char *id, const char *affiliation)
|
||||
{
|
||||
struct t_channel_member *member;
|
||||
struct t_user *user;
|
||||
|
||||
user = user__search(account, id);
|
||||
if (!user)
|
||||
return 0;
|
||||
|
||||
member = channel__member_search(channel, id);
|
||||
if (!member)
|
||||
return 0;
|
||||
|
||||
member->affiliation = strdup(affiliation);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct t_channel_member *channel__remove_member(struct t_account *account,
|
||||
struct t_channel *channel,
|
||||
const char *id, const char *status)
|
||||
const char *id, const char *reason)
|
||||
{
|
||||
struct t_channel_member *member;
|
||||
struct t_user *user;
|
||||
|
||||
user = user__search(account, id);
|
||||
//if (user)
|
||||
// user__nicklist_remove(account, channel, user);
|
||||
if (user)
|
||||
user__nicklist_remove(account, channel, user);
|
||||
|
||||
member = channel__member_search(channel, id);
|
||||
if (member)
|
||||
@ -965,9 +964,9 @@ struct t_channel_member *channel__remove_member(struct t_account *account,
|
||||
weechat_color("irc.color.message_quit"),
|
||||
weechat_color("reset"),
|
||||
channel->id,
|
||||
status ? "[" : "",
|
||||
status ? status : "",
|
||||
status ? "]" : "");
|
||||
reason ? "[" : "",
|
||||
reason ? reason : "",
|
||||
reason ? "]" : "");
|
||||
else
|
||||
weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,leave,log4", "%s%s (%s) %sleft%s %s %s%s%s",
|
||||
weechat_prefix("quit"),
|
||||
@ -976,9 +975,9 @@ struct t_channel_member *channel__remove_member(struct t_account *account,
|
||||
weechat_color("irc.color.message_quit"),
|
||||
weechat_color("reset"),
|
||||
channel->id,
|
||||
status ? "[" : "",
|
||||
status ? status : "",
|
||||
status ? "]" : "");
|
||||
reason ? "[" : "",
|
||||
reason ? reason : "",
|
||||
reason ? "]" : "");
|
||||
|
||||
return member;
|
||||
}
|
||||
|
14
channel.h
14
channel.h
@ -170,20 +170,14 @@ void channel__update_purpose(struct t_channel *channel,
|
||||
|
||||
struct t_channel_member *channel__add_member(struct t_account *account,
|
||||
struct t_channel *channel,
|
||||
const char *id, const char *client,
|
||||
const char *status);
|
||||
const char *id, const char *client);
|
||||
|
||||
int channel__set_member_role(struct t_account *account,
|
||||
struct t_channel *channel,
|
||||
const char *id, const char *role);
|
||||
|
||||
int channel__set_member_affiliation(struct t_account *account,
|
||||
struct t_channel *channel,
|
||||
const char *id, const char *affiliation);
|
||||
struct t_channel_member *channel__member_search(struct t_channel *channel,
|
||||
const char *id);
|
||||
|
||||
struct t_channel_member *channel__remove_member(struct t_account *account,
|
||||
struct t_channel *channel,
|
||||
const char *id, const char *status);
|
||||
const char *id, const char *reason);
|
||||
|
||||
void channel__send_message(struct t_account *account, struct t_channel *channel,
|
||||
const char *to, const char *body);
|
||||
|
138
command.c
138
command.c
@ -6,11 +6,11 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <weechat/weechat-plugin.h>
|
||||
|
||||
#include "plugin.h"
|
||||
//#include "oauth.h"
|
||||
//#include "teaminfo.h"
|
||||
#include "account.h"
|
||||
#include "user.h"
|
||||
#include "channel.h"
|
||||
@ -18,6 +18,9 @@
|
||||
#include "message.h"
|
||||
#include "command.h"
|
||||
|
||||
#define MAM_DEFAULT_DAYS 2
|
||||
#define STR(X) #X
|
||||
|
||||
void command__display_account(struct t_account *account)
|
||||
{
|
||||
int num_channels, num_pv;
|
||||
@ -161,10 +164,12 @@ void command__add_account(const char *name, const char *jid, const char *passwor
|
||||
weechat_color("reset"));
|
||||
}
|
||||
|
||||
void command__account_add(int argc, char **argv)
|
||||
void command__account_add(struct t_gui_buffer *buffer, int argc, char **argv)
|
||||
{
|
||||
char *name, *jid = NULL, *password = NULL;
|
||||
|
||||
(void) buffer;
|
||||
|
||||
switch (argc)
|
||||
{
|
||||
case 5:
|
||||
@ -202,11 +207,12 @@ int command__connect_account(struct t_account *account)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int command__account_connect(int argc, char **argv)
|
||||
int command__account_connect(struct t_gui_buffer *buffer, int argc, char **argv)
|
||||
{
|
||||
int i, nb_connect, connect_ok;
|
||||
struct t_account *ptr_account;
|
||||
|
||||
(void) buffer;
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
@ -257,7 +263,7 @@ int command__disconnect_account(struct t_account *account)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int command__account_disconnect(int argc, char **argv)
|
||||
int command__account_disconnect(struct t_gui_buffer *buffer, int argc, char **argv)
|
||||
{
|
||||
int i, nb_disconnect, disconnect_ok;
|
||||
struct t_account *ptr_account;
|
||||
@ -268,6 +274,20 @@ int command__account_disconnect(int argc, char **argv)
|
||||
disconnect_ok = 1;
|
||||
|
||||
nb_disconnect = 0;
|
||||
if (argc < 2)
|
||||
{
|
||||
struct t_channel *ptr_channel;
|
||||
|
||||
buffer__get_account_and_channel(buffer, &ptr_account, &ptr_channel);
|
||||
|
||||
if (ptr_account)
|
||||
{
|
||||
if (!command__disconnect_account(ptr_account))
|
||||
{
|
||||
disconnect_ok = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 2; i < argc; i++)
|
||||
{
|
||||
nb_disconnect++;
|
||||
@ -292,14 +312,16 @@ int command__account_disconnect(int argc, char **argv)
|
||||
return (disconnect_ok) ? WEECHAT_RC_OK : WEECHAT_RC_ERROR;
|
||||
}
|
||||
|
||||
int command__account_reconnect(int argc, char **argv)
|
||||
int command__account_reconnect(struct t_gui_buffer *buffer, int argc, char **argv)
|
||||
{
|
||||
command__account_disconnect(argc, argv);
|
||||
return command__account_connect(argc, argv);
|
||||
command__account_disconnect(buffer, argc, argv);
|
||||
return command__account_connect(buffer, argc, argv);
|
||||
}
|
||||
|
||||
void command__account_delete(int argc, char **argv)
|
||||
void command__account_delete(struct t_gui_buffer *buffer, int argc, char **argv)
|
||||
{
|
||||
(void) buffer;
|
||||
|
||||
struct t_account *account;
|
||||
char *account_name;
|
||||
|
||||
@ -367,31 +389,31 @@ int command__account(const void *pointer, void *data,
|
||||
{
|
||||
if (weechat_strcasecmp(argv[1], "add") == 0)
|
||||
{
|
||||
command__account_add(argc, argv);
|
||||
command__account_add(buffer, argc, argv);
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
if (weechat_strcasecmp(argv[1], "connect") == 0)
|
||||
{
|
||||
command__account_connect(argc, argv);
|
||||
command__account_connect(buffer, argc, argv);
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
if (weechat_strcasecmp(argv[1], "disconnect") == 0)
|
||||
{
|
||||
command__account_disconnect(argc, argv);
|
||||
command__account_disconnect(buffer, argc, argv);
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
if (weechat_strcasecmp(argv[1], "reconnect") == 0)
|
||||
{
|
||||
command__account_reconnect(argc, argv);
|
||||
command__account_reconnect(buffer, argc, argv);
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
if (weechat_strcasecmp(argv[1], "delete") == 0)
|
||||
{
|
||||
command__account_delete(argc, argv);
|
||||
command__account_delete(buffer, argc, argv);
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
@ -478,6 +500,33 @@ int command__enter(const void *pointer, void *data,
|
||||
}
|
||||
weechat_string_free_split(jids);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *buffer_jid = weechat_buffer_get_string(buffer, "localvar_channel");
|
||||
|
||||
pres_jid = xmpp_jid_new(
|
||||
ptr_account->context,
|
||||
xmpp_jid_node(ptr_account->context, buffer_jid),
|
||||
xmpp_jid_domain(ptr_account->context, buffer_jid),
|
||||
weechat_buffer_get_string(buffer, "localvar_nick"));
|
||||
|
||||
ptr_channel = channel__search(ptr_account, buffer_jid);
|
||||
if (!ptr_channel)
|
||||
ptr_channel = channel__new(ptr_account, CHANNEL_TYPE_MUC, buffer_jid, buffer_jid);
|
||||
|
||||
pres = xmpp_presence_new(ptr_account->context);
|
||||
xmpp_stanza_set_to(pres, pres_jid);
|
||||
xmpp_stanza_set_from(pres, account_jid(ptr_account));
|
||||
|
||||
xmpp_stanza_t *pres__x = xmpp_stanza_new(ptr_account->context);
|
||||
xmpp_stanza_set_name(pres__x, "x");
|
||||
xmpp_stanza_set_ns(pres__x, "http://jabber.org/protocol/muc");
|
||||
xmpp_stanza_add_child(pres, pres__x);
|
||||
xmpp_stanza_release(pres__x);
|
||||
|
||||
xmpp_send(ptr_account->connection, pres);
|
||||
xmpp_stanza_release(pres);
|
||||
}
|
||||
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
@ -656,6 +705,58 @@ int command__me(const void *pointer, void *data,
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
int command__mam(const void *pointer, void *data,
|
||||
struct t_gui_buffer *buffer, int argc,
|
||||
char **argv, char **argv_eol)
|
||||
{
|
||||
struct t_account *ptr_account = NULL;
|
||||
struct t_channel *ptr_channel = NULL;
|
||||
int days;
|
||||
|
||||
(void) pointer;
|
||||
(void) data;
|
||||
(void) argv_eol;
|
||||
|
||||
buffer__get_account_and_channel(buffer, &ptr_account, &ptr_channel);
|
||||
|
||||
if (!ptr_account)
|
||||
return WEECHAT_RC_ERROR;
|
||||
|
||||
if (!ptr_channel)
|
||||
{
|
||||
weechat_printf(
|
||||
ptr_account->buffer,
|
||||
_("%s%s: \"%s\" command can not be executed on a account buffer"),
|
||||
weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, "mam");
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
time_t start = time(NULL);
|
||||
struct tm *ago = gmtime(&start);
|
||||
if (argc > 1)
|
||||
{
|
||||
errno = 0;
|
||||
days = strtol(argv[1], NULL, 10);
|
||||
|
||||
if (errno == 0)
|
||||
ago->tm_mday -= days;
|
||||
else
|
||||
{
|
||||
weechat_printf(
|
||||
ptr_channel->buffer,
|
||||
_("%s%s: \"%s\" is not a valid number of %s for %s"),
|
||||
weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, "days", "mam");
|
||||
ago->tm_mday -= MAM_DEFAULT_DAYS;
|
||||
}
|
||||
}
|
||||
else
|
||||
ago->tm_mday -= MAM_DEFAULT_DAYS;
|
||||
start = mktime(ago);
|
||||
channel__fetch_mam(ptr_account, ptr_channel, &start, NULL);
|
||||
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
int command__pgp(const void *pointer, void *data,
|
||||
struct t_gui_buffer *buffer, int argc,
|
||||
char **argv, char **argv_eol)
|
||||
@ -678,7 +779,7 @@ int command__pgp(const void *pointer, void *data,
|
||||
weechat_printf(
|
||||
ptr_account->buffer,
|
||||
_("%s%s: \"%s\" command can not be executed on a account buffer"),
|
||||
weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, "me");
|
||||
weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, "pgp");
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
@ -797,6 +898,15 @@ void command__init()
|
||||
if (!hook)
|
||||
weechat_printf(NULL, "Failed to setup command /me");
|
||||
|
||||
hook = weechat_hook_command(
|
||||
"mam",
|
||||
N_("retrieve mam messages for the current channel"),
|
||||
N_("[days]"),
|
||||
N_("days: number of days to fetch (default: " STR(MAM_DEFAULT_DAYS) ")"),
|
||||
NULL, &command__mam, NULL, NULL);
|
||||
if (!hook)
|
||||
weechat_printf(NULL, "Failed to setup command /mam");
|
||||
|
||||
hook = weechat_hook_command(
|
||||
"pgp",
|
||||
N_("set the target pgp key for the current channel"),
|
||||
|
139
connection.c
139
connection.c
@ -86,9 +86,9 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void
|
||||
struct t_account *account = (struct t_account *)userdata;
|
||||
struct t_user *user;
|
||||
struct t_channel *channel;
|
||||
xmpp_stanza_t *iq__x_signed, *iq__x_muc_user, *iq__x__item, *iq__c, *iq__status;
|
||||
xmpp_stanza_t *iq__x_signed, *iq__x_muc_user, *show, *iq__x__item, *iq__c, *iq__status;
|
||||
const char *from, *from_bare, *from_res, *type, *role = NULL, *affiliation = NULL, *jid = NULL;
|
||||
const char *certificate = NULL, *node = NULL, *ver = NULL;
|
||||
const char *show__text = NULL, *certificate = NULL, *node = NULL, *ver = NULL;
|
||||
char *clientid = NULL, *status;
|
||||
|
||||
from = xmpp_stanza_get_from(stanza);
|
||||
@ -97,30 +97,21 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void
|
||||
from_bare = xmpp_jid_bare(account->context, from);
|
||||
from_res = xmpp_jid_resource(account->context, from);
|
||||
type = xmpp_stanza_get_type(stanza);
|
||||
show = xmpp_stanza_get_child_by_name(stanza, "show");
|
||||
show__text = show ? xmpp_stanza_get_text(show) : NULL;
|
||||
iq__x_signed = xmpp_stanza_get_child_by_name_and_ns(
|
||||
stanza, "x", "jabber:x:signed");
|
||||
if (iq__x_signed)
|
||||
{
|
||||
certificate = xmpp_stanza_get_text(iq__x_signed);
|
||||
}
|
||||
iq__x_muc_user = xmpp_stanza_get_child_by_name_and_ns(
|
||||
stanza, "x", "http://jabber.org/protocol/muc#user");
|
||||
if (iq__x_muc_user)
|
||||
{
|
||||
iq__x__item = xmpp_stanza_get_child_by_name(iq__x_muc_user, "item");
|
||||
role = xmpp_stanza_get_attribute(iq__x__item, "role");
|
||||
affiliation = xmpp_stanza_get_attribute(iq__x__item, "affiliation");
|
||||
jid = xmpp_stanza_get_attribute(iq__x__item, "jid");
|
||||
}
|
||||
iq__c = xmpp_stanza_get_child_by_name_and_ns(
|
||||
stanza, "c", "http://jabber.org/protocol/caps");
|
||||
if (iq__c)
|
||||
{
|
||||
node = xmpp_stanza_get_attribute(iq__c, "node");
|
||||
ver = xmpp_stanza_get_attribute(iq__c, "ver");
|
||||
if (jid)
|
||||
clientid = strdup(jid);
|
||||
else if (node && ver)
|
||||
if (node && ver)
|
||||
{
|
||||
int len = strlen(node)+1+strlen(ver);
|
||||
clientid = malloc(sizeof(char)*len);
|
||||
@ -129,36 +120,76 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void
|
||||
}
|
||||
iq__status = xmpp_stanza_get_child_by_name(stanza, "status");
|
||||
status = iq__status ? xmpp_stanza_get_text(iq__status) : NULL;
|
||||
iq__x_muc_user = xmpp_stanza_get_child_by_name_and_ns(
|
||||
stanza, "x", "http://jabber.org/protocol/muc#user");
|
||||
|
||||
channel = channel__search(account, from_bare);
|
||||
if (weechat_strcasecmp(type, "unavailable") && !iq__x_muc_user && !channel)
|
||||
channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare);
|
||||
if (certificate && channel)
|
||||
|
||||
if (iq__x_muc_user)
|
||||
for (iq__x__item = xmpp_stanza_get_children(iq__x_muc_user);
|
||||
iq__x__item; iq__x__item = xmpp_stanza_get_next(iq__x__item))
|
||||
{
|
||||
if (channel->type != CHANNEL_TYPE_MUC)
|
||||
channel->pgp_id = pgp__verify(channel->buffer, account->pgp, certificate);
|
||||
weechat_printf(channel->buffer, "[PGP]\t%sKey %s from %s",
|
||||
weechat_color("gray"), channel->pgp_id, from);
|
||||
}
|
||||
if (weechat_strcasecmp(xmpp_stanza_get_name(iq__x__item), "item") != 0)
|
||||
continue;
|
||||
|
||||
role = xmpp_stanza_get_attribute(iq__x__item, "role");
|
||||
affiliation = xmpp_stanza_get_attribute(iq__x__item, "affiliation");
|
||||
jid = xmpp_stanza_get_attribute(iq__x__item, "jid");
|
||||
|
||||
user = user__search(account, from);
|
||||
if (!user)
|
||||
user = user__new(account, from,
|
||||
channel && weechat_strcasecmp(from_bare, channel->id) == 0
|
||||
? from_res : from);
|
||||
|
||||
if (!iq__x_muc_user && channel)
|
||||
user->profile.status_text = status ? strdup(status) : NULL;
|
||||
user->profile.status = show ? strdup(show__text) : NULL;
|
||||
user->is_away = show ? weechat_strcasecmp(show__text, "away") == 0 : 0;
|
||||
user->profile.role = role ? strdup(role) : NULL;
|
||||
user->profile.affiliation = affiliation && strcmp(affiliation, "none") != 0
|
||||
? strdup(affiliation) : NULL;
|
||||
if (certificate && channel)
|
||||
{
|
||||
channel__add_member(account, channel, from, clientid, status);
|
||||
user->profile.pgp_id = pgp__verify(channel->buffer, account->pgp, certificate);
|
||||
if (channel->type != CHANNEL_TYPE_MUC)
|
||||
channel->pgp_id = user->profile.pgp_id;
|
||||
}
|
||||
else if (channel)
|
||||
|
||||
if (channel)
|
||||
{
|
||||
channel__set_member_role(account, channel, from, role);
|
||||
channel__set_member_affiliation(account, channel, from, affiliation);
|
||||
if (weechat_strcasecmp(role, "none") == 0)
|
||||
channel__remove_member(account, channel, from, status);
|
||||
else
|
||||
channel__add_member(account, channel, from, clientid, status);
|
||||
channel__add_member(account, channel, from, jid ? jid : clientid);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
user = user__search(account, from);
|
||||
if (!user)
|
||||
user = user__new(account, from,
|
||||
channel && weechat_strcasecmp(from_bare, channel->id) == 0
|
||||
? from_res : from);
|
||||
user->profile.status_text = status ? strdup(status) : NULL;
|
||||
user->profile.status = show ? strdup(show__text) : NULL;
|
||||
user->profile.role = role ? strdup(role) : NULL;
|
||||
user->profile.affiliation = affiliation && strcmp(affiliation, "none") != 0
|
||||
? strdup(affiliation) : NULL;
|
||||
if (certificate && channel)
|
||||
{
|
||||
user->profile.pgp_id = pgp__verify(channel->buffer, account->pgp, certificate);
|
||||
if (channel->type != CHANNEL_TYPE_MUC)
|
||||
channel->pgp_id = user->profile.pgp_id;
|
||||
}
|
||||
|
||||
if (channel)
|
||||
{
|
||||
if (weechat_strcasecmp(type, "unavailable") == 0)
|
||||
channel__remove_member(account, channel, from, status);
|
||||
else
|
||||
channel__add_member(account, channel, from, clientid);
|
||||
}
|
||||
}
|
||||
|
||||
if (clientid)
|
||||
@ -219,8 +250,7 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *
|
||||
channel__add_typing(channel, user);
|
||||
weechat_printf(channel->buffer, "...\t%s%s typing",
|
||||
weechat_color("gray"),
|
||||
weechat_strcasecmp(from_bare, channel->id) == 0
|
||||
? nick : from);
|
||||
channel->type == CHANNEL_TYPE_MUC ? nick : from);
|
||||
}
|
||||
|
||||
sent = xmpp_stanza_get_child_by_name_and_ns(
|
||||
@ -819,19 +849,21 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd
|
||||
{
|
||||
list = xmpp_stanza_get_child_by_name_and_ns(
|
||||
item, "list", "eu.siacs.conversations.axolotl");
|
||||
if (list)
|
||||
if (list && account->omemo)
|
||||
{
|
||||
account__free_device_all(account);
|
||||
|
||||
struct t_account_device *dev = malloc(sizeof(struct t_account_device));
|
||||
struct t_account_device *dev;
|
||||
char id[64] = {0};
|
||||
int i = 0;
|
||||
|
||||
dev = malloc(sizeof(struct t_account_device));
|
||||
|
||||
dev->id = account->omemo->device_id;
|
||||
snprintf(id, sizeof(id), "%d", dev->id);
|
||||
dev->name = strdup(id);
|
||||
account__add_device(account, dev);
|
||||
|
||||
int i = 0;
|
||||
children = malloc(sizeof(xmpp_stanza_t *) * 128);
|
||||
children[i++] = stanza__iq_pubsub_publish_item_list_device(
|
||||
account->context, NULL, with_noop(dev->name));
|
||||
@ -1005,6 +1037,8 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status,
|
||||
|
||||
if (status == XMPP_CONN_CONNECT)
|
||||
{
|
||||
account->disconnected = 0;
|
||||
|
||||
xmpp_stanza_t *pres, *pres__c, *pres__status, *pres__status__text,
|
||||
*pres__x, *pres__x__text, **children;
|
||||
char cap_hash[28+1] = {0};
|
||||
@ -1113,45 +1147,10 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status,
|
||||
xmpp_send(conn, children[0]);
|
||||
xmpp_stanza_release(children[0]);
|
||||
|
||||
struct t_hashtable *variables = weechat_hashtable_new (8,
|
||||
WEECHAT_HASHTABLE_STRING,
|
||||
WEECHAT_HASHTABLE_STRING,
|
||||
NULL, NULL);
|
||||
weechat_hashtable_set(variables, "account", account->name);
|
||||
char *device_r = weechat_string_eval_expression(
|
||||
"${sec.data.xmpp_device_${account}}",
|
||||
NULL, variables, NULL);
|
||||
char *device_w = device_r;
|
||||
char *account_r = weechat_string_eval_expression(
|
||||
"${sec.data.xmpp_identity_${account}}",
|
||||
NULL, variables, NULL);
|
||||
char *account_w = account_r;
|
||||
weechat_hashtable_free(variables);
|
||||
omemo__init(account->buffer, &account->omemo, account->name);
|
||||
|
||||
omemo__init(account->buffer, &account->omemo, &device_w, &account_w);
|
||||
|
||||
if (weechat_strcasecmp(device_w, device_r) != 0)
|
||||
{
|
||||
char **command = weechat_string_dyn_alloc(256);
|
||||
weechat_string_dyn_concat(command, "/secure set ", -1);
|
||||
weechat_string_dyn_concat(command, "xmpp_device_", -1);
|
||||
weechat_string_dyn_concat(command, account->name, -1);
|
||||
weechat_string_dyn_concat(command, " ", -1);
|
||||
weechat_string_dyn_concat(command, device_w, -1);
|
||||
weechat_command(account->buffer, *command);
|
||||
weechat_string_dyn_free(command, 1);
|
||||
}
|
||||
if (weechat_strcasecmp(account_w, account_r) != 0)
|
||||
{
|
||||
char **command = weechat_string_dyn_alloc(256);
|
||||
weechat_string_dyn_concat(command, "/secure set ", -1);
|
||||
weechat_string_dyn_concat(command, "xmpp_identity_", -1);
|
||||
weechat_string_dyn_concat(command, account->name, -1);
|
||||
weechat_string_dyn_concat(command, " ", -1);
|
||||
weechat_string_dyn_concat(command, account_w, -1);
|
||||
weechat_command(account->buffer, *command);
|
||||
weechat_string_dyn_free(command, 1);
|
||||
}
|
||||
(void) weechat_hook_signal_send("xmpp_account_connected",
|
||||
WEECHAT_HOOK_SIGNAL_STRING, account->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
167
omemo.c
167
omemo.c
@ -9,6 +9,7 @@
|
||||
#include <gcrypt.h>
|
||||
#include <signal_protocol.h>
|
||||
#include <key_helper.h>
|
||||
#include <lmdb.h>
|
||||
#include <strophe.h>
|
||||
#include <weechat/weechat-plugin.h>
|
||||
|
||||
@ -90,19 +91,19 @@ signal_protocol_address* signal_protocol_address_new(const char* name, int32_t d
|
||||
return address;
|
||||
}
|
||||
|
||||
int signal_randomize(uint8_t *data, size_t len) {
|
||||
int cp_randomize(uint8_t *data, size_t len) {
|
||||
gcry_randomize(data, len, GCRY_STRONG_RANDOM);
|
||||
return SG_SUCCESS;
|
||||
}
|
||||
|
||||
int signal_random_generator(uint8_t *data, size_t len, void *user_data) {
|
||||
int cp_random_generator(uint8_t *data, size_t len, void *user_data) {
|
||||
(void) user_data;
|
||||
|
||||
gcry_randomize(data, len, GCRY_STRONG_RANDOM);
|
||||
return SG_SUCCESS;
|
||||
}
|
||||
|
||||
int signal_hmac_sha256_init(void **hmac_context, const uint8_t *key, size_t key_len, void *user_data) {
|
||||
int cp_hmac_sha256_init(void **hmac_context, const uint8_t *key, size_t key_len, void *user_data) {
|
||||
(void) user_data;
|
||||
|
||||
gcry_mac_hd_t* ctx = malloc(sizeof(gcry_mac_hd_t));
|
||||
@ -123,7 +124,7 @@ int signal_hmac_sha256_init(void **hmac_context, const uint8_t *key, size_t key_
|
||||
return SG_SUCCESS;
|
||||
}
|
||||
|
||||
int signal_hmac_sha256_update(void *hmac_context, const uint8_t *data, size_t data_len, void *user_data) {
|
||||
int cp_hmac_sha256_update(void *hmac_context, const uint8_t *data, size_t data_len, void *user_data) {
|
||||
(void) user_data;
|
||||
|
||||
gcry_mac_hd_t* ctx = hmac_context;
|
||||
@ -133,7 +134,7 @@ int signal_hmac_sha256_update(void *hmac_context, const uint8_t *data, size_t da
|
||||
return SG_SUCCESS;
|
||||
}
|
||||
|
||||
int signal_hmac_sha256_final(void *hmac_context, signal_buffer **output, void *user_data) {
|
||||
int cp_hmac_sha256_final(void *hmac_context, signal_buffer **output, void *user_data) {
|
||||
(void) user_data;
|
||||
|
||||
size_t len = gcry_mac_get_algo_maclen(GCRY_MAC_HMAC_SHA256);
|
||||
@ -150,7 +151,7 @@ int signal_hmac_sha256_final(void *hmac_context, signal_buffer **output, void *u
|
||||
return SG_SUCCESS;
|
||||
}
|
||||
|
||||
void signal_hmac_sha256_cleanup(void *hmac_context, void *user_data) {
|
||||
void cp_hmac_sha256_cleanup(void *hmac_context, void *user_data) {
|
||||
(void) user_data;
|
||||
|
||||
gcry_mac_hd_t* ctx = hmac_context;
|
||||
@ -160,7 +161,7 @@ void signal_hmac_sha256_cleanup(void *hmac_context, void *user_data) {
|
||||
}
|
||||
}
|
||||
|
||||
int signal_sha512_digest_init(void **digest_context, void *user_data) {
|
||||
int cp_sha512_digest_init(void **digest_context, void *user_data) {
|
||||
(void) user_data;
|
||||
|
||||
gcry_md_hd_t* ctx = malloc(sizeof(gcry_mac_hd_t));
|
||||
@ -176,7 +177,7 @@ int signal_sha512_digest_init(void **digest_context, void *user_data) {
|
||||
return SG_SUCCESS;
|
||||
}
|
||||
|
||||
int signal_sha512_digest_update(void *digest_context, const uint8_t *data, size_t data_len, void *user_data) {
|
||||
int cp_sha512_digest_update(void *digest_context, const uint8_t *data, size_t data_len, void *user_data) {
|
||||
(void) user_data;
|
||||
|
||||
gcry_md_hd_t* ctx = digest_context;
|
||||
@ -186,7 +187,7 @@ int signal_sha512_digest_update(void *digest_context, const uint8_t *data, size_
|
||||
return SG_SUCCESS;
|
||||
}
|
||||
|
||||
int signal_sha512_digest_final(void *digest_context, signal_buffer **output, void *user_data) {
|
||||
int cp_sha512_digest_final(void *digest_context, signal_buffer **output, void *user_data) {
|
||||
(void) user_data;
|
||||
|
||||
size_t len = gcry_md_get_algo_dlen(GCRY_MD_SHA512);
|
||||
@ -206,7 +207,7 @@ int signal_sha512_digest_final(void *digest_context, signal_buffer **output, voi
|
||||
return SG_SUCCESS;
|
||||
}
|
||||
|
||||
void signal_sha512_digest_cleanup(void *digest_context, void *user_data) {
|
||||
void cp_sha512_digest_cleanup(void *digest_context, void *user_data) {
|
||||
(void) user_data;
|
||||
|
||||
gcry_md_hd_t* ctx = digest_context;
|
||||
@ -243,7 +244,7 @@ int aes_cipher(int cipher, size_t key_len, int* algo, int* mode) {
|
||||
return SG_SUCCESS;
|
||||
}
|
||||
|
||||
int signal_encrypt(signal_buffer **output,
|
||||
int cp_encrypt(signal_buffer **output,
|
||||
int cipher,
|
||||
const uint8_t *key, size_t key_len,
|
||||
const uint8_t *iv, size_t iv_len,
|
||||
@ -320,7 +321,7 @@ no_error:
|
||||
return SG_SUCCESS;
|
||||
}
|
||||
|
||||
int signal_decrypt(signal_buffer **output,
|
||||
int cp_decrypt(signal_buffer **output,
|
||||
int cipher,
|
||||
const uint8_t *key, size_t key_len,
|
||||
const uint8_t *iv, size_t iv_len,
|
||||
@ -415,63 +416,131 @@ void omemo__log_emit_weechat(int level, const char *message, size_t len, void *u
|
||||
log_level_name[level], len, message);
|
||||
}
|
||||
|
||||
int omemo__signal_init(struct t_gui_buffer *buffer, struct t_omemo *omemo)
|
||||
int iks_get_identity_key_pair(signal_buffer **public_data, signal_buffer **private_data, void *user_data)
|
||||
{
|
||||
signal_context *global_context;
|
||||
(void) public_data;
|
||||
(void) private_data;
|
||||
(void) user_data;
|
||||
// Get the local client's identity key pair
|
||||
}
|
||||
|
||||
int iks_get_local_registration_id(void *user_data, uint32_t *registration_id)
|
||||
{
|
||||
(void) user_data;
|
||||
(void) registration_id;
|
||||
// Return the local client's registration ID
|
||||
}
|
||||
|
||||
int iks_save_identity(const signal_protocol_address *address, uint8_t *key_data, size_t key_len, void *user_data)
|
||||
{
|
||||
(void) address;
|
||||
(void) key_data;
|
||||
(void) key_len;
|
||||
(void) user_data;
|
||||
// Save a remote client's identity key
|
||||
}
|
||||
|
||||
int iks_is_trusted_identity(const signal_protocol_address *address, uint8_t *key_data, size_t key_len, void *user_data)
|
||||
{
|
||||
(void) address;
|
||||
(void) key_data;
|
||||
(void) key_len;
|
||||
(void) user_data;
|
||||
// Verify a remote client's identity key
|
||||
}
|
||||
|
||||
void iks_destroy_func(void *user_data)
|
||||
{
|
||||
(void) user_data;
|
||||
// Function called to perform cleanup when the data store context is being destroyed
|
||||
}
|
||||
|
||||
|
||||
void omemo__init(struct t_gui_buffer *buffer, struct t_omemo **omemo,
|
||||
const char *account_name)
|
||||
{
|
||||
struct t_omemo *new_omemo;
|
||||
|
||||
gcry_check_version(NULL);
|
||||
|
||||
signal_context_create(&global_context, buffer);
|
||||
signal_context_set_log_function(global_context, &omemo__log_emit_weechat);
|
||||
new_omemo = calloc(1, sizeof(**omemo));
|
||||
|
||||
struct signal_crypto_provider provider = {
|
||||
.random_func = &signal_random_generator,
|
||||
.hmac_sha256_init_func = &signal_hmac_sha256_init,
|
||||
.hmac_sha256_update_func = &signal_hmac_sha256_update,
|
||||
.hmac_sha256_final_func = &signal_hmac_sha256_final,
|
||||
.hmac_sha256_cleanup_func = &signal_hmac_sha256_cleanup,
|
||||
.sha512_digest_init_func = &signal_sha512_digest_init,
|
||||
.sha512_digest_update_func = &signal_sha512_digest_update,
|
||||
.sha512_digest_final_func = &signal_sha512_digest_final,
|
||||
.sha512_digest_cleanup_func = &signal_sha512_digest_cleanup,
|
||||
.encrypt_func = &signal_encrypt,
|
||||
.decrypt_func = &signal_decrypt,
|
||||
signal_context_create(&new_omemo->context, buffer);
|
||||
signal_context_set_log_function(new_omemo->context, &omemo__log_emit_weechat);
|
||||
|
||||
mdb_env_create(&new_omemo->db.env);
|
||||
mdb_env_set_maxdbs(new_omemo->db.env, 50);
|
||||
mdb_env_set_mapsize(new_omemo->db.env, (size_t)1048576 * 100000); // 1MB * 100000
|
||||
char *path = weechat_string_eval_expression("${weechat_data_dir}/xmpp.omemo.db",
|
||||
NULL, NULL, NULL);
|
||||
if (mdb_env_open(new_omemo->db.env, path, MDB_NOSUBDIR, 0664) != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
free(path);
|
||||
|
||||
MDB_txn *parentTransaction = NULL;
|
||||
MDB_txn *transaction;
|
||||
if (mdb_txn_begin(new_omemo->db.env, parentTransaction, 0 ? MDB_RDONLY : 0, &transaction)) {
|
||||
//Error
|
||||
}
|
||||
|
||||
if (0) {
|
||||
mdb_txn_abort(transaction);
|
||||
} else {
|
||||
mdb_txn_commit(transaction);
|
||||
}
|
||||
|
||||
if (mdb_dbi_open(transaction, "databasename", MDB_DUPSORT | MDB_CREATE, new_omemo->db.dbi)) {
|
||||
//Error
|
||||
}
|
||||
|
||||
struct signal_crypto_provider crypto_provider = {
|
||||
.random_func = &cp_random_generator,
|
||||
.hmac_sha256_init_func = &cp_hmac_sha256_init,
|
||||
.hmac_sha256_update_func = &cp_hmac_sha256_update,
|
||||
.hmac_sha256_final_func = &cp_hmac_sha256_final,
|
||||
.hmac_sha256_cleanup_func = &cp_hmac_sha256_cleanup,
|
||||
.sha512_digest_init_func = &cp_sha512_digest_init,
|
||||
.sha512_digest_update_func = &cp_sha512_digest_update,
|
||||
.sha512_digest_final_func = &cp_sha512_digest_final,
|
||||
.sha512_digest_cleanup_func = &cp_sha512_digest_cleanup,
|
||||
.encrypt_func = &cp_encrypt,
|
||||
.decrypt_func = &cp_decrypt,
|
||||
.user_data = buffer,
|
||||
};
|
||||
|
||||
signal_context_set_crypto_provider(global_context, &provider);
|
||||
signal_context_set_locking_functions(global_context, &lock_function, &unlock_function);
|
||||
signal_context_set_crypto_provider(new_omemo->context, &crypto_provider);
|
||||
signal_context_set_locking_functions(new_omemo->context, &lock_function, &unlock_function);
|
||||
|
||||
signal_protocol_key_helper_pre_key_list_node *pre_keys_head;
|
||||
session_signed_pre_key *signed_pre_key;
|
||||
int start_id = 0;
|
||||
time_t timestamp = time(NULL);
|
||||
|
||||
signal_protocol_key_helper_generate_identity_key_pair(&omemo->identity, global_context);
|
||||
signal_protocol_key_helper_generate_registration_id(&omemo->device_id, 0, global_context);
|
||||
signal_protocol_key_helper_generate_pre_keys(&pre_keys_head, start_id, 100, global_context);
|
||||
signal_protocol_key_helper_generate_signed_pre_key(&signed_pre_key, omemo->identity, 5, timestamp, global_context);
|
||||
if (new_omemo->identity)
|
||||
0;
|
||||
else
|
||||
signal_protocol_key_helper_generate_identity_key_pair(&new_omemo->identity, new_omemo->context);
|
||||
signal_protocol_key_helper_generate_registration_id(&new_omemo->device_id, 0, new_omemo->context);
|
||||
signal_protocol_key_helper_generate_pre_keys(&pre_keys_head, start_id, 100, new_omemo->context);
|
||||
signal_protocol_key_helper_generate_signed_pre_key(&signed_pre_key, new_omemo->identity, 5, timestamp, new_omemo->context);
|
||||
|
||||
/* Store pre keys in the pre key store. */
|
||||
/* Store signed pre key in the signed pre key store. */
|
||||
|
||||
omemo->context = global_context;
|
||||
signal_protocol_store_context_create(&new_omemo->store_context, new_omemo->context);
|
||||
|
||||
return SG_SUCCESS;
|
||||
}
|
||||
struct signal_protocol_identity_key_store identity_key_store = {
|
||||
.get_identity_key_pair = &iks_get_identity_key_pair,
|
||||
.get_local_registration_id = &iks_get_local_registration_id,
|
||||
.save_identity = &iks_save_identity,
|
||||
.is_trusted_identity = &iks_is_trusted_identity,
|
||||
.destroy_func = &iks_destroy_func,
|
||||
.user_data = account_name,
|
||||
};
|
||||
|
||||
void omemo__init(struct t_gui_buffer *buffer, struct t_omemo **omemo,
|
||||
char **device, char **identity)
|
||||
{
|
||||
struct t_omemo *new_omemo;
|
||||
|
||||
new_omemo = calloc(1, sizeof(**omemo));
|
||||
|
||||
omemo__deserialize(new_omemo, *device, *identity, strlen(*identity));
|
||||
|
||||
omemo__signal_init(buffer, new_omemo);
|
||||
|
||||
omemo__serialize(new_omemo, device, identity, NULL);
|
||||
signal_protocol_store_context_set_identity_key_store(new_omemo->store_context, &identity_key_store);
|
||||
|
||||
*omemo = new_omemo;
|
||||
}
|
||||
|
8
omemo.h
8
omemo.h
@ -10,6 +10,12 @@ extern const char *OMEMO_ADVICE;
|
||||
struct t_omemo
|
||||
{
|
||||
struct signal_context *context;
|
||||
struct signal_protocol_store_context *store_context;
|
||||
|
||||
struct {
|
||||
struct MDB_env *env;
|
||||
struct MDB_dbi *dbi;
|
||||
} db;
|
||||
|
||||
struct ratchet_identity_key_pair *identity;
|
||||
|
||||
@ -17,7 +23,7 @@ struct t_omemo
|
||||
};
|
||||
|
||||
void omemo__init(struct t_gui_buffer *buffer, struct t_omemo **omemo,
|
||||
char **device, char **identity);
|
||||
const char *account_name);
|
||||
|
||||
void omemo__serialize(struct t_omemo *omemo, char **device,
|
||||
char **identity, size_t *identity_len);
|
||||
|
50
pgp.c
50
pgp.c
@ -75,20 +75,20 @@ char *pgp__encrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *t
|
||||
if ((ret = rnp_input_from_memory(&input, (uint8_t *)message, strlen(message), false)) !=
|
||||
RNP_SUCCESS) {
|
||||
const char *reason = rnp_result_to_string(ret);
|
||||
weechat_printf(buffer, "[PGP]\tfailed to create input object: %s\n", reason);
|
||||
weechat_printf(buffer, "%spgp: failed to create input object: %s\n", weechat_prefix("error"), reason);
|
||||
goto encrypt_finish;
|
||||
}
|
||||
|
||||
if ((ret = rnp_output_to_memory(&output, 0)) != RNP_SUCCESS) {
|
||||
const char *reason = rnp_result_to_string(ret);
|
||||
weechat_printf(buffer, "[PGP]\tfailed to create output object: %s\n", reason);
|
||||
weechat_printf(buffer, "%spgp: failed to create output object: %s\n", weechat_prefix("error"), reason);
|
||||
goto encrypt_finish;
|
||||
}
|
||||
|
||||
/* create encryption operation */
|
||||
if ((ret = rnp_op_encrypt_create(&encrypt, pgp->context, input, output)) != RNP_SUCCESS) {
|
||||
const char *reason = rnp_result_to_string(ret);
|
||||
weechat_printf(buffer, "[PGP]\tfailed to create encrypt operation: %s\n", reason);
|
||||
weechat_printf(buffer, "%spgp: failed to create encrypt operation: %s\n", weechat_prefix("error"), reason);
|
||||
goto encrypt_finish;
|
||||
}
|
||||
|
||||
@ -103,13 +103,13 @@ char *pgp__encrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *t
|
||||
/* locate recipient's key and add it to the operation context. */
|
||||
if ((ret = rnp_locate_key(pgp->context, "keyid", target, &key)) != RNP_SUCCESS) {
|
||||
const char *reason = rnp_result_to_string(ret);
|
||||
weechat_printf(buffer, "[PGP]\tfailed to locate recipient key: %s\n", reason);
|
||||
weechat_printf(buffer, "%spgp: failed to locate recipient key: %s\n", weechat_prefix("error"), reason);
|
||||
goto encrypt_finish;
|
||||
}
|
||||
|
||||
if ((ret = rnp_op_encrypt_add_recipient(encrypt, key)) != RNP_SUCCESS) {
|
||||
const char *reason = rnp_result_to_string(ret);
|
||||
weechat_printf(buffer, "[PGP]\tfailed to add recipient: %s\n", reason);
|
||||
weechat_printf(buffer, "%spgp: failed to add recipient: %s\n", weechat_prefix("error"), reason);
|
||||
goto encrypt_finish;
|
||||
}
|
||||
rnp_key_handle_destroy(key);
|
||||
@ -118,7 +118,7 @@ char *pgp__encrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *t
|
||||
/* execute encryption operation */
|
||||
if ((ret = rnp_op_encrypt_execute(encrypt)) != RNP_SUCCESS) {
|
||||
const char *reason = rnp_result_to_string(ret);
|
||||
weechat_printf(buffer, "[PGP]\tencryption failed: %s\n", reason);
|
||||
weechat_printf(buffer, "%spgp: encryption failed: %s\n", weechat_prefix("error"), reason);
|
||||
goto encrypt_finish;
|
||||
}
|
||||
|
||||
@ -156,19 +156,19 @@ char *pgp__decrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *c
|
||||
* message */
|
||||
if ((ret = rnp_input_from_memory(&input, buf, buf_len, false)) != RNP_SUCCESS) {
|
||||
const char *reason = rnp_result_to_string(ret);
|
||||
weechat_printf(buffer, "[PGP]\tfailed to create input object: %s\n", reason);
|
||||
weechat_printf(buffer, "%spgp: failed to create input object: %s\n", weechat_prefix("error"), reason);
|
||||
goto decrypt_finish;
|
||||
}
|
||||
|
||||
if ((ret = rnp_output_to_memory(&output, 0)) != RNP_SUCCESS) {
|
||||
const char *reason = rnp_result_to_string(ret);
|
||||
weechat_printf(buffer, "[PGP]\tfailed to create output object: %s\n", reason);
|
||||
weechat_printf(buffer, "%spgp: failed to create output object: %s\n", weechat_prefix("error"), reason);
|
||||
goto decrypt_finish;
|
||||
}
|
||||
|
||||
if ((ret = rnp_decrypt(pgp->context, input, output)) != RNP_SUCCESS) {
|
||||
const char *reason = rnp_result_to_string(ret);
|
||||
weechat_printf(buffer, "[PGP]\tpublic-key decryption failed: %s\n", reason);
|
||||
weechat_printf(buffer, "%spgp: public-key decryption failed: %s\n", weechat_prefix("error"), reason);
|
||||
goto decrypt_finish;
|
||||
}
|
||||
free(buf);
|
||||
@ -204,19 +204,19 @@ char *pgp__verify(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *ce
|
||||
/* create file input memory objects for the signed message and verified message */
|
||||
if ((ret = rnp_input_from_memory(&input, buf, buf_len, false)) != RNP_SUCCESS) {
|
||||
const char *reason = rnp_result_to_string(ret);
|
||||
weechat_printf(buffer, "[PGP]\tfailed to create input object: %s\n", reason);
|
||||
weechat_printf(buffer, "%spgp: failed to create input object: %s\n", weechat_prefix("error"), reason);
|
||||
goto verify_finish;
|
||||
}
|
||||
|
||||
if ((ret = rnp_input_from_memory(&signature, buf, buf_len, false)) != RNP_SUCCESS) {
|
||||
const char *reason = rnp_result_to_string(ret);
|
||||
weechat_printf(buffer, "[PGP]\tfailed to create input object: %s\n", reason);
|
||||
weechat_printf(buffer, "%spgp: failed to create input object: %s\n", weechat_prefix("error"), reason);
|
||||
goto verify_finish;
|
||||
}
|
||||
|
||||
if ((ret = rnp_op_verify_detached_create(&verify, pgp->context, input, signature)) != RNP_SUCCESS) {
|
||||
const char *reason = rnp_result_to_string(ret);
|
||||
weechat_printf(buffer, "[PGP]\tfailed to create verification context: %s\n", reason);
|
||||
weechat_printf(buffer, "%spgp: failed to create verification context: %s\n", weechat_prefix("error"), reason);
|
||||
goto verify_finish;
|
||||
}
|
||||
|
||||
@ -226,14 +226,14 @@ char *pgp__verify(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *ce
|
||||
// ) != RNP_ERROR_SIGNATURE_INVALID)
|
||||
// if (ret != RNP_ERROR_SIGNATURE_INVALID) {
|
||||
// const char *reason = rnp_result_to_string(ret);
|
||||
// weechat_printf(buffer, "[PGP]\tfailed to execute verification operation: %s\n", reason);
|
||||
// weechat_printf(buffer, "%spgp: failed to execute verification operation: %s\n", weechat_prefix("error"), reason);
|
||||
// goto verify_finish;
|
||||
// }
|
||||
|
||||
/* now check signatures and get some info about them */
|
||||
if ((ret = rnp_op_verify_get_signature_count(verify, &sigcount)) != RNP_SUCCESS) {
|
||||
const char *reason = rnp_result_to_string(ret);
|
||||
weechat_printf(buffer, "[PGP]\tfailed to get signature count: %s\n", reason);
|
||||
weechat_printf(buffer, "%spgp: failed to get signature count: %s\n", weechat_prefix("error"), reason);
|
||||
goto verify_finish;
|
||||
}
|
||||
|
||||
@ -245,14 +245,14 @@ char *pgp__verify(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *ce
|
||||
|
||||
if ((ret = rnp_op_verify_get_signature_at(verify, i, &sig)) != RNP_SUCCESS) {
|
||||
const char *reason = rnp_result_to_string(ret);
|
||||
weechat_printf(buffer, "[PGP]\tfailed to get signature %d: %s\n", (int)i, reason);
|
||||
weechat_printf(buffer, "%spgp: failed to get signature %d: %s\n", weechat_prefix("error"), (int)i, reason);
|
||||
goto verify_finish;
|
||||
}
|
||||
|
||||
if ((ret = rnp_op_verify_signature_get_key(sig, &key)) == RNP_SUCCESS) {
|
||||
if ((ret = rnp_key_get_keyid(key, &keyid)) != RNP_SUCCESS) {
|
||||
const char *reason = rnp_result_to_string(ret);
|
||||
weechat_printf(buffer, "[PGP]\tfailed to get key id %d: %s\n", (int)i, reason);
|
||||
weechat_printf(buffer, "%spgp: failed to get key id %d: %s\n", weechat_prefix("error"), (int)i, reason);
|
||||
rnp_key_handle_destroy(key);
|
||||
goto verify_finish;
|
||||
}
|
||||
@ -260,7 +260,7 @@ char *pgp__verify(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *ce
|
||||
if ((ret = rnp_key_get_signature_at(key, 0, &signature)) == RNP_SUCCESS) {
|
||||
if ((ret = rnp_signature_get_keyid(signature, &keyid)) != RNP_SUCCESS) {
|
||||
const char *reason = rnp_result_to_string(ret);
|
||||
weechat_printf(buffer, "[PGP]\tfailed to get key id: %s\n", reason);
|
||||
weechat_printf(buffer, "%spgp: failed to get key id: %s\n", weechat_prefix("error"), reason);
|
||||
rnp_key_handle_destroy(key);
|
||||
goto verify_finish;
|
||||
}
|
||||
@ -269,13 +269,13 @@ char *pgp__verify(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *ce
|
||||
} else {
|
||||
if ((ret = rnp_op_verify_signature_get_handle(sig, &signature)) != RNP_SUCCESS) {
|
||||
const char *reason = rnp_result_to_string(ret);
|
||||
weechat_printf(buffer, "[PGP]\tfailed to get signature's %d handle: %s\n", (int)i, reason);
|
||||
weechat_printf(buffer, "%spgp: failed to get signature's %d handle: %s\n", weechat_prefix("error"), (int)i, reason);
|
||||
goto verify_finish;
|
||||
}
|
||||
|
||||
if ((ret = rnp_signature_get_keyid(signature, &keyid)) != RNP_SUCCESS) {
|
||||
const char *reason = rnp_result_to_string(ret);
|
||||
weechat_printf(buffer, "[PGP]\tfailed to get key id: %s\n", reason);
|
||||
weechat_printf(buffer, "%spgp: failed to get key id: %s\n", weechat_prefix("error"), reason);
|
||||
rnp_key_handle_destroy(key);
|
||||
goto verify_finish;
|
||||
}
|
||||
@ -309,18 +309,18 @@ char *pgp__sign(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *sour
|
||||
* message */
|
||||
if (rnp_input_from_memory(&input, (uint8_t *)message, strlen(message), false) !=
|
||||
RNP_SUCCESS) {
|
||||
weechat_printf(buffer, "[PGP]\tfailed to create input object\n");
|
||||
weechat_printf(buffer, "%spgp: failed to create input object\n", weechat_prefix("error"));
|
||||
goto sign_finish;
|
||||
}
|
||||
|
||||
if (rnp_output_to_memory(&output, 0) != RNP_SUCCESS) {
|
||||
weechat_printf(buffer, "[PGP]\tfailed to create output object\n");
|
||||
weechat_printf(buffer, "%spgp: failed to create output object\n", weechat_prefix("error"));
|
||||
goto sign_finish;
|
||||
}
|
||||
|
||||
/* initialize and configure sign operation */
|
||||
if (rnp_op_sign_detached_create(&sign, pgp->context, input, output) != RNP_SUCCESS) {
|
||||
weechat_printf(buffer, "[PGP]\tfailed to create sign operation\n");
|
||||
weechat_printf(buffer, "%spgp: failed to create sign operation\n", weechat_prefix("error"));
|
||||
goto sign_finish;
|
||||
}
|
||||
|
||||
@ -338,12 +338,12 @@ char *pgp__sign(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *sour
|
||||
|
||||
/* now add signatures. First locate the signing key, then add and setup signature */
|
||||
if (rnp_locate_key(pgp->context, "keyid", source, &key) != RNP_SUCCESS) {
|
||||
weechat_printf(buffer, "[PGP]\tfailed to locate signing key: %s\n", source);
|
||||
weechat_printf(buffer, "%spgp: failed to locate signing key: %s\n", weechat_prefix("error"), source);
|
||||
goto sign_finish;
|
||||
}
|
||||
|
||||
if (rnp_op_sign_add_signature(sign, key, NULL) != RNP_SUCCESS) {
|
||||
weechat_printf(buffer, "[PGP]\tfailed to add signature for key: %s\n", source);
|
||||
weechat_printf(buffer, "%spgp: failed to add signature for key: %s\n", weechat_prefix("error"), source);
|
||||
goto sign_finish;
|
||||
}
|
||||
|
||||
@ -352,7 +352,7 @@ char *pgp__sign(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *sour
|
||||
|
||||
/* finally do signing */
|
||||
if (rnp_op_sign_execute(sign) != RNP_SUCCESS) {
|
||||
weechat_printf(buffer, "[PGP]\tfailed to sign with key: %s\n", source);
|
||||
weechat_printf(buffer, "%spgp: failed to sign with key: %s\n", weechat_prefix("error"), source);
|
||||
goto sign_finish;
|
||||
}
|
||||
|
||||
|
58
user.c
58
user.c
@ -53,18 +53,18 @@ const char *user__as_prefix(struct t_account *account,
|
||||
}
|
||||
|
||||
struct t_user *user__bot_search(struct t_account *account,
|
||||
const char *bot_id)
|
||||
const char *pgp_id)
|
||||
{
|
||||
struct t_user *ptr_user;
|
||||
|
||||
if (!account || !bot_id)
|
||||
if (!account || !pgp_id)
|
||||
return NULL;
|
||||
|
||||
for (ptr_user = account->users; ptr_user;
|
||||
ptr_user = ptr_user->next_user)
|
||||
{
|
||||
if (ptr_user->profile.bot_id &&
|
||||
weechat_strcasecmp(ptr_user->profile.bot_id, bot_id) == 0)
|
||||
if (ptr_user->profile.pgp_id &&
|
||||
weechat_strcasecmp(ptr_user->profile.pgp_id, pgp_id) == 0)
|
||||
return ptr_user;
|
||||
}
|
||||
|
||||
@ -102,15 +102,28 @@ void user__nicklist_add(struct t_account *account,
|
||||
|
||||
ptr_buffer = channel ? channel->buffer : account->buffer;
|
||||
|
||||
ptr_group = weechat_nicklist_search_group(ptr_buffer, NULL,
|
||||
user->is_away ?
|
||||
"+" : "...");
|
||||
char *group = "...";
|
||||
if (weechat_strcasecmp(user->profile.affiliation, "outcast") == 0)
|
||||
group = "!";
|
||||
if (weechat_strcasecmp(user->profile.role, "visitor") == 0)
|
||||
group = "?";
|
||||
if (weechat_strcasecmp(user->profile.role, "participant") == 0)
|
||||
group = "+";
|
||||
if (weechat_strcasecmp(user->profile.affiliation, "member") == 0)
|
||||
group = "%";
|
||||
if (weechat_strcasecmp(user->profile.role, "moderator") == 0)
|
||||
group = "@";
|
||||
if (weechat_strcasecmp(user->profile.affiliation, "admin") == 0)
|
||||
group = "&";
|
||||
if (weechat_strcasecmp(user->profile.affiliation, "owner") == 0)
|
||||
group = "~";
|
||||
ptr_group = weechat_nicklist_search_group(ptr_buffer, NULL, group);
|
||||
weechat_nicklist_add_nick(ptr_buffer, ptr_group,
|
||||
name,
|
||||
user->is_away ?
|
||||
"weechat.color.nicklist_away" :
|
||||
user__get_colour_for_nicklist(user),
|
||||
user->is_away ? "+" : "",
|
||||
group,
|
||||
"bar_fg",
|
||||
1);
|
||||
}
|
||||
@ -119,7 +132,7 @@ void user__nicklist_remove(struct t_account *account,
|
||||
struct t_channel *channel,
|
||||
struct t_user *user)
|
||||
{
|
||||
struct t_gui_nick_group *ptr_group;
|
||||
struct t_gui_nick *ptr_nick;
|
||||
struct t_gui_buffer *ptr_buffer;
|
||||
char *name = user->profile.display_name;
|
||||
if (channel && weechat_strcasecmp(xmpp_jid_bare(account->context, name),
|
||||
@ -128,11 +141,8 @@ void user__nicklist_remove(struct t_account *account,
|
||||
|
||||
ptr_buffer = channel ? channel->buffer : account->buffer;
|
||||
|
||||
ptr_group = weechat_nicklist_search_group(ptr_buffer, NULL,
|
||||
user->is_away ?
|
||||
"+" : "...");
|
||||
weechat_nicklist_remove_nick(ptr_buffer,
|
||||
weechat_nicklist_search_nick(ptr_buffer, ptr_group, name));
|
||||
if ((ptr_nick = weechat_nicklist_search_nick(ptr_buffer, NULL, name)))
|
||||
weechat_nicklist_remove_nick(ptr_buffer, ptr_nick);
|
||||
}
|
||||
|
||||
struct t_user *user__new(struct t_account *account,
|
||||
@ -173,14 +183,14 @@ struct t_user *user__new(struct t_account *account,
|
||||
|
||||
new_user->profile.avatar_hash = NULL;
|
||||
new_user->profile.status_text = NULL;
|
||||
new_user->profile.status_emoji = NULL;
|
||||
new_user->profile.status = NULL;
|
||||
new_user->profile.real_name = NULL;
|
||||
new_user->profile.display_name = display_name ?
|
||||
strdup(display_name) : strdup("");
|
||||
new_user->profile.real_name_normalized = NULL;
|
||||
new_user->profile.affiliation = NULL;
|
||||
new_user->profile.email = NULL;
|
||||
new_user->profile.team = NULL;
|
||||
new_user->profile.bot_id = NULL;
|
||||
new_user->profile.role = NULL;
|
||||
new_user->profile.pgp_id = NULL;
|
||||
new_user->updated = 0;
|
||||
new_user->is_away = 0;
|
||||
|
||||
@ -220,18 +230,18 @@ void user__free(struct t_account *account,
|
||||
free(user->profile.avatar_hash);
|
||||
if (user->profile.status_text)
|
||||
free(user->profile.status_text);
|
||||
if (user->profile.status_emoji)
|
||||
free(user->profile.status_emoji);
|
||||
if (user->profile.status)
|
||||
free(user->profile.status);
|
||||
if (user->profile.real_name)
|
||||
free(user->profile.real_name);
|
||||
if (user->profile.display_name)
|
||||
free(user->profile.display_name);
|
||||
if (user->profile.real_name_normalized)
|
||||
free(user->profile.real_name_normalized);
|
||||
if (user->profile.affiliation)
|
||||
free(user->profile.affiliation);
|
||||
if (user->profile.email)
|
||||
free(user->profile.email);
|
||||
if (user->profile.team)
|
||||
free(user->profile.team);
|
||||
if (user->profile.role)
|
||||
free(user->profile.role);
|
||||
|
||||
free(user);
|
||||
|
||||
|
11
user.h
11
user.h
@ -9,13 +9,13 @@ struct t_user_profile
|
||||
{
|
||||
char *avatar_hash;
|
||||
char *status_text;
|
||||
char *status_emoji;
|
||||
char *status;
|
||||
char *real_name;
|
||||
char *display_name;
|
||||
char *real_name_normalized;
|
||||
char *email;
|
||||
char *team;
|
||||
char *bot_id;
|
||||
char *role;
|
||||
char *affiliation;
|
||||
char *pgp_id;
|
||||
};
|
||||
|
||||
struct t_user
|
||||
@ -41,9 +41,6 @@ const char *user__as_prefix(struct t_account *account,
|
||||
struct t_user *user,
|
||||
const char *name);
|
||||
|
||||
struct t_user *user__bot_search(struct t_account *account,
|
||||
const char *bot_id);
|
||||
|
||||
struct t_user *user__search(struct t_account *account,
|
||||
const char *id);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user