fetch devicelist

v1
Tony Olagbaiye 3 years ago
parent 2190c0a075
commit ee16eaaa7a
No known key found for this signature in database
GPG Key ID: 9E2FF3BDEBDFC910

@ -38,6 +38,7 @@ use_guix()
make cmake gcc-toolchain pkg-config patchelf
weechat libxml2 libstrophe
glib libsignal-protocol-c sqlite
minixml
)
# Thanks <https://lists.gnu.org/archive/html/guix-devel/2016-09/msg00859.html>

@ -7,7 +7,7 @@ FIND=find
INCLUDES=-Ilibstrophe $(shell xml2-config --cflags) $(shell pkg-config --cflags glib-2.0) $(shell pkg-config --cflags libsignal-protocol-c)
CFLAGS+=$(DBGCFLAGS) -fno-omit-frame-pointer -fPIC -std=gnu99 -g -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 glib-2.0) $(shell pkg-config --libs libsignal-protocol-c)
LDLIBS=-lstrophe -lpthread $(shell xml2-config --libs) $(shell pkg-config --libs glib-2.0) $(shell pkg-config --libs libsignal-protocol-c) -lmxml
PREFIX ?= /usr/local
LIBDIR ?= $(PREFIX)/lib
@ -27,7 +27,7 @@ SRCS=plugin.c \
xmpp/presence.c \
xmpp/iq.c \
DEPS=axc/build/libaxc.a
DEPS=omemo/build/libomemo-conversations.a axc/build/libaxc.a
OBJS=$(subst .c,.o,$(SRCS))
all: weechat-xmpp
@ -39,6 +39,10 @@ xmpp.so: $(OBJS) $(DEPS)
patchelf --set-rpath $(LIBRARY_PATH):$(shell realpath $(shell dirname $(shell gcc --print-libgcc-file-name))/../../../) xmpp.so && \
patchelf --shrink-rpath xmpp.so || true
omemo/build/libomemo-conversations.a:
$(MAKE) -C omemo
omemo: omemo/build/libomemo-conversations.a
axc/build/libaxc.a:
$(MAKE) -C axc
axc: axc/build/libaxc.a
@ -62,6 +66,7 @@ tidy:
clean:
$(RM) -f $(OBJS)
$(MAKE) -C omemo clean || true
$(MAKE) -C axc clean || true
git submodule foreach --recursive git clean -xfd || true
git submodule foreach --recursive git reset --hard || true

@ -122,10 +122,12 @@
* [ ] [#A] Send typing notifications
* [ ] [#A] Recv typing notifications
* [ ] [#C] Read receipts
* [ ] Message Carbons
* [ ] Service Disco
* [ ] Bookmarks / Roster
* [ ] OTR (libotr)
* [ ] PGP (libgpgme)
* [ ] Room Explorer (https://search.jabber.network/docs/api)
** TODO [#C] Implement completion engine (milestone v0.3)
** TODO [#D] Close all issues (milestone v1.0)
* [ ] Absorb libomemo / axc, and drop glib

@ -13,6 +13,7 @@
#include "plugin.h"
#include "config.h"
#include "input.h"
#include "omemo.h"
#include "account.h"
#include "connection.h"
#include "user.h"
@ -86,6 +87,81 @@ int account__search_option(const char *option_name)
return -1;
}
struct t_device *account__search_device(struct t_account *account, int id)
{
struct t_device *ptr_device;
if (!account)
return NULL;
for (ptr_device = account->devices; ptr_device;
ptr_device = ptr_device->next_device)
{
if (ptr_device->id == id)
return ptr_device;
}
return NULL;
}
void account__add_device(struct t_account *account,
struct t_device *device)
{
struct t_device *new_device;
new_device = account__search_device(account, device->id);
if (!new_device)
{
new_device = malloc(sizeof(*new_device));
new_device->id = device->id;
new_device->name = strdup(device->name);
new_device->prev_device = account->last_device;
new_device->next_device = NULL;
if (account->last_device)
(account->last_device)->next_device = new_device;
else
account->devices = new_device;
account->last_device = new_device;
}
}
void account__free_device(struct t_account *account, struct t_device *device)
{
struct t_device *new_devices;
if (!account || !device)
return;
/* remove device from devices list */
if (account->last_device == device)
account->last_device = device->prev_device;
if (device->prev_device)
{
(device->prev_device)->next_device = device->next_device;
new_devices = account->devices;
}
else
new_devices = device->next_device;
if (device->next_device)
(device->next_device)->prev_device = device->prev_device;
/* free device data */
if (device->name)
free(device->name);
free(device);
account->devices = new_devices;
}
void account__free_device_all(struct t_account *account)
{
while (account->devices)
account__free_device(account, account->devices);
}
void account__log_emit_weechat(void *const userdata, const xmpp_log_level_t level,
const char *const area, const char *const msg)
{
@ -204,6 +280,10 @@ struct t_account *account__alloc(const char *name)
new_account->is_connected = 0;
new_account->disconnected = 0;
new_account->current_retry = 0;
new_account->reconnect_delay = 0;
new_account->reconnect_start = 0;
new_account->logger.handler = &account__log_emit_weechat;
new_account->logger.userdata = new_account;
new_account->context = xmpp_ctx_new(NULL, &new_account->logger);
@ -211,6 +291,11 @@ struct t_account *account__alloc(const char *name)
new_account->buffer = NULL;
new_account->buffer_as_string = NULL;
new_account->omemo = NULL;
new_account->devices = NULL;
new_account->last_device = NULL;
new_account->users = NULL;
new_account->last_user = NULL;
new_account->channels = NULL;
@ -300,6 +385,9 @@ void account__free_data(struct t_account *account)
if (account->buffer_as_string)
free(account->buffer_as_string);
if (account->omemo)
omemo__free(account->omemo);
//channel__free_all(account);
//user__free_all(account);
}
@ -384,58 +472,34 @@ void account__disconnect(struct t_account *account, int reconnect)
weechat_prefix ("network"), WEECHAT_XMPP_PLUGIN_NAME);
}
/*
account->current_retry = 0;
if (switch_address)
account__switch_address(account, 0);
else
account__set_index_current_address(account, 0);
if (account->nick_modes)
if (reconnect)
{
free (account->nick_modes);
account->nick_modes = NULL;
weechat_bar_item_update ("input_prompt");
weechat_bar_item_update ("xmpp_nick_modes");
if (account->current_retry++ == 0)
{
account->reconnect_delay = 5;
account->reconnect_start = time(NULL) + account->reconnect_delay;
}
account->current_retry %= 5;
}
account->cap_away_notify = 0;
account->cap_account_notify = 0;
account->cap_extended_join = 0;
account->is_away = 0;
account->away_time = 0;
account->lag = 0;
account->lag_displayed = -1;
account->lag_check_time.tv_sec = 0;
account->lag_check_time.tv_usec = 0;
account->lag_next_check = time (NULL) +
weechat_config_integer (xmpp_config_network_lag_check);
account->lag_last_refresh = 0;
account__set_lag (account);
account->monitor = 0;
account->monitor_time = 0;
*/
/*
if (reconnect
&& IRC_SERVER_OPTION_BOOLEAN(account, IRC_SERVER_OPTION_AUTORECONNECT))
account__reconnect_schedule(account);
else
{
account->current_retry = 0;
account->reconnect_delay = 0;
account->reconnect_start = 0;
}
*/
/* discard current nick if no reconnection asked */
/*
if (!reconnect && account->nick)
account__set_nick(account, NULL);
account__set_buffer_title(account);
/*
account->lag = 0;
account->lag_displayed = -1;
account->lag_check_time.tv_sec = 0;
account->lag_check_time.tv_usec = 0;
account->lag_next_check = time(NULL) +
weechat_config_integer(xmpp_config_network_lag_check);
account->lag_last_refresh = 0;
account__set_lag(account);
*/ // lag based on xmpp ping
account->disconnected = 1;
*/
/* send signal "account_disconnected" with account name */
(void) weechat_hook_signal_send("xmpp_account_disconnected",
@ -536,6 +600,11 @@ 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->reconnect_start > 0
&& ptr_account->reconnect_start < time(NULL))
{
account__connect(ptr_account);
}
}
return WEECHAT_RC_OK;

@ -58,6 +58,15 @@ enum t_account_option
#define account_autojoin(account) \
weechat_config_string(account->options[ACCOUNT_OPTION_AUTOJOIN])
struct t_device
{
int id;
char *name;
struct t_device *prev_device;
struct t_device *next_device;
};
struct t_account
{
char *name;
@ -68,18 +77,26 @@ struct t_account
int is_connected;
int disconnected;
int current_retry;
int reconnect_delay;
int reconnect_start;
xmpp_log_t logger;
xmpp_ctx_t *context;
xmpp_conn_t *connection;
struct t_gui_buffer *buffer;
char *buffer_as_string;
//struct t_device *devices;
//struct t_device *last_device;
struct t_omemo *omemo;
struct t_device *devices;
struct t_device *last_device;
struct t_user *users;
struct t_user *last_user;
struct t_channel *channels;
struct t_channel *last_channel;
struct t_account *prev_account;
struct t_account *next_account;
};
@ -89,6 +106,10 @@ extern char *account_options[][2];
struct t_account *account__search(const char *account_name);
struct t_account *account__casesearch (const char *account_name);
int account__search_option(const char *option_name);
struct t_device *account__search_device(struct t_account *account, int id);
void account__add_device(struct t_account *account, struct t_device *device);
void account__free_device(struct t_account *account, struct t_device *device);
void account__free_device_all(struct t_account *account);
struct t_account *account__alloc(const char *name);
void account__free_data(struct t_account *account);
void account__free(struct t_account *account);

@ -2,8 +2,8 @@
// License, version 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <strophe.h>
#include <string.h>
#include <strophe.h>
#include <weechat/weechat-plugin.h>
#include "plugin.h"

@ -10,6 +10,7 @@
#include <weechat/weechat-plugin.h>
#include "plugin.h"
#include "omemo.h"
#include "account.h"
#include "user.h"
#include "channel.h"
@ -489,6 +490,10 @@ void channel__member_free(struct t_channel *channel,
/* free member data */
if (member->id)
free(member->id);
if (member->role)
free(member->role);
if (member->affiliation)
free(member->affiliation);
free(member);
@ -589,6 +594,9 @@ struct t_channel_member *channel__add_member(struct t_account *account,
member = malloc(sizeof(struct t_channel_member));
member->id = strdup(id);
member->role = NULL;
member->affiliation = NULL;
member->prev_member = channel->last_member;
member->next_member = NULL;
if (channel->last_member)
@ -607,12 +615,13 @@ struct t_channel_member *channel__add_member(struct t_account *account,
&& channel->type == CHANNEL_TYPE_MUC)
weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,enter,log4", "%s%s entered",
weechat_prefix("join"),
jid_resource);
user__as_prefix_raw(account, jid_resource));
else
weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,enter,log4", "%s%s (%s) entered",
weechat_prefix("join"),
xmpp_jid_bare(account->context, user->id),
xmpp_jid_resource(account->context, user->id));
user__as_prefix_raw(account,
xmpp_jid_resource(account->context, user->id)));
return member;
}
@ -635,6 +644,46 @@ 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)
@ -643,8 +692,8 @@ struct t_channel_member *channel__remove_member(struct t_account *account,
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)

@ -27,6 +27,9 @@ struct t_channel_member
{
char *id;
char *role;
char *affiliation;
struct t_channel_member *prev_member;
struct t_channel_member *next_member;
};
@ -120,6 +123,14 @@ struct t_channel_member *channel__add_member(struct t_account *account,
struct t_channel *channel,
const char *id);
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__remove_member(struct t_account *account,
struct t_channel *channel,
const char *id);

@ -111,6 +111,8 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void
}
else 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);
else
@ -127,7 +129,7 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *
struct t_account *account = (struct t_account *)userdata;
struct t_channel *channel;
xmpp_stanza_t *body, *delay, *topic, *replace;
const char *type, *from, *from_bare, *to, *id, *replace_id, *timestamp;
const char *type, *from, *nick, *from_bare, *to, *id, *replace_id, *timestamp;
char *intext;
struct tm time = {0};
time_t date = 0;
@ -170,9 +172,10 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *
if (!channel)
channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare);
nick = NULL;
if (weechat_strcasecmp(type, "groupchat") == 0)
{
from = weechat_strcasecmp(channel->name,
nick = weechat_strcasecmp(channel->name,
xmpp_jid_bare(account->context,
from)) == 0
? xmpp_jid_resource(account->context, from)
@ -188,6 +191,14 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *
char **dyn_tags = weechat_string_dyn_alloc(1);
weechat_string_dyn_concat(dyn_tags, "xmpp_message,message", -1);
{
weechat_string_dyn_concat(dyn_tags, ",nick_", -1);
weechat_string_dyn_concat(dyn_tags, nick, -1);
}
{
weechat_string_dyn_concat(dyn_tags, ",host_", -1);
weechat_string_dyn_concat(dyn_tags, from, -1);
}
if (id)
{
weechat_string_dyn_concat(dyn_tags, ",id_", -1);
@ -213,15 +224,15 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *
const char *edit = replace ? "* " : ""; // Losing which message was edited, sadly
if (strcmp(to, channel->id) == 0)
weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s[to %s]: %s",
edit, user__as_prefix_raw(account, from),
edit, user__as_prefix_raw(account, nick),
to, intext ? intext : "");
else if (weechat_string_match(intext, "/me *", 0))
weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s%s %s",
edit, weechat_prefix("action"), from,
edit, weechat_prefix("action"), nick,
intext ? intext+4 : "");
else
weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s%s",
edit, user__as_prefix_raw(account, from),
edit, user__as_prefix_raw(account, nick),
intext ? intext : "");
weechat_string_dyn_free(dyn_tags, 1);
@ -238,196 +249,276 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd
struct t_account *account = (struct t_account *)userdata;
xmpp_stanza_t *reply, *query, *identity, *feature, *x, *field, *value, *text;
const char *node;
xmpp_stanza_t *pubsub, *items, *item, *list, *device, *children[2];
static struct utsname osinfo;
char *client_name = weechat_string_eval_expression("weechat ${info:version}",
NULL, NULL, NULL);
reply = xmpp_stanza_reply(stanza);
xmpp_stanza_set_type(reply, "result");
query = xmpp_stanza_get_child_by_name_and_ns(
stanza, "query", "http://jabber.org/protocol/disco#info");
node = xmpp_stanza_get_attribute(query, "node");
xmpp_stanza_set_attribute(reply, "id", node);
identity = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(identity, "identity");
xmpp_stanza_set_attribute(identity, "category", "client");
xmpp_stanza_set_attribute(identity, "name", client_name);
xmpp_stanza_set_attribute(identity, "type", "pc");
xmpp_stanza_add_child(query, identity);
xmpp_stanza_release(identity);
#define FEATURE(ns) \
feature = xmpp_stanza_new(account->context); \
xmpp_stanza_set_name(feature, "feature"); \
xmpp_stanza_set_attribute(feature, "var", ns); \
xmpp_stanza_add_child(query, feature); \
xmpp_stanza_release(feature);
FEATURE("http://jabber.org/protocol/caps");
FEATURE("http://jabber.org/protocol/disco#info");
FEATURE("http://jabber.org/protocol/disco#items");
FEATURE("http://jabber.org/protocol/muc");
FEATURE("eu.siacs.conversations.axolotl.devicelist");
FEATURE("eu.siacs.conversations.axolotl.devicelist+notify");
if (query)
{
char *client_name;
reply = xmpp_stanza_reply(stanza);
xmpp_stanza_set_type(reply, "result");
client_name = weechat_string_eval_expression("weechat ${info:version}",
NULL, NULL, NULL);
identity = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(identity, "identity");
xmpp_stanza_set_attribute(identity, "category", "client");
xmpp_stanza_set_attribute(identity, "name", client_name);
xmpp_stanza_set_attribute(identity, "type", "pc");
xmpp_stanza_add_child(query, identity);
xmpp_stanza_release(identity);
#define FEATURE(ns) \
feature = xmpp_stanza_new(account->context); \
xmpp_stanza_set_name(feature, "feature"); \
xmpp_stanza_set_attribute(feature, "var", ns); \
xmpp_stanza_add_child(query, feature); \
xmpp_stanza_release(feature);
FEATURE("http://jabber.org/protocol/caps");
FEATURE("http://jabber.org/protocol/disco#info");
FEATURE("http://jabber.org/protocol/disco#items");
FEATURE("http://jabber.org/protocol/muc");
FEATURE("eu.siacs.conversations.axolotl.devicelist");
FEATURE("eu.siacs.conversations.axolotl.devicelist+notify");
FEATURE("storage:bookmarks+notify");
#undef FEATURE
x = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(x, "x");
xmpp_stanza_set_ns(x, "jabber:x:data");
xmpp_stanza_set_attribute(x, "type", "result");
x = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(x, "x");
xmpp_stanza_set_ns(x, "jabber:x:data");
xmpp_stanza_set_attribute(x, "type", "result");
if (uname(&osinfo) < 0)
{
*osinfo.sysname = 0;
*osinfo.release = 0;
}
if (uname(&osinfo) < 0)
{
*osinfo.sysname = 0;
*osinfo.release = 0;
}
// This is utter bullshit, TODO: not this.
{
field = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(field, "field");
xmpp_stanza_set_attribute(field, "var", "FORM_TYPE");
xmpp_stanza_set_attribute(field, "type", "hidden");
{
field = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(field, "field");
xmpp_stanza_set_attribute(field, "var", "FORM_TYPE");
xmpp_stanza_set_attribute(field, "type", "hidden");
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, "urn:xmpp:dataforms:softwareinfo");
xmpp_stanza_add_child(value, text);
xmpp_stanza_release(text);
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, "urn:xmpp:dataforms:softwareinfo");
xmpp_stanza_add_child(value, text);
xmpp_stanza_release(text);
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
xmpp_stanza_add_child(x, field);
xmpp_stanza_release(field);
}
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
{
field = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(field, "field");
xmpp_stanza_set_attribute(field, "var", "ip_version");
xmpp_stanza_set_attribute(field, "type", "text-multi");
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
xmpp_stanza_add_child(x, field);
xmpp_stanza_release(field);
}
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, "ipv4");
xmpp_stanza_add_child(value, text);
xmpp_stanza_release(text);
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
{
field = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(field, "field");
xmpp_stanza_set_attribute(field, "var", "ip_version");
xmpp_stanza_set_attribute(field, "type", "text-multi");
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, "ipv6");
xmpp_stanza_add_child(value, text);
xmpp_stanza_release(text);
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, "ipv4");
xmpp_stanza_add_child(value, text);
xmpp_stanza_release(text);
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
xmpp_stanza_add_child(x, field);
xmpp_stanza_release(field);
}
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
{
field = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(field, "field");
xmpp_stanza_set_attribute(field, "var", "os");
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, "ipv6");
xmpp_stanza_add_child(value, text);
xmpp_stanza_release(text);
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, osinfo.sysname);
xmpp_stanza_add_child(value, text);
xmpp_stanza_release(text);
xmpp_stanza_add_child(x, field);
xmpp_stanza_release(field);
}
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
{
field = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(field, "field");
xmpp_stanza_set_attribute(field, "var", "os");
xmpp_stanza_add_child(x, field);
xmpp_stanza_release(field);
}
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
{
field = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(field, "field");
xmpp_stanza_set_attribute(field, "var", "os_version");
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, osinfo.sysname);
xmpp_stanza_add_child(value, text);
xmpp_stanza_release(text);
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, osinfo.release);
xmpp_stanza_add_child(value, text);
xmpp_stanza_release(text);
xmpp_stanza_add_child(x, field);
xmpp_stanza_release(field);
}
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
{
field = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(field, "field");
xmpp_stanza_set_attribute(field, "var", "os_version");
xmpp_stanza_add_child(x, field);
xmpp_stanza_release(field);
}
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
{
field = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(field, "field");
xmpp_stanza_set_attribute(field, "var", "software");
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, osinfo.release);
xmpp_stanza_add_child(value, text);
xmpp_stanza_release(text);
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, "weechat");
xmpp_stanza_add_child(value, text);
xmpp_stanza_release(text);
xmpp_stanza_add_child(x, field);
xmpp_stanza_release(field);
}
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
{
field = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(field, "field");
xmpp_stanza_set_attribute(field, "var", "software");
xmpp_stanza_add_child(x, field);
xmpp_stanza_release(field);
}
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
{
field = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(field, "field");
xmpp_stanza_set_attribute(field, "var", "software_version");
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, "weechat");
xmpp_stanza_add_child(value, text);
xmpp_stanza_release(text);
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, weechat_info_get("version", NULL));
xmpp_stanza_add_child(value, text);
xmpp_stanza_release(text);
xmpp_stanza_add_child(x, field);
xmpp_stanza_release(field);
}
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
{
field = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(field, "field");
xmpp_stanza_set_attribute(field, "var", "software_version");
xmpp_stanza_add_child(x, field);
xmpp_stanza_release(field);
}
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
xmpp_stanza_add_child(query, x);
xmpp_stanza_release(x);
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, weechat_info_get("version", NULL));
xmpp_stanza_add_child(value, text);
xmpp_stanza_release(text);
xmpp_stanza_add_child(reply, query);
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
xmpp_send(conn, reply);
xmpp_stanza_release(reply);
xmpp_stanza_add_child(x, field);
xmpp_stanza_release(field);
free(client_name);
}
xmpp_stanza_add_child(query, x);
xmpp_stanza_release(x);
xmpp_stanza_add_child(reply, query);
xmpp_send(conn, reply);
xmpp_stanza_release(reply);
free(client_name);
pubsub = xmpp_stanza_get_child_by_name_and_ns(
stanza, "pubsub", "http://jabber.org/protocol/pubsub");
if (pubsub)
{
const char *items_node, *item_id, *device_id, *ns, *node;
items = xmpp_stanza_get_child_by_name(pubsub, "items");
if (items)
items_node = xmpp_stanza_get_attribute(items, "node");
if (items && items_node
&& weechat_strcasecmp(items_node,
"eu.siacs.conversations.axolotl.devicelist") == 0)
{
item = xmpp_stanza_get_child_by_name(items, "item");
if (item)
item_id = xmpp_stanza_get_id(item);
if (item && item_id && weechat_strcasecmp(item_id, "current") == 0)
{
list = xmpp_stanza_get_child_by_name_and_ns(
item, "list", "eu.siacs.conversations.axolotl");
if (list)
{
account__free_device_all(account);
struct t_device *dev = malloc(sizeof(dev));
char id[64] = {0};
dev->id = account->omemo->device_id;
snprintf(id, sizeof(id), "%d", dev->id);
dev->name = strdup(id);
account__add_device(account, dev);
free(dev->name);
free(dev);
for (device = xmpp_stanza_get_children(list);
device; device = xmpp_stanza_get_next(device))
{
device_id = xmpp_stanza_get_id(device);
dev = malloc(sizeof(dev));
dev->id = atoi(device_id);
dev->name = strdup(device_id);
account__add_device(account, dev);
free(dev->name);
free(dev);
}
reply = xmpp_stanza_reply(stanza);
xmpp_stanza_set_type(reply, "result");
children[1] = NULL;
children[0] = stanza__iq_pubsub_publish_item_list_device(
account->context, NULL, with_noop(id));
ns = "http://jabber.org/protocol/pubsub";
children[0] = stanza__iq_pubsub_publish_item_list(
account->context, NULL, children, with_noop(ns));
node = "eu.siacs.conversations.axolotl.devicelist";
children[0] = stanza__iq_pubsub_publish_item(
account->context, NULL, children, with_noop(node));
children[0] = stanza__iq_pubsub_publish(account->context,
NULL, children,
with_noop(ns));
children[0] = stanza__iq_pubsub(account->context, NULL,
children, with_noop(""));
reply = stanza__iq(account->context, reply, children, NULL,
NULL, NULL, NULL, NULL);
xmpp_send(conn, reply);
xmpp_stanza_release(reply);
}
}
}
}
return 1;
}
@ -441,18 +532,21 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status,
(void)error;
(void)stream_error;
if (status == XMPP_CONN_CONNECT) {
if (status == XMPP_CONN_CONNECT)
{
xmpp_stanza_t *pres, *pres__c, *pres__status, *pres__status__text, **children;
char cap_hash[28+1] = {0};
xmpp_handler_add(conn, connection__version_handler,
xmpp_handler_add(conn, &connection__version_handler,
"jabber:iq:version", "iq", NULL, account);
xmpp_handler_add(conn, connection__presence_handler,
xmpp_handler_add(conn, &connection__presence_handler,
NULL, "presence", NULL, account);
xmpp_handler_add(conn, connection__message_handler,
xmpp_handler_add(conn, &connection__message_handler,
NULL, "message", /*type*/ NULL, account);
xmpp_handler_add(conn, connection__iq_handler,
NULL, "iq", "get", account);
//xmpp_handler_add(conn, &connection__iq_handler,
// NULL, "iq", "get", account);
xmpp_handler_add(conn, &connection__iq_handler,
NULL, "iq", NULL, account);
/* Send initial <presence/> so that we appear online to contacts */
children = malloc(sizeof(*children) * (2 + 1));
@ -495,7 +589,7 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status,
strdup("eu.siacs.conversations.axolotl.devicelist"));
children[0] =
stanza__iq_pubsub(account->context, NULL, children,
strdup("http://jabber.org/protocol/pubsub"));
with_noop("http://jabber.org/protocol/pubsub"));
children[0] =
stanza__iq(account->context, NULL, children, NULL, strdup("fetch1"),
strdup(account_jid(account)), strdup(account_jid(account)),
@ -504,8 +598,10 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status,
xmpp_send(conn, children[0]);
xmpp_stanza_release(children[0]);
omemo__init(account);
} else {
omemo__init(&account->omemo, 0, NULL);
}
else
{
account__disconnect(account, 1);
//xmpp_stop(account->context); //keep context?
}

@ -4,13 +4,58 @@
#include <stdlib.h>
#include "omemo/src/libomemo.h"
#include "axc/src/axc.h"
#include "omemo.h"
void omemo__init()
void omemo__init(struct t_omemo **omemo, uint32_t device,
struct t_identity *identity)
{
const char* ns_devicelist = "eu.siacs.conversations.axolotl.devicelist";
const char* ft_devicelist = "eu.siacs.conversations.axolotl.devicelist+notify";
int rc;
srandom(time(NULL));
omemo_bundle* bundle;
rc = omemo_bundle_create(&bundle);
if (rc)
return;
if (!device)
device = random();
omemo_bundle_set_device_id(bundle, device);
if (identity)
omemo_bundle_set_identity_key(bundle, identity->key, identity->length);
else
{
identity = malloc(sizeof(*identity));
identity->length = 4;
identity->key = malloc(sizeof(*identity->key) * identity->length);
identity->key[0] = random();
identity->key[1] = random();
identity->key[2] = random();
identity->key[3] = random();
omemo_bundle_set_identity_key(bundle, identity->key, identity->length);
free(identity->key);
free(identity);
}
*omemo = malloc(sizeof(**omemo));
(*omemo)->provider.random_bytes_func = omemo_default_crypto_random_bytes;
(*omemo)->provider.aes_gcm_encrypt_func = omemo_default_crypto_aes_gcm_encrypt;
(*omemo)->provider.aes_gcm_decrypt_func = omemo_default_crypto_aes_gcm_decrypt;
(*omemo)->provider.user_data_p = (void *)(*omemo);
(*omemo)->bundle = bundle;
(*omemo)->device_id = omemo_bundle_get_device_id(bundle);
omemo_bundle_get_identity_key(bundle, &(*omemo)->identity.key, &(*omemo)->identity.length);
omemo_devicelist *devicelist;
}
void omemo__free(struct t_omemo *omemo)
{
free(omemo);
}

@ -5,6 +5,32 @@
#ifndef _WEECHAT_XMPP_OMEMO_H_
#define _WEECHAT_XMPP_OMEMO_H_
void omemo__init();
#include "axc/src/axc.h"
#include "omemo/src/libomemo.h"
#include "omemo/src/libomemo_crypto.h"
struct t_identity
{
uint8_t *key;
size_t length;
};
struct t_omemo
{
omemo_crypto_provider provider;
omemo_devicelist *devicelist;
omemo_bundle *bundle;
struct t_identity identity;
uint32_t device_id;
};
void omemo__init(struct t_omemo **omemo, uint32_t device,
struct t_identity *identity);
void omemo__free(struct t_omemo *omemo);
#endif /*WEECHAT_XMPP_OMEMO_H*/

@ -5,6 +5,8 @@
#include <stdlib.h>
#include <strophe.h>
#include "stanza.h"
xmpp_stanza_t *stanza__iq(xmpp_ctx_t *context, xmpp_stanza_t *base,
xmpp_stanza_t **children, char *ns, char *id,
char *from, char *to, char *type)
@ -54,7 +56,7 @@ xmpp_stanza_t *stanza__iq(xmpp_ctx_t *context, xmpp_stanza_t *base,
}
xmpp_stanza_t *stanza__iq_pubsub(xmpp_ctx_t *context, xmpp_stanza_t *base,
xmpp_stanza_t **children, char *ns)
xmpp_stanza_t **children, struct t_string *ns)
{
xmpp_stanza_t *parent = base;
xmpp_stanza_t **child = children;
@ -67,7 +69,8 @@ xmpp_stanza_t *stanza__iq_pubsub(xmpp_ctx_t *context, xmpp_stanza_t *base,
if (ns)
{
xmpp_stanza_set_ns(parent, ns);
xmpp_stanza_set_ns(parent, ns->value);
ns->finalize(ns);
free(ns);
}
@ -100,3 +103,135 @@ xmpp_stanza_t *stanza__iq_pubsub_items(xmpp_ctx_t *context, xmpp_stanza_t *base,
return parent;
}
xmpp_stanza_t *stanza__iq_pubsub_publish(xmpp_ctx_t *context, xmpp_stanza_t *base,
xmpp_stanza_t **children, struct t_string *node)
{
xmpp_stanza_t *parent = base;
xmpp_stanza_t **child = children;
if (!parent)
{
parent = xmpp_stanza_new(context);
xmpp_stanza_set_name(parent, "publish");
}
if (node)
{
xmpp_stanza_set_attribute(parent, "node", node->value);
node->finalize(node);
free(node);
}
while (*child)
{
xmpp_stanza_add_child(parent, *child);
xmpp_stanza_release(*child);
++child;
}
return parent;
}
xmpp_stanza_t *stanza__iq_pubsub_publish_item(xmpp_ctx_t *context, xmpp_stanza_t *base,
xmpp_stanza_t **children, struct t_string *id)
{
xmpp_stanza_t *parent = base;
xmpp_stanza_t **child = children;
if (!parent)
{
parent = xmpp_stanza_new(context);
xmpp_stanza_set_name(parent, "item");
}
if (id)
{
xmpp_stanza_set_id(parent, id->value);
id->finalize(id);
free(id);
}
while (*child)
{
xmpp_stanza_add_child(parent, *child);
xmpp_stanza_release(*child);
++child;
}
return parent;
}
xmpp_stanza_t *stanza__iq_pubsub_publish_item_list(xmpp_ctx_t *context, xmpp_stanza_t *base,
xmpp_stanza_t **children, struct t_string *ns)
{
xmpp_stanza_t *parent = base;
xmpp_stanza_t **child = children;
if (!parent)
{
parent = xmpp_stanza_new(context);
xmpp_stanza_set_name(parent, "list");
}
if (ns)
{
xmpp_stanza_set_ns(parent, ns->value);
ns->finalize(ns);
free(ns);
}
while (*child)
{
xmpp_stanza_add_child(parent, *child);
xmpp_stanza_release(*child);
++child;
}
return parent;
}
xmpp_stanza_t *stanza__iq_pubsub_publish_item_list_device(xmpp_ctx_t *context, xmpp_stanza_t *base,
struct t_string *id)
{
xmpp_stanza_t *parent = base;
if (!parent)
{
parent = xmpp_stanza_new(context);
xmpp_stanza_set_name(parent, "device");
}
if (id)
{
xmpp_stanza_set_id(parent, id->value);
id->finalize(id);
free(id);
}
return parent;
}
xmpp_stanza_t *stanza__iq_ping(xmpp_ctx_t *context, xmpp_stanza_t *base,
struct t_string *ns)
{
xmpp_stanza_t *parent = base;
if (!parent)
{
parent = xmpp_stanza_new(context);
xmpp_stanza_set_name(parent, "ping");
}
if (ns)
{
xmpp_stanza_set_ns(parent, ns->value);
ns->finalize(ns);
free(ns);
}
return parent;
}

@ -5,6 +5,50 @@
#ifndef _WEECHAT_XMPP_STANZA_H_
#define _WEECHAT_XMPP_STANZA_H_
struct t_string
{
char *value;
void (*finalize)(struct t_string *);
void *pointer;
};
static void t_string_noop(struct t_string *string)
{ (void)string; }
static void t_string_free(struct t_string *string)
{ free(string->value); }
static void t_string_xmpp_free(struct t_string *string)
{ xmpp_free(string->pointer, string->value); }
static inline struct t_string *with_noop(const char *const value)
{
struct t_string *string = malloc(sizeof(struct t_string));
string->value = (char*)value;
string->finalize = &t_string_noop;
string->pointer = NULL;
return string;
}
static inline struct t_string *with_free(char *value)
{
struct t_string *string = malloc(sizeof(struct t_string));
string->value = value;
string->finalize = &t_string_free;
string->pointer = NULL;
return string;
}
static inline struct t_string *with_xmpp_free(char *value, xmpp_ctx_t *pointer)
{
struct t_string *string = malloc(sizeof(struct t_string));
string->value = value;
string->finalize = &t_string_xmpp_free;
string->pointer = pointer;
return string;
}
xmpp_stanza_t *stanza__presence(xmpp_ctx_t *context, xmpp_stanza_t *base,
xmpp_stanza_t **children, const char *ns,
char *from, char *to, const char *type);
@ -14,8 +58,23 @@ xmpp_stanza_t *stanza__iq(xmpp_ctx_t *context, xmpp_stanza_t *base,
char *from, char *to, char *type);
xmpp_stanza_t *stanza__iq_pubsub(xmpp_ctx_t *context, xmpp_stanza_t *base,
xmpp_stanza_t **children, char *ns);
xmpp_stanza_t **children, struct t_string *ns);
xmpp_stanza_t *stanza__iq_pubsub_items(xmpp_ctx_t *context, xmpp_stanza_t *base, char *node);
xmpp_stanza_t *stanza__iq_pubsub_publish(xmpp_ctx_t *context, xmpp_stanza_t *base,
xmpp_stanza_t **children, struct t_string *node);
xmpp_stanza_t *stanza__iq_pubsub_publish_item(xmpp_ctx_t *context, xmpp_stanza_t *base,
xmpp_stanza_t **children, struct t_string *id);
xmpp_stanza_t *stanza__iq_pubsub_publish_item_list(xmpp_ctx_t *context, xmpp_stanza_t *base,
xmpp_stanza_t **children, struct t_string *ns);
xmpp_stanza_t *stanza__iq_pubsub_publish_item_list_device(xmpp_ctx_t *context, xmpp_stanza_t *base,
struct t_string *id);
xmpp_stanza_t *stanza__iq_ping(xmpp_ctx_t *context, xmpp_stanza_t *base,
struct t_string *ns);
#endif /*WEECHAT_XMPP_STANZA_H*/

Loading…
Cancel
Save