nicklist stuff

This commit is contained in:
Tony Olagbaiye 2021-07-27 22:27:03 +01:00
parent d566f45c6a
commit d3ffc19378
No known key found for this signature in database
GPG Key ID: 9E2FF3BDEBDFC910
14 changed files with 494 additions and 307 deletions

2
.envrc
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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))
{

View File

@ -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
View File

@ -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;
}

View File

@ -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);

148
command.c
View File

@ -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;
@ -147,7 +150,7 @@ void command__add_account(const char *name, const char *jid, const char *passwor
account_option_set(account, ACCOUNT_OPTION_NICKNAME,
strdup(xmpp_jid_node(account->context, jid)));
weechat_printf (
weechat_printf(
NULL,
_("%s: account %s%s%s %s(%s%s%s)%s added"),
WEECHAT_XMPP_PLUGIN_NAME,
@ -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;
@ -337,7 +359,7 @@ void command__account_delete(int argc, char **argv)
account_name = strdup(account->name);
account__free(account);
weechat_printf (
weechat_printf(
NULL,
_("%s: account %s%s%s has been deleted"),
WEECHAT_XMPP_PLUGIN_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;
}
@ -564,7 +613,7 @@ int command__msg(const void *pointer, void *data,
if (!ptr_channel)
{
weechat_printf (
weechat_printf(
ptr_account->buffer,
_("%s%s: \"%s\" command can not be executed on a account buffer"),
weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, "msg");
@ -619,7 +668,7 @@ int command__me(const void *pointer, void *data,
if (!ptr_channel)
{
weechat_printf (
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");
@ -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)
@ -675,10 +776,10 @@ int command__pgp(const void *pointer, void *data,
if (!ptr_channel)
{
weechat_printf (
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"),

View File

@ -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
View File

@ -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;
}

View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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);