weechat-xmpp/connection.c

1161 lines
47 KiB
C
Raw Normal View History

2021-06-26 14:17:00 +00:00
// This Source Code Form is subject to the terms of the Mozilla Public
// 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/.
2021-07-02 06:48:09 +00:00
#include <time.h>
2021-06-26 14:17:00 +00:00
#include <stdlib.h>
2021-07-16 02:44:46 +00:00
#include <stdint.h>
2021-07-02 06:48:09 +00:00
#include <stdio.h>
2021-06-26 14:17:00 +00:00
#include <string.h>
2021-07-05 00:31:57 +00:00
#include <sys/utsname.h>
2021-06-26 14:17:00 +00:00
#include <strophe.h>
#include <weechat/weechat-plugin.h>
2021-06-28 01:17:02 +00:00
#include "plugin.h"
2021-07-12 17:01:04 +00:00
#include "diff/diff.h"
2021-07-05 00:31:57 +00:00
#include "xmpp/stanza.h"
2021-06-28 01:17:02 +00:00
#include "config.h"
2021-06-30 08:54:59 +00:00
#include "account.h"
2021-07-01 22:08:12 +00:00
#include "user.h"
2021-06-30 08:54:59 +00:00
#include "channel.h"
2021-06-28 01:17:02 +00:00
#include "connection.h"
2021-07-05 00:31:57 +00:00
#include "omemo.h"
2021-07-22 04:04:15 +00:00
#include "pgp.h"
2021-07-13 03:03:34 +00:00
#include "util.h"
2021-06-26 14:17:00 +00:00
2021-06-30 06:26:06 +00:00
void connection__init()
2021-06-26 14:17:00 +00:00
{
xmpp_initialize();
2021-06-27 22:51:05 +00:00
}
2021-06-26 14:17:00 +00:00
2021-07-04 05:39:30 +00:00
int connection__version_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
2021-06-28 01:00:49 +00:00
{
xmpp_stanza_t *reply, *query, *name, *version, *text;
const char *ns;
2021-06-30 08:54:59 +00:00
struct t_account *account = (struct t_account *)userdata;
const char *weechat_name = "weechat";
2021-07-05 00:31:57 +00:00
char *weechat_version = weechat_info_get("version", NULL);
2021-06-28 01:00:49 +00:00
weechat_printf(NULL, "Received version request from %s", xmpp_stanza_get_from(stanza));
reply = xmpp_stanza_reply(stanza);
xmpp_stanza_set_type(reply, "result");
2021-06-30 08:54:59 +00:00
query = xmpp_stanza_new(account->context);
2021-06-28 01:00:49 +00:00
xmpp_stanza_set_name(query, "query");
ns = xmpp_stanza_get_ns(xmpp_stanza_get_children(stanza));
if (ns) {
xmpp_stanza_set_ns(query, ns);
}
2021-06-30 08:54:59 +00:00
name = xmpp_stanza_new(account->context);
2021-06-28 01:00:49 +00:00
xmpp_stanza_set_name(name, "name");
xmpp_stanza_add_child(query, name);
xmpp_stanza_release(name);
2021-06-30 08:54:59 +00:00
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, weechat_name);
2021-06-28 01:00:49 +00:00
xmpp_stanza_add_child(name, text);
xmpp_stanza_release(text);
2021-06-30 08:54:59 +00:00
version = xmpp_stanza_new(account->context);
2021-06-28 01:00:49 +00:00
xmpp_stanza_set_name(version, "version");
2021-07-03 23:22:57 +00:00
xmpp_stanza_add_child(query, version);
2021-06-28 01:00:49 +00:00
xmpp_stanza_release(version);
2021-06-30 08:54:59 +00:00
text = xmpp_stanza_new(account->context);
2021-07-03 23:22:57 +00:00
xmpp_stanza_set_text(text, weechat_version);
2021-06-28 01:00:49 +00:00
xmpp_stanza_add_child(version, text);
xmpp_stanza_release(text);
xmpp_stanza_add_child(reply, query);
xmpp_stanza_release(query);
xmpp_send(conn, reply);
xmpp_stanza_release(reply);
2021-07-05 00:31:57 +00:00
if (weechat_version)
free(weechat_version);
2021-06-30 08:54:59 +00:00
2021-06-28 01:00:49 +00:00
return 1;
}
2021-07-04 05:39:30 +00:00
int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
2021-07-02 08:29:21 +00:00
{
2021-07-03 23:22:57 +00:00
(void) conn;
2021-07-02 08:29:21 +00:00
struct t_account *account = (struct t_account *)userdata;
2021-07-02 16:26:23 +00:00
struct t_user *user;
struct t_channel *channel;
2021-07-22 05:27:39 +00:00
xmpp_stanza_t *iq__x_signed, *iq__x_muc_user, *iq__x__item, *iq__c, *iq__status;
2021-07-22 04:04:15 +00:00
const char *from, *from_bare, *from_res, *role = NULL, *affiliation = NULL, *jid = NULL;
2021-07-22 05:27:39 +00:00
const char *certificate = NULL, *node = NULL, *ver = NULL;
2021-07-12 17:01:04 +00:00
char *clientid = NULL, *status;
2021-07-02 08:29:21 +00:00
from = xmpp_stanza_get_from(stanza);
if (from == NULL)
return 1;
from_bare = xmpp_jid_bare(account->context, from);
2021-07-22 04:04:15 +00:00
from_res = xmpp_jid_resource(account->context, from);
2021-07-22 05:27:39 +00:00
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(
2021-07-04 05:39:30 +00:00
stanza, "x", "http://jabber.org/protocol/muc#user");
2021-07-22 05:27:39 +00:00
if (iq__x_muc_user)
2021-07-04 05:39:30 +00:00
{
2021-07-22 05:27:39 +00:00
iq__x__item = xmpp_stanza_get_child_by_name(iq__x_muc_user, "item");
2021-07-04 05:39:30 +00:00
role = xmpp_stanza_get_attribute(iq__x__item, "role");
affiliation = xmpp_stanza_get_attribute(iq__x__item, "affiliation");
2021-07-12 17:01:04 +00:00
jid = xmpp_stanza_get_attribute(iq__x__item, "jid");
2021-07-04 05:39:30 +00:00
}
2021-07-12 17:01:04 +00:00
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)
{
int len = strlen(node)+1+strlen(ver);
clientid = malloc(sizeof(char)*len);
snprintf(clientid, len, "%s#%s", node, ver);
}
}
iq__status = xmpp_stanza_get_child_by_name(stanza, "status");
status = iq__status ? xmpp_stanza_get_text(iq__status) : NULL;
2021-07-02 08:29:21 +00:00
2021-07-22 04:04:15 +00:00
channel = channel__search(account, from_bare);
2021-07-22 05:27:39 +00:00
if (!iq__x_muc_user && !channel)
2021-07-22 04:04:15 +00:00
channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare);
2021-07-22 05:27:39 +00:00
if (certificate)
{
2021-07-22 05:53:36 +00:00
channel->pgp_id = pgp__verify(channel->buffer, account->pgp, certificate);
2021-07-22 05:27:39 +00:00
weechat_printf(channel->buffer, "[PGP]\t%sKey %s from %s",
weechat_color("gray"), channel->pgp_id, from);
}
2021-07-22 04:04:15 +00:00
2021-07-02 16:26:23 +00:00
user = user__search(account, from);
2021-07-02 08:29:21 +00:00
if (!user)
2021-07-22 04:04:15 +00:00
user = user__new(account, from,
channel && weechat_strcasecmp(from_bare, channel->id) == 0
? from_res : from);
2021-07-02 08:29:21 +00:00
2021-07-22 05:27:39 +00:00
if (!iq__x_muc_user)
2021-07-04 05:39:30 +00:00
{
2021-07-12 17:01:04 +00:00
channel__add_member(account, channel, from, clientid, status);
2021-07-04 05:39:30 +00:00
}
else if (channel)
{
2021-07-07 17:27:06 +00:00
channel__set_member_role(account, channel, from, role);
channel__set_member_affiliation(account, channel, from, affiliation);
2021-07-04 05:39:30 +00:00
if (weechat_strcasecmp(role, "none") == 0)
2021-07-12 17:01:04 +00:00
channel__remove_member(account, channel, from, status);
2021-07-05 21:59:54 +00:00
else
2021-07-12 17:01:04 +00:00
channel__add_member(account, channel, from, clientid, status);
2021-07-04 05:39:30 +00:00
}
2021-07-02 08:29:21 +00:00
2021-07-12 17:01:04 +00:00
if (clientid)
free(clientid);
2021-07-02 08:29:21 +00:00
return 1;
}
2021-07-04 05:39:30 +00:00
int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
2021-06-28 01:00:49 +00:00
{
2021-07-03 23:22:57 +00:00
(void) conn;
2021-06-30 08:54:59 +00:00
struct t_account *account = (struct t_account *)userdata;
2021-07-02 16:26:23 +00:00
struct t_channel *channel;
2021-07-22 04:04:15 +00:00
xmpp_stanza_t *x, *body, *delay, *topic, *replace, *composing, *sent, *received, *forwarded;
2021-07-16 02:44:46 +00:00
const char *type, *from, *nick, *from_bare, *to, *to_bare, *id, *replace_id, *timestamp;
2021-07-22 04:04:15 +00:00
char *text, *intext, *difftext = NULL, *cleartext = NULL;
2021-07-02 08:29:21 +00:00
struct tm time = {0};
time_t date = 0;
2021-06-28 01:00:49 +00:00
body = xmpp_stanza_get_child_by_name(stanza, "body");
if (body == NULL)
2021-07-02 16:26:23 +00:00
{
topic = xmpp_stanza_get_child_by_name(stanza, "subject");
2021-07-16 02:44:46 +00:00
if (topic != NULL)
{
intext = xmpp_stanza_get_text(topic);
from = xmpp_stanza_get_from(stanza);
if (from == NULL)
return 1;
from_bare = xmpp_jid_bare(account->context, from);
from = xmpp_jid_resource(account->context, from);
channel = channel__search(account, from_bare);
if (!channel)
channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare);
channel__update_topic(channel, intext ? intext : "", from, 0);
if (intext != NULL)
xmpp_free(account->context, intext);
}
composing = xmpp_stanza_get_child_by_name_and_ns(
stanza, "composing", "http://jabber.org/protocol/chatstates");
if (composing != NULL)
{
from = xmpp_stanza_get_from(stanza);
if (from == NULL)
return 1;
from_bare = xmpp_jid_bare(account->context, from);
2021-07-22 04:04:15 +00:00
nick = xmpp_jid_resource(account->context, from);
2021-07-16 02:44:46 +00:00
channel = channel__search(account, from_bare);
if (!channel)
return 1;
struct t_user *user = user__search(account, from);
if (!user)
2021-07-22 04:04:15 +00:00
user = user__new(account, from,
weechat_strcasecmp(from_bare, channel->id) == 0
? nick : from);
2021-07-16 02:44:46 +00:00
channel__add_typing(channel, user);
2021-07-22 04:04:15 +00:00
weechat_printf(channel->buffer, "...\t%s%s typing",
weechat_color("gray"),
weechat_strcasecmp(from_bare, channel->id) == 0
? nick : from);
2021-07-16 02:44:46 +00:00
}
sent = xmpp_stanza_get_child_by_name_and_ns(
stanza, "sent", "urn:xmpp:carbons:2");
if (sent)
forwarded = xmpp_stanza_get_child_by_name_and_ns(
sent, "forwarded", "urn:xmpp:forward:0");
received = xmpp_stanza_get_child_by_name_and_ns(
stanza, "received", "urn:xmpp:carbons:2");
if (received)
forwarded = xmpp_stanza_get_child_by_name_and_ns(
received, "forwarded", "urn:xmpp:forward:0");
2021-07-17 16:36:53 +00:00
if ((sent || received) && forwarded != NULL)
2021-07-16 02:44:46 +00:00
{
xmpp_stanza_t *message = xmpp_stanza_get_children(forwarded);
return connection__message_handler(conn, message, userdata);
}
2021-06-28 01:00:49 +00:00
return 1;
2021-07-02 16:26:23 +00:00
}
2021-06-28 01:00:49 +00:00
type = xmpp_stanza_get_type(stanza);
if (type != NULL && strcmp(type, "error") == 0)
return 1;
2021-06-30 08:54:59 +00:00
from = xmpp_stanza_get_from(stanza);
2021-07-01 21:08:50 +00:00
if (from == NULL)
return 1;
2021-06-30 22:31:20 +00:00
from_bare = xmpp_jid_bare(account->context, from);
to = xmpp_stanza_get_to(stanza);
2021-07-16 02:44:46 +00:00
to_bare = to ? xmpp_jid_bare(account->context, to) : NULL;
2021-07-05 21:50:38 +00:00
id = xmpp_stanza_get_id(stanza);
2021-07-16 02:44:46 +00:00
replace = xmpp_stanza_get_child_by_name_and_ns(stanza, "replace",
"urn:xmpp:message-correct:0");
2021-07-05 21:50:38 +00:00
replace_id = replace ? xmpp_stanza_get_id(replace) : NULL;
2021-06-28 01:00:49 +00:00
2021-07-22 05:53:36 +00:00
const char *channel_id = weechat_strcasecmp(account_jid(account), from_bare)
== 0 ? to_bare : from_bare;
channel = channel__search(account, channel_id);
if (!channel)
channel = channel__new(account,
weechat_strcasecmp(type, "groupchat") == 0
? CHANNEL_TYPE_MUC : CHANNEL_TYPE_PM,
channel_id, channel_id);
2021-07-22 04:04:15 +00:00
x = xmpp_stanza_get_child_by_name_and_ns(stanza, "x", "jabber:x:encrypted");
2021-06-28 01:00:49 +00:00
intext = xmpp_stanza_get_text(body);
2021-07-22 04:04:15 +00:00
if (x)
{
char *ciphertext = xmpp_stanza_get_text(x);
2021-07-22 05:53:36 +00:00
cleartext = pgp__decrypt(channel->buffer, account->pgp, ciphertext);
2021-07-22 04:04:15 +00:00
xmpp_free(account->context, ciphertext);
}
text = cleartext ? cleartext : intext;
2021-06-28 01:00:49 +00:00
2021-07-12 17:01:04 +00:00
if (replace)
{
const char *orig = NULL;
void *lines = weechat_hdata_pointer(weechat_hdata_get("buffer"),
channel->buffer, "lines");
if (lines)
{
void *last_line = weechat_hdata_pointer(weechat_hdata_get("lines"),
lines, "last_line");
while (last_line && !orig)
{
void *line_data = weechat_hdata_pointer(weechat_hdata_get("line"),
last_line, "data");
if (line_data)
{
int tags_count = weechat_hdata_integer(weechat_hdata_get("line_data"),
line_data, "tags_count");
char str_tag[20] = {0};
for (int n_tag = 0; n_tag < tags_count; n_tag++)
{
snprintf(str_tag, sizeof(str_tag), "%d|tags_array", n_tag);
const char *tag = weechat_hdata_string(weechat_hdata_get("line_data"),
line_data, str_tag);
if (strlen(tag) > strlen("id_") &&
weechat_strcasecmp(tag+strlen("id_"), replace_id) == 0)
{
2021-07-13 03:03:34 +00:00
struct t_arraylist *orig_lines = weechat_arraylist_new(
0, 0, 0, NULL, NULL, NULL, NULL);
char *msg = (char*)weechat_hdata_string(weechat_hdata_get("line_data"),
line_data, "message");
weechat_arraylist_insert(orig_lines, 0, msg);
while (msg)
{
last_line = weechat_hdata_pointer(weechat_hdata_get("line"),
last_line, "prev_line");
if (last_line)
line_data = weechat_hdata_pointer(weechat_hdata_get("line"),
last_line, "data");
else
line_data = NULL;
msg = NULL;
if (line_data)
{
tags_count = weechat_hdata_integer(weechat_hdata_get("line_data"),
line_data, "tags_count");
for (n_tag = 0; n_tag < tags_count; n_tag++)
{
snprintf(str_tag, sizeof(str_tag), "%d|tags_array", n_tag);
tag = weechat_hdata_string(weechat_hdata_get("line_data"),
line_data, str_tag);
if (strlen(tag) > strlen("id_") &&
weechat_strcasecmp(tag+strlen("id_"), replace_id) == 0)
{
msg = (char*)weechat_hdata_string(weechat_hdata_get("line_data"),
line_data, "message");
break;
}
}
}
if (msg)
weechat_arraylist_insert(orig_lines, 0, msg);
}
char **orig_message = weechat_string_dyn_alloc(256);
for (int i = 0; i < weechat_arraylist_size(orig_lines); i++)
weechat_string_dyn_concat(orig_message,
weechat_arraylist_get(orig_lines, i),
-1);
orig = *orig_message;
weechat_string_dyn_free(orig_message, 0);
2021-07-12 17:01:04 +00:00
break;
}
}
}
last_line = weechat_hdata_pointer(weechat_hdata_get("line"),
last_line, "prev_line");
}
}
if (orig)
{
struct diff result;
2021-07-22 04:04:15 +00:00
if (diff(&result, char_cmp, 1, orig, strlen(orig), text, strlen(text)) > 0)
2021-07-12 17:01:04 +00:00
{
char **visual = weechat_string_dyn_alloc(256);
char ch[2] = {0};
for (size_t i = 0; i < result.sessz; i++)
switch (result.ses[i].type)
{
case DIFF_ADD:
weechat_string_dyn_concat(visual, weechat_color("green"), -1);
*ch = *(const char *)result.ses[i].e;
weechat_string_dyn_concat(visual, ch, -1);
break;
case DIFF_DELETE:
weechat_string_dyn_concat(visual, weechat_color("red"), -1);
*ch = *(const char *)result.ses[i].e;
weechat_string_dyn_concat(visual, ch, -1);
break;
case DIFF_COMMON:
default:
weechat_string_dyn_concat(visual, weechat_color("resetcolor"), -1);
*ch = *(const char *)result.ses[i].e;
2021-07-16 02:44:46 +00:00
2021-07-12 17:01:04 +00:00
weechat_string_dyn_concat(visual, ch, -1);
break;
}
free(result.ses);
free(result.lcs);
difftext = strdup(*visual);
weechat_string_dyn_free(visual, 1);
}
}
}
2021-06-30 08:54:59 +00:00
2021-07-16 02:44:46 +00:00
nick = from;
2021-07-01 20:37:43 +00:00
if (weechat_strcasecmp(type, "groupchat") == 0)
{
2021-07-07 17:27:06 +00:00
nick = weechat_strcasecmp(channel->name,
2021-07-01 20:37:43 +00:00
xmpp_jid_bare(account->context,
from)) == 0
? xmpp_jid_resource(account->context, from)
: from;
}
2021-07-02 08:29:21 +00:00
delay = xmpp_stanza_get_child_by_name_and_ns(stanza, "delay", "urn:xmpp:delay");
timestamp = delay ? xmpp_stanza_get_attribute(delay, "stamp") : NULL;
if (timestamp)
{
strptime(timestamp, "%FT%T", &time);
date = mktime(&time);
}
2021-07-01 20:37:43 +00:00
2021-07-05 21:50:38 +00:00
char **dyn_tags = weechat_string_dyn_alloc(1);
weechat_string_dyn_concat(dyn_tags, "xmpp_message,message", -1);
2021-07-07 17:27:06 +00:00
{
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);
}
2021-07-05 21:50:38 +00:00
if (id)
{
weechat_string_dyn_concat(dyn_tags, ",id_", -1);
weechat_string_dyn_concat(dyn_tags, id, -1);
}
2021-07-17 16:36:53 +00:00
if (channel->type == CHANNEL_TYPE_PM)
2021-07-05 21:50:38 +00:00
weechat_string_dyn_concat(dyn_tags, ",private", -1);
2021-07-22 04:04:15 +00:00
if (weechat_string_match(text, "/me *", 0))
2021-07-17 16:36:53 +00:00
weechat_string_dyn_concat(dyn_tags, ",xmpp_action", -1);
2021-07-05 21:50:38 +00:00
if (replace)
{
weechat_string_dyn_concat(dyn_tags, ",edit", -1);
weechat_string_dyn_concat(dyn_tags, ",replace_", -1);
weechat_string_dyn_concat(dyn_tags, replace_id, -1);
}
if (date != 0)
weechat_string_dyn_concat(dyn_tags, ",notify_none", -1);
2021-07-22 04:04:15 +00:00
else if (channel->type == CHANNEL_TYPE_PM
&& weechat_strcasecmp(from_bare, account_jid(account)) != 0)
2021-07-17 16:36:53 +00:00
weechat_string_dyn_concat(dyn_tags, ",notify_private", -1);
2021-07-05 21:50:38 +00:00
else
weechat_string_dyn_concat(dyn_tags, ",log1", -1);
const char *edit = replace ? "* " : ""; // Losing which message was edited, sadly
2021-07-22 04:04:15 +00:00
if (x && text == cleartext)
weechat_printf(channel->buffer, "[~]\t%s%s: PGP", weechat_color("gray"), nick);
2021-07-16 02:44:46 +00:00
if (channel_id == from_bare && strcmp(to, channel->id) == 0)
2021-07-07 19:53:25 +00:00
weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s\t[to %s]: %s",
2021-07-07 17:27:06 +00:00
edit, user__as_prefix_raw(account, nick),
2021-07-22 04:04:15 +00:00
to, difftext ? difftext : text ? text : "");
else if (weechat_string_match(text, "/me *", 0))
2021-07-07 19:53:25 +00:00
weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s\t%s %s",
2021-07-22 04:04:15 +00:00
edit, weechat_prefix("action"), user__as_prefix_raw(account, nick),
difftext ? difftext+4 : text ? text+4 : "");
2021-07-01 02:07:18 +00:00
else
2021-07-07 19:53:25 +00:00
weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s\t%s",
2021-07-07 17:27:06 +00:00
edit, user__as_prefix_raw(account, nick),
2021-07-22 04:04:15 +00:00
difftext ? difftext : text ? text : "");
2021-06-28 01:00:49 +00:00
2021-07-05 21:50:38 +00:00
weechat_string_dyn_free(dyn_tags, 1);
2021-07-02 16:26:23 +00:00
if (intext)
xmpp_free(account->context, intext);
2021-07-12 17:01:04 +00:00
if (difftext)
free(difftext);
2021-07-22 04:04:15 +00:00
if (cleartext)
free(cleartext);
2021-06-28 01:00:49 +00:00
return 1;
}
2021-07-04 05:39:30 +00:00
int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
{
(void) conn;
struct t_account *account = (struct t_account *)userdata;
2021-07-16 02:44:46 +00:00
xmpp_stanza_t *reply, *query, *identity, *feature, *x, *field, *value, *text;
2021-07-07 19:53:25 +00:00
xmpp_stanza_t *pubsub, *items, *item, *list, *device, **children;
xmpp_stanza_t *storage, *conference, *nick;
2021-07-04 05:39:30 +00:00
static struct utsname osinfo;
query = xmpp_stanza_get_child_by_name_and_ns(
stanza, "query", "http://jabber.org/protocol/disco#info");
2021-07-07 19:53:25 +00:00
const char *type = xmpp_stanza_get_attribute(stanza, "type");
if (query && type && weechat_strcasecmp(type, "get") == 0)
2021-07-07 17:27:06 +00:00
{
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);
2021-07-07 19:53:25 +00:00
FEATURE("eu.siacs.conversations.axolotl.devicelist+notify");
2021-07-07 17:27:06 +00:00
FEATURE("http://jabber.org/protocol/caps");
2021-07-07 19:53:25 +00:00
FEATURE("http://jabber.org/protocol/chatstates");
2021-07-07 17:27:06 +00:00
FEATURE("http://jabber.org/protocol/disco#info");
FEATURE("http://jabber.org/protocol/disco#items");
FEATURE("http://jabber.org/protocol/muc");
2021-07-07 19:53:25 +00:00
FEATURE("http://jabber.org/protocol/nick+notify");
FEATURE("jabber:iq:version");
FEATURE("jabber:x:conference");
FEATURE("jabber:x:oob");
2021-07-07 17:27:06 +00:00
FEATURE("storage:bookmarks+notify");
2021-07-07 19:53:25 +00:00
FEATURE("urn:xmpp:avatar:metadata+notify");
FEATURE("urn:xmpp:chat-markers:0");
FEATURE("urn:xmpp:idle:1");
//FEATURE("urn:xmpp:jingle-message:0");
//FEATURE("urn:xmpp:jingle:1");
//FEATURE("urn:xmpp:jingle:apps:dtls:0");
//FEATURE("urn:xmpp:jingle:apps:file-transfer:3");
//FEATURE("urn:xmpp:jingle:apps:file-transfer:4");
//FEATURE("urn:xmpp:jingle:apps:file-transfer:5");
//FEATURE("urn:xmpp:jingle:apps:rtp:1");
//FEATURE("urn:xmpp:jingle:apps:rtp:audio");
//FEATURE("urn:xmpp:jingle:apps:rtp:video");
//FEATURE("urn:xmpp:jingle:jet-omemo:0");
//FEATURE("urn:xmpp:jingle:jet:0");
//FEATURE("urn:xmpp:jingle:transports:ibb:1");
//FEATURE("urn:xmpp:jingle:transports:ice-udp:1");
//FEATURE("urn:xmpp:jingle:transports:s5b:1");
FEATURE("urn:xmpp:message-correct:0");
FEATURE("urn:xmpp:ping");
FEATURE("urn:xmpp:receipts");
FEATURE("urn:xmpp:time");
2021-07-04 05:39:30 +00:00
#undef FEATURE
2021-07-07 17:27:06 +00:00
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");
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
if (uname(&osinfo) < 0)
{
*osinfo.sysname = 0;
*osinfo.release = 0;
}
2021-07-07 19:53:25 +00:00
// This is utter bullshit, TODO: anything but this.
2021-07-07 17:27:06 +00:00
{
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");
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
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);
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
xmpp_stanza_add_child(x, field);
xmpp_stanza_release(field);
}
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
{
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");
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
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);
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, "ipv6");
xmpp_stanza_add_child(value, text);
xmpp_stanza_release(text);
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
xmpp_stanza_add_child(x, field);
xmpp_stanza_release(field);
}
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
{
field = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(field, "field");
xmpp_stanza_set_attribute(field, "var", "os");
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, osinfo.sysname);
xmpp_stanza_add_child(value, text);
xmpp_stanza_release(text);
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
xmpp_stanza_add_child(x, field);
xmpp_stanza_release(field);
}
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
{
field = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(field, "field");
xmpp_stanza_set_attribute(field, "var", "os_version");
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, osinfo.release);
xmpp_stanza_add_child(value, text);
xmpp_stanza_release(text);
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
xmpp_stanza_add_child(x, field);
xmpp_stanza_release(field);
}
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
{
field = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(field, "field");
xmpp_stanza_set_attribute(field, "var", "software");
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(text, "weechat");
xmpp_stanza_add_child(value, text);
xmpp_stanza_release(text);
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
xmpp_stanza_add_child(x, field);
xmpp_stanza_release(field);
}
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
{
field = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(field, "field");
xmpp_stanza_set_attribute(field, "var", "software_version");
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
value = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(value, "value");
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
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);
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
xmpp_stanza_add_child(field, value);
xmpp_stanza_release(value);
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
xmpp_stanza_add_child(x, field);
xmpp_stanza_release(field);
}
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
xmpp_stanza_add_child(query, x);
xmpp_stanza_release(x);
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
xmpp_stanza_add_child(reply, query);
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
xmpp_send(conn, reply);
xmpp_stanza_release(reply);
2021-07-04 05:39:30 +00:00
2021-07-07 17:27:06 +00:00
free(client_name);
2021-07-04 05:39:30 +00:00
}
2021-07-07 17:27:06 +00:00
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)
{
2021-07-07 19:53:25 +00:00
items_node = xmpp_stanza_get_attribute(items, "node");
if (items_node
&& weechat_strcasecmp(items_node,
"eu.siacs.conversations.axolotl.devicelist") == 0)
2021-07-07 17:27:06 +00:00
{
2021-07-07 19:53:25 +00:00
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)
2021-07-07 17:27:06 +00:00
{
2021-07-07 19:53:25 +00:00
list = xmpp_stanza_get_child_by_name_and_ns(
item, "list", "eu.siacs.conversations.axolotl");
if (list)
2021-07-07 17:27:06 +00:00
{
2021-07-07 19:53:25 +00:00
account__free_device_all(account);
struct t_device *dev = malloc(sizeof(dev));
char id[64] = {0};
2021-07-07 17:27:06 +00:00
2021-07-07 19:53:25 +00:00
dev->id = account->omemo->device_id;
snprintf(id, sizeof(id), "%d", dev->id);
dev->name = strdup(id);
2021-07-07 17:27:06 +00:00
account__add_device(account, dev);
2021-07-07 19:53:25 +00:00
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));
2021-07-07 17:27:06 +00:00
free(dev->name);
free(dev);
2021-07-07 19:53:25 +00:00
for (device = xmpp_stanza_get_children(list);
device; device = xmpp_stanza_get_next(device))
{
const char *name = xmpp_stanza_get_name(device);
if (weechat_strcasecmp(name, "device") != 0)
continue;
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);
children[i++] = stanza__iq_pubsub_publish_item_list_device(
account->context, NULL, with_noop(dev->name));
free(dev->name);
free(dev);
}
children[i] = NULL;
2021-07-13 03:03:34 +00:00
node = "eu.siacs.conversations.axolotl";
2021-07-07 19:53:25 +00:00
children[0] = stanza__iq_pubsub_publish_item_list(
2021-07-13 03:03:34 +00:00
account->context, NULL, children, with_noop(node));
2021-07-07 19:53:25 +00:00
children[1] = NULL;
children[0] = stanza__iq_pubsub_publish_item(
account->context, NULL, children, with_noop("current"));
2021-07-13 03:03:34 +00:00
ns = "http://jabber.org/protocol/pubsub";
2021-07-07 19:53:25 +00:00
children[0] = stanza__iq_pubsub_publish(account->context,
NULL, children,
2021-07-13 03:03:34 +00:00
with_noop(ns));
2021-07-07 19:53:25 +00:00
children[0] = stanza__iq_pubsub(account->context, NULL,
children, with_noop(""));
reply = stanza__iq(account->context, xmpp_stanza_reply(stanza),
children, NULL, strdup("announce1"),
NULL, NULL, strdup("set"));
xmpp_send(conn, reply);
xmpp_stanza_release(reply);
2021-07-13 03:03:34 +00:00
char bundle_node[128] = {0};
snprintf(bundle_node, sizeof(bundle_node),
"eu.siacs.conversations.axolotl.bundles:%d",
account->omemo->device_id);
2021-07-16 02:44:46 +00:00
xmpp_stanza_t *textchild[2] = {NULL};
textchild[0] = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(textchild[0], "b64enc1");
children[0] = stanza__iq_pubsub_publish_item_bundle_signedPreKeyPublic(
account->context, NULL, textchild, with_noop("1"));
textchild[0] = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(textchild[0], "b64enc2");
children[1] = stanza__iq_pubsub_publish_item_bundle_signedPreKeySignature(
account->context, NULL, textchild);
textchild[0] = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(textchild[0], "b64enc3");
children[2] = stanza__iq_pubsub_publish_item_bundle_identityKey(
account->context, NULL, textchild);
textchild[0] = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(textchild[0], "b64enc4");
children[3] = stanza__iq_pubsub_publish_item_bundle_prekeys_preKeyPublic(
account->context, NULL, textchild, with_noop("1"));
textchild[0] = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(textchild[0], "b64enc5");
children[4] = stanza__iq_pubsub_publish_item_bundle_prekeys_preKeyPublic(
account->context, NULL, textchild, with_noop("2"));
textchild[0] = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(textchild[0], "b64enc6");
children[5] = stanza__iq_pubsub_publish_item_bundle_prekeys_preKeyPublic(
account->context, NULL, textchild, with_noop("3"));
children[6] = NULL;
children[3] = stanza__iq_pubsub_publish_item_bundle_prekeys(
account->context, NULL, &children[3]);
children[4] = NULL;
2021-07-13 03:03:34 +00:00
ns = "eu.siacs.conversations.axolotl";
children[0] = stanza__iq_pubsub_publish_item_bundle(
2021-07-16 02:44:46 +00:00
account->context, NULL, children, with_noop(ns));
2021-07-13 03:03:34 +00:00
children[1] = NULL;
children[0] = stanza__iq_pubsub_publish_item(
account->context, NULL, children, with_noop("current"));
children[0] = stanza__iq_pubsub_publish(account->context,
NULL, children,
with_noop(bundle_node));
children[0] =
stanza__iq_pubsub(account->context, NULL, children,
with_noop("http://jabber.org/protocol/pubsub"));
children[0] =
stanza__iq(account->context, NULL, children, NULL, strdup("announce2"),
strdup(account_jid(account)), strdup(account_jid(account)),
strdup("set"));
xmpp_send(conn, children[0]);
xmpp_stanza_release(children[0]);
free(children);
2021-07-07 19:53:25 +00:00
}
}
}
if (items_node
&& weechat_strcasecmp(items_node, "storage:bookmarks") == 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)
{
storage = xmpp_stanza_get_child_by_name_and_ns(
item, "storage", "storage:bookmarks");
if (storage)
{
for (conference = xmpp_stanza_get_children(storage);
conference; conference = xmpp_stanza_get_next(conference))
{
const char *name = xmpp_stanza_get_name(conference);
if (weechat_strcasecmp(name, "conference") != 0)
continue;
const char *jid = xmpp_stanza_get_attribute(conference, "jid");
const char *autojoin = xmpp_stanza_get_attribute(conference, "autojoin");
name = xmpp_stanza_get_attribute(conference, "name");
nick = xmpp_stanza_get_child_by_name(conference, "nick");
char *intext;
if (nick)
{
text = xmpp_stanza_get_children(nick);
intext = xmpp_stanza_get_text(text);
}
if (weechat_strcasecmp(autojoin, "true") == 0)
{
char **command = weechat_string_dyn_alloc(256);
weechat_string_dyn_concat(command, "/enter ", -1);
weechat_string_dyn_concat(command, jid, -1);
if (nick)
{
weechat_string_dyn_concat(command, "/", -1);
weechat_string_dyn_concat(command, intext, -1);
}
weechat_command(account->buffer, *command);
weechat_string_dyn_free(command, 1);
}
if (nick)
free(intext);
}
}
2021-07-07 17:27:06 +00:00
}
}
}
}
2021-07-05 00:31:57 +00:00
2021-07-04 05:39:30 +00:00
return 1;
}
2021-06-30 06:26:06 +00:00
void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status,
2021-06-30 08:54:59 +00:00
int error, xmpp_stream_error_t *stream_error,
void *userdata)
2021-06-27 22:51:05 +00:00
{
2021-06-30 08:54:59 +00:00
struct t_account *account = (struct t_account *)userdata;
2021-06-28 01:00:49 +00:00
(void)error;
(void)stream_error;
2021-07-07 17:27:06 +00:00
if (status == XMPP_CONN_CONNECT)
{
2021-07-22 06:48:57 +00:00
xmpp_stanza_t *pres, *pres__c, *pres__status, *pres__status__text,
*pres__x, *pres__x__text, **children;
2021-07-02 18:46:58 +00:00
char cap_hash[28+1] = {0};
2021-07-02 08:29:21 +00:00
2021-07-07 17:27:06 +00:00
xmpp_handler_add(conn, &connection__version_handler,
2021-07-04 05:39:30 +00:00
"jabber:iq:version", "iq", NULL, account);
2021-07-07 17:27:06 +00:00
xmpp_handler_add(conn, &connection__presence_handler,
2021-07-04 05:39:30 +00:00
NULL, "presence", NULL, account);
2021-07-07 17:27:06 +00:00
xmpp_handler_add(conn, &connection__message_handler,
2021-07-04 05:39:30 +00:00
NULL, "message", /*type*/ NULL, account);
2021-07-07 17:27:06 +00:00
//xmpp_handler_add(conn, &connection__iq_handler,
// NULL, "iq", "get", account);
xmpp_handler_add(conn, &connection__iq_handler,
NULL, "iq", NULL, account);
2021-06-28 01:00:49 +00:00
2021-07-22 06:48:57 +00:00
pgp__init(&account->pgp,
weechat_string_eval_expression(account_pgp_pubring_path(account),
NULL, NULL, NULL),
weechat_string_eval_expression(account_pgp_secring_path(account),
NULL, NULL, NULL));
2021-06-28 01:00:49 +00:00
/* Send initial <presence/> so that we appear online to contacts */
2021-07-22 06:48:57 +00:00
children = malloc(sizeof(*children) * (3 + 1));
2021-07-02 18:46:58 +00:00
pres__c = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(pres__c, "c");
xmpp_stanza_set_ns(pres__c, "http://jabber.org/protocol/caps");
xmpp_stanza_set_attribute(pres__c, "hash", "sha-1");
xmpp_stanza_set_attribute(pres__c, "node", "http://weechat.org");
2021-07-03 23:22:57 +00:00
snprintf(cap_hash, sizeof(cap_hash), "%027ld=", time(NULL));
2021-07-02 18:46:58 +00:00
xmpp_stanza_set_attribute(pres__c, "ver", cap_hash);
2021-07-05 00:31:57 +00:00
children[0] = pres__c;
2021-07-02 18:46:58 +00:00
2021-07-02 23:05:36 +00:00
pres__status = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(pres__status, "status");
pres__status__text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(pres__status__text, account_status(account));
xmpp_stanza_add_child(pres__status, pres__status__text);
xmpp_stanza_release(pres__status__text);
2021-07-05 00:31:57 +00:00
children[1] = pres__status;
children[2] = NULL;
2021-07-22 06:48:57 +00:00
if (account->pgp)
{
pres__x = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(pres__x, "x");
xmpp_stanza_set_ns(pres__x, "jabber:x:signed");
pres__x__text = xmpp_stanza_new(account->context);
char *signature = pgp__sign(account->buffer, account->pgp, account_pgp_keyid(account), account_status(account));
xmpp_stanza_set_text(pres__x__text, signature ? signature : "");
free(signature);
xmpp_stanza_add_child(pres__x, pres__x__text);
xmpp_stanza_release(pres__x__text);
children[2] = pres__x;
children[3] = NULL;
}
2021-07-05 00:31:57 +00:00
pres = stanza__presence(account->context, NULL,
children, NULL, strdup(account_jid(account)),
NULL, NULL);
2021-06-28 01:00:49 +00:00
xmpp_send(conn, pres);
xmpp_stanza_release(pres);
2021-07-03 20:58:55 +00:00
2021-07-16 02:44:46 +00:00
children[1] = NULL;
children[0] =
stanza__iq_enable(account->context, NULL, with_noop("urn:xmpp:carbons:2"));
children[0] =
stanza__iq(account->context, NULL, children,
strdup("jabber:client"), strdup("enable1"),
strdup(account_jid(account)), NULL, strdup("set"));
xmpp_send(conn, children[0]);
xmpp_stanza_release(children[0]);
2021-07-07 19:53:25 +00:00
children[1] = NULL;
children[0] =
stanza__iq_pubsub_items(account->context, NULL,
strdup("storage:bookmarks"));
children[0] =
stanza__iq_pubsub(account->context, NULL, children,
with_noop("http://jabber.org/protocol/pubsub"));
children[0] =
stanza__iq(account->context, NULL, children, NULL, strdup("retrieve1"),
strdup(account_jid(account)), strdup(account_jid(account)),
strdup("get"));
xmpp_send(conn, children[0]);
xmpp_stanza_release(children[0]);
2021-07-05 00:31:57 +00:00
2021-07-05 21:50:38 +00:00
children[1] = NULL;
children[0] =
stanza__iq_pubsub_items(account->context, NULL,
strdup("eu.siacs.conversations.axolotl.devicelist"));
children[0] =
stanza__iq_pubsub(account->context, NULL, children,
2021-07-07 17:27:06 +00:00
with_noop("http://jabber.org/protocol/pubsub"));
2021-07-05 21:50:38 +00:00
children[0] =
stanza__iq(account->context, NULL, children, NULL, strdup("fetch1"),
strdup(account_jid(account)), strdup(account_jid(account)),
strdup("get"));
xmpp_send(conn, children[0]);
xmpp_stanza_release(children[0]);
2021-07-08 03:19:49 +00:00
struct t_hashtable *variables = weechat_hashtable_new (8,
WEECHAT_HASHTABLE_STRING,
WEECHAT_HASHTABLE_STRING,
NULL, NULL);
weechat_hashtable_set(variables, "account", account->name);
char *dev_str = weechat_string_eval_expression(
"${sec.data.xmpp_device_${account}}",
NULL, variables, NULL);
char *b64_id = weechat_string_eval_expression(
"${sec.data.xmpp_identity_${account}}",
NULL, variables, NULL);
weechat_hashtable_free(variables);
uint32_t dev_id = dev_str[0] ? atoi(dev_str) : 0;
2021-07-12 17:01:04 +00:00
uint8_t identity[128] = {0};
if (b64_id && *b64_id)
2021-07-08 03:19:49 +00:00
weechat_string_base_decode(64, b64_id, (char*)identity);
struct t_identity id_key = {
2021-07-12 17:01:04 +00:00
.key = identity,
2021-07-08 03:19:49 +00:00
.length = 4,
};
2021-07-12 17:01:04 +00:00
omemo__init(&account->omemo, dev_id, b64_id && *b64_id ? &id_key : NULL);
2021-07-08 03:19:49 +00:00
char account_id[64] = {0};
snprintf(account_id, sizeof(account_id), "%d", account->omemo->device_id);
if (weechat_strcasecmp(dev_str, account_id) != 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, account_id, -1);
weechat_command(account->buffer, *command);
weechat_string_dyn_free(command, 1);
}
char account_key[64] = {0};
2021-07-16 02:44:46 +00:00
weechat_string_base_encode(64, (char*)account->omemo->identity->key,
account->omemo->identity->length, account_key);
2021-07-12 17:01:04 +00:00
if (weechat_strcasecmp(b64_id, account_key) != 0)
2021-07-08 03:19:49 +00:00
{
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);
2021-07-12 17:01:04 +00:00
weechat_string_dyn_concat(command, account_key, -1);
2021-07-08 03:19:49 +00:00
weechat_command(account->buffer, *command);
weechat_string_dyn_free(command, 1);
}
2021-07-07 17:27:06 +00:00
}
else
{
2021-07-05 16:33:26 +00:00
account__disconnect(account, 1);
//xmpp_stop(account->context); //keep context?
2021-06-28 01:00:49 +00:00
}
2021-06-26 14:17:00 +00:00
}
2021-07-04 05:39:30 +00:00
char* connection__rand_string(int length)
2021-07-02 06:48:09 +00:00
{
char *string = malloc(length);
srand(time(NULL));
for(int i = 0; i < length; ++i){
string[i] = '0' + rand()%72; // starting on '0', ending on '}'
if (!((string[i] >= '0' && string[i] <= '9') ||
(string[i] >= 'A' && string[i] <= 'Z') ||
(string[i] >= 'a' && string[i] <= 'z')))
i--; // reroll
}
string[length] = 0;
return string;
}
2021-06-30 08:54:59 +00:00
int connection__connect(struct t_account *account, xmpp_conn_t **connection,
const char* jid, const char* password, int tls)
2021-06-26 14:17:00 +00:00
{
2021-07-05 16:33:26 +00:00
static const unsigned ka_timeout_sec = 60;
static const unsigned ka_timeout_ivl = 1;
2021-06-30 08:54:59 +00:00
*connection = xmpp_conn_new(account->context);
2021-07-05 16:33:26 +00:00
xmpp_conn_set_keepalive(*connection, ka_timeout_sec, ka_timeout_ivl);
2021-07-03 23:22:57 +00:00
const char *resource = account_resource(account);
2021-07-02 06:48:09 +00:00
if (!(resource && strlen(resource)))
{
2021-07-04 05:39:30 +00:00
char *const rand = connection__rand_string(8);
2021-07-02 06:48:09 +00:00
char ident[64] = {0};
snprintf(ident, sizeof(ident), "weechat.%s", rand);
free(rand);
account_option_set(account, ACCOUNT_OPTION_RESOURCE, ident);
resource = account_resource(account);
}
xmpp_conn_set_jid(*connection,
xmpp_jid_new(account->context,
xmpp_jid_node(account->context, jid),
xmpp_jid_domain(account->context, jid),
resource));
2021-06-30 06:26:06 +00:00
xmpp_conn_set_pass(*connection, password);
2021-06-26 14:17:00 +00:00
2021-07-03 23:22:57 +00:00
int flags = xmpp_conn_get_flags(*connection);
2021-06-30 06:26:06 +00:00
switch (tls)
{
case 0:
flags |= XMPP_CONN_FLAG_DISABLE_TLS;
break;
case 1:
2021-07-02 08:29:21 +00:00
flags &= ~XMPP_CONN_FLAG_DISABLE_TLS;
flags &= ~XMPP_CONN_FLAG_TRUST_TLS;
2021-06-30 06:26:06 +00:00
break;
case 2:
flags |= XMPP_CONN_FLAG_TRUST_TLS;
break;
default:
break;
}
xmpp_conn_set_flags(*connection, flags);
2021-06-26 14:17:00 +00:00
2021-06-30 08:54:59 +00:00
if (xmpp_connect_client(*connection, NULL, 0, &connection__handler, account)
2021-06-30 06:26:06 +00:00
!= XMPP_EOK)
{
weechat_printf(
NULL,
_("%s%s: error connecting to %s"),
weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME,
jid);
return 0;
}
2021-06-26 14:17:00 +00:00
2021-06-30 06:26:06 +00:00
return 1;
2021-06-28 01:00:49 +00:00
}
2021-06-30 06:26:06 +00:00
void connection__process(xmpp_ctx_t *context, xmpp_conn_t *connection,
const unsigned long timeout)
2021-06-28 01:00:49 +00:00
{
2021-06-30 06:26:06 +00:00
if (connection)
2021-06-28 01:00:49 +00:00
{
2021-06-30 06:26:06 +00:00
xmpp_run_once(context ? context : xmpp_conn_get_context(connection),
timeout);
2021-06-28 01:00:49 +00:00
}
2021-06-26 14:17:00 +00:00
}