From 9c03d4d660d6788e4e088641f17061e2799de5ec Mon Sep 17 00:00:00 2001 From: Tony Olagbaiye Date: Fri, 16 Jul 2021 03:44:46 +0100 Subject: [PATCH] carbons --- .envrc | 3 +- Makefile | 16 +----- README.org | 16 +++--- account.c | 1 + channel.c | 1 + command.c | 2 +- connection.c | 150 ++++++++++++++++++++++++++++++++++++++----------- omemo.c | 153 +++++++++++++++++++++++++++++++++++++++----------- omemo.h | 15 ++--- xmpp/iq.c | 121 +++++++++++++++++++++++++++++++++++---- xmpp/stanza.h | 17 +++--- 11 files changed, 378 insertions(+), 117 deletions(-) diff --git a/.envrc b/.envrc index f61f48c..ae0bd87 100644 --- a/.envrc +++ b/.envrc @@ -37,8 +37,7 @@ use_guix() autoconf autoconf-archive automake libtool make cmake gcc-toolchain pkg-config patchelf weechat libxml2 libstrophe - glib libsignal-protocol-c sqlite - minixml + libgcrypt libsignal-protocol-c ) # Thanks diff --git a/Makefile b/Makefile index a7d0b0c..9936944 100644 --- a/Makefile +++ b/Makefile @@ -4,10 +4,10 @@ ifdef DEBUG endif RM=rm -f FIND=find -INCLUDES=-Ilibstrophe $(shell xml2-config --cflags) $(shell pkg-config --cflags glib-2.0) $(shell pkg-config --cflags libsignal-protocol-c) +INCLUDES=-Ilibstrophe $(shell xml2-config --cflags) $(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) -lmxml +LDLIBS=-lstrophe -lpthread $(shell xml2-config --libs) $(shell pkg-config --libs libsignal-protocol-c) -lgcrypt PREFIX ?= /usr/local LIBDIR ?= $(PREFIX)/lib @@ -28,7 +28,7 @@ SRCS=plugin.c \ xmpp/presence.c \ xmpp/iq.c \ -DEPS=omemo/build/libomemo-conversations.a axc/build/libaxc.a diff/libdiff.a +DEPS=diff/libdiff.a OBJS=$(subst .c,.o,$(SRCS)) all: weechat-xmpp @@ -40,14 +40,6 @@ 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 - diff/libdiff.a: cd diff && ./configure $(MAKE) -C diff CFLAGS=-fPIC @@ -72,8 +64,6 @@ tidy: clean: $(RM) -f $(OBJS) - $(MAKE) -C omemo clean || true - $(MAKE) -C axc clean || true $(MAKE) -C diff clean || true git submodule foreach --recursive git clean -xfd || true git submodule foreach --recursive git reset --hard || true diff --git a/README.org b/README.org index d16370a..8b95555 100644 --- a/README.org +++ b/README.org @@ -88,7 +88,9 @@ * [X] Opening PMs (/chat) ** TODO [#A] Implement essential functionality (milestone v0.2) * [X] Opening PMs with initial message - * [X] OOB media messages + * [-] OOB messages + * [X] Single media on a line + * [ ] Multiple media inline (protocol?) * [X] Buffer autoswitch on enter/open * [X] Handle open/enter jids with a resource without breaking * [X] Allow /close without crashing @@ -96,13 +98,13 @@ * [ ] [#B] Event-driven MUC entrance * [ ] [#C] XMPP Ping (xep-199) * [X] [#A] Highlight - * [ ] MUCs + * [-] MUCs * [X] Opening (/enter) * [ ] [#B] Leave on /close * [X] Receiving * [X] Sending * [X] With /msg - * [ ] [#B] Edits + * [-] [#B] Edits * [X] [#B] Displaying * [X] [#B] Tagging * [ ] [#B] Making @@ -113,11 +115,11 @@ * [X] [#B] Leaves * [X] [#B] Tracking * [X] [#B] Set/show topic - * [ ] OMEMO (libsignal-protocol-c / axc) - * [ ] Presence + * [-] OMEMO (libsignal-protocol-c / axc) + * [-] Presence * [X] Disco * [X] Disco response - * [ ] Key Generation / storage (secured_data?) + * [-] Key Generation / storage (secured_data?) * [X] Generation * [X] Storage * [ ] Announce @@ -128,7 +130,7 @@ * [ ] [#C] Read receipts * [ ] Message Carbons * [ ] Service Disco - * [ ] Bookmarks / Roster + * [-] Bookmarks / Roster * [X] Autojoin bookmarks * [ ] Add bookmarks * [ ] Delete bookmarks diff --git a/account.c b/account.c index a9583db..453fbe3 100644 --- a/account.c +++ b/account.c @@ -4,6 +4,7 @@ #include #include +#include #include #include #include diff --git a/channel.c b/channel.c index bebed0d..7a8a2a6 100644 --- a/channel.c +++ b/channel.c @@ -3,6 +3,7 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #include +#include #include #include #include diff --git a/command.c b/command.c index 85de4f5..c40b581 100644 --- a/command.c +++ b/command.c @@ -649,7 +649,7 @@ int command__me(const void *pointer, void *data, "xmpp_message,message,action,private,notify_none,self_msg,log1", "%s%s %s", weechat_prefix("action"), account_jid(ptr_account), - text); + strlen(text) > strlen("/me ") ? text+4 : ""); } return WEECHAT_RC_OK; diff --git a/connection.c b/connection.c index d58f940..6c24c90 100644 --- a/connection.c +++ b/connection.c @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -153,8 +154,8 @@ 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, *nick, *from_bare, *to, *id, *replace_id, *timestamp; + xmpp_stanza_t *body, *delay, *topic, *replace, *composing, *sent, *received, *forwarded; + const char *type, *from, *nick, *from_bare, *to, *to_bare, *id, *replace_id, *timestamp; char *intext, *difftext = NULL; struct tm time = {0}; time_t date = 0; @@ -163,20 +164,66 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * if (body == NULL) { topic = xmpp_stanza_get_child_by_name(stanza, "subject"); - if (topic == NULL) - return 1; - 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); + 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); + from = xmpp_jid_resource(account->context, from); + channel = channel__search(account, from_bare); + if (!channel) + return 1; + struct t_user *user = user__search(account, from); + if (!user) + user = user__new(account, from, from); + channel__add_typing(channel, user); + weechat_printf(channel->buffer, "%s typing...", from); + } + + 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 (sent && forwarded != NULL) + { + xmpp_stanza_t *message = xmpp_stanza_get_children(forwarded); + //from = xmpp_stanza_get_from(stanza); + //to = xmpp_stanza_get_to(stanza); + //xmpp_stanza_set_from(stanza, to); + //xmpp_stanza_set_to(stanza, from); + return connection__message_handler(conn, message, userdata); + } + if (received) + forwarded = xmpp_stanza_get_child_by_name_and_ns( + received, "forwarded", "urn:xmpp:forward:0"); + if (received && forwarded != NULL) + { + xmpp_stanza_t *message = xmpp_stanza_get_children(forwarded); + return connection__message_handler(conn, message, userdata); + } + return 1; } type = xmpp_stanza_get_type(stanza); @@ -187,15 +234,19 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * return 1; from_bare = xmpp_jid_bare(account->context, from); to = xmpp_stanza_get_to(stanza); + to_bare = to ? xmpp_jid_bare(account->context, to) : NULL; id = xmpp_stanza_get_id(stanza); - replace = xmpp_stanza_get_child_by_name_and_ns(stanza, "replace", "urn:xmpp:message-correct:0"); + replace = xmpp_stanza_get_child_by_name_and_ns(stanza, "replace", + "urn:xmpp:message-correct:0"); replace_id = replace ? xmpp_stanza_get_id(replace) : NULL; intext = xmpp_stanza_get_text(body); - channel = channel__search(account, from_bare); + 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, CHANNEL_TYPE_PM, from_bare, from_bare); + channel = channel__new(account, CHANNEL_TYPE_PM, channel_id, channel_id); if (replace) { const char *orig = NULL; @@ -304,6 +355,7 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * default: weechat_string_dyn_concat(visual, weechat_color("resetcolor"), -1); *ch = *(const char *)result.ses[i].e; + weechat_string_dyn_concat(visual, ch, -1); break; } @@ -316,7 +368,7 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * } } - nick = NULL; + nick = from; if (weechat_strcasecmp(type, "groupchat") == 0) { nick = weechat_strcasecmp(channel->name, @@ -366,7 +418,7 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * weechat_string_dyn_concat(dyn_tags, ",log1", -1); const char *edit = replace ? "* " : ""; // Losing which message was edited, sadly - if (strcmp(to, channel->id) == 0) + if (channel_id == from_bare && strcmp(to, channel->id) == 0) weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s\t[to %s]: %s", edit, user__as_prefix_raw(account, nick), to, difftext ? difftext : intext ? intext : ""); @@ -394,7 +446,7 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd (void) conn; struct t_account *account = (struct t_account *)userdata; - xmpp_stanza_t *reply, *query, *identity, *feature, *enable, *x, *field, *value, *text; + xmpp_stanza_t *reply, *query, *identity, *feature, *x, *field, *value, *text; xmpp_stanza_t *pubsub, *items, *item, *list, *device, **children; xmpp_stanza_t *storage, *conference, *nick; static struct utsname osinfo; @@ -461,12 +513,6 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd FEATURE("urn:xmpp:time"); #undef FEATURE - enable = xmpp_stanza_new(account->context); - xmpp_stanza_set_name(enable, "enable"); - xmpp_stanza_set_ns(enable, "urn:xmpp:carbons:2"); - xmpp_stanza_add_child(query, enable); - xmpp_stanza_release(enable); - x = xmpp_stanza_new(account->context); xmpp_stanza_set_name(x, "x"); xmpp_stanza_set_ns(x, "jabber:x:data"); @@ -710,11 +756,38 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd "eu.siacs.conversations.axolotl.bundles:%d", account->omemo->device_id); - children[1] = NULL; - children[0] = NULL; + 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; ns = "eu.siacs.conversations.axolotl"; children[0] = stanza__iq_pubsub_publish_item_bundle( - account->context, NULL, NULL, with_noop(ns)); + account->context, NULL, children, with_noop(ns)); children[1] = NULL; children[0] = stanza__iq_pubsub_publish_item( account->context, NULL, children, with_noop("current")); @@ -846,6 +919,17 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, xmpp_send(conn, pres); xmpp_stanza_release(pres); + 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]); + children[1] = NULL; children[0] = stanza__iq_pubsub_items(account->context, NULL, @@ -913,8 +997,8 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, weechat_string_dyn_free(command, 1); } char account_key[64] = {0}; - weechat_string_base_encode(64, (char*)account->omemo->identity.key, - account->omemo->identity.length, account_key); + weechat_string_base_encode(64, (char*)account->omemo->identity->key, + account->omemo->identity->length, account_key); if (weechat_strcasecmp(b64_id, account_key) != 0) { char **command = weechat_string_dyn_alloc(256); diff --git a/omemo.c b/omemo.c index d331bf1..c8e7795 100644 --- a/omemo.c +++ b/omemo.c @@ -3,57 +3,144 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #include +#include +#include +#include +#include #include "omemo.h" +/* +char *omemo__signal_init() +{ + signal_protocol_store_context *store_context_p = NULL; + + signal_protocol_session_store session_store = { + .load_session_func = &axc_db_session_load, + .get_sub_device_sessions_func = &axc_db_session_get_sub_device_sessions, + .store_session_func = &axc_db_session_store, + .contains_session_func = &axc_db_session_contains, + .delete_session_func = &axc_db_session_delete, + .delete_all_sessions_func = &axc_db_session_delete_all, + .destroy_func = &axc_db_session_destroy_store_ctx, + .user_data = ctx_p + }; + signal_protocol_pre_key_store pre_key_store = { + .load_pre_key = &axc_db_pre_key_load, + .store_pre_key = &axc_db_pre_key_store, + .contains_pre_key = &axc_db_pre_key_contains, + .remove_pre_key = &axc_db_pre_key_remove, + .destroy_func = &axc_db_pre_key_destroy_ctx, + .user_data = ctx_p + }; + signal_protocol_signed_pre_key_store signed_pre_key_store = { + .load_signed_pre_key = &axc_db_signed_pre_key_load, + .store_signed_pre_key = &axc_db_signed_pre_key_store, + .contains_signed_pre_key = &axc_db_signed_pre_key_contains, + .remove_signed_pre_key = &axc_db_signed_pre_key_remove, + .destroy_func = &axc_db_signed_pre_key_destroy_ctx, + .user_data = ctx_p + }; + signal_protocol_identity_key_store identity_key_store = { + .get_identity_key_pair = &axc_db_identity_get_key_pair, + .get_local_registration_id = &axc_db_identity_get_local_registration_id, + .save_identity = &axc_db_identity_save, + .is_trusted_identity = &axc_db_identity_always_trusted, + .destroy_func = &axc_db_identity_destroy_ctx, + .user_data = ctx_p + }; + + if (signal_context_create(&(ctx_p->axolotl_global_context_p), ctx_p)) { + return "failed to create global axolotl context"; + } + + signal_crypto_provider crypto_provider = { + .random_func = random_bytes, + .hmac_sha256_init_func = hmac_sha256_init, + .hmac_sha256_update_func = hmac_sha256_update, + .hmac_sha256_final_func = hmac_sha256_final, + .sha512_digest_init_func = sha512_digest_init, + .sha512_digest_update_func = sha512_digest_update, + .sha512_digest_final_func = sha512_digest_final, + .encrypt_func = aes_encrypt, + .decrypt_func = aes_decrypt, + .user_data = ctx_p + }; + if (signal_context_set_crypto_provider(ctx_p->axolotl_global_context_p, &crypto_provider)) { + return "failed to set crypto provider"; + } + + if (signal_context_set_locking_functions(ctx_p->axolotl_global_context_p, recursive_mutex_lock, recursive_mutex_unlock)) { + return "failed to set locking functions"; + } + + if (signal_protocol_store_context_create(&store_context_p, ctx_p->axolotl_global_context_p)) { + return "failed to create store context"; + } + + if (signal_protocol_store_context_set_session_store(store_context_p, &session_store)) { + return "failed to create session store"; + } + + if (signal_protocol_store_context_set_pre_key_store(store_context_p, &pre_key_store)) { + return "failed to set pre key store"; + } + + if (signal_protocol_store_context_set_signed_pre_key_store(store_context_p, &signed_pre_key_store)) { + return "failed to set signed pre key store"; + } + + if (signal_protocol_store_context_set_identity_key_store(store_context_p, &identity_key_store)) { + return "failed to set identity key store"; + } + + ctx_p->axolotl_store_context_p = store_context_p; + + return NULL; +} +*/ + void omemo__init(struct t_omemo **omemo, uint32_t device, - struct t_identity *identity) + struct t_identity *const identity) { - int rc; + struct t_omemo *new_omemo; 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); + new_omemo = calloc(1, sizeof(**omemo)); + new_omemo->identity = malloc(sizeof(*identity)); if (identity) - omemo_bundle_set_identity_key(bundle, identity->key, identity->length); + { + new_omemo->identity->length = identity->length; + new_omemo->identity->key = calloc(identity->length, sizeof(*identity->key)); + memcpy(new_omemo->identity->key, identity->key, + identity->length * sizeof(*identity->key)); + } 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(); + new_omemo->identity->length = 4; + new_omemo->identity->key = calloc(identity->length, sizeof(*identity->key)); - omemo_bundle_set_identity_key(bundle, identity->key, identity->length); - - free(identity->key); - free(identity); + new_omemo->identity->key[0] = random(); + new_omemo->identity->key[1] = random(); + new_omemo->identity->key[2] = random(); + new_omemo->identity->key[3] = random(); } - *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); + new_omemo->device_id = device ? device : random(); - omemo_devicelist *devicelist; + *omemo = new_omemo; } void omemo__free(struct t_omemo *omemo) { - free(omemo); + if (omemo) + { + if (omemo->identity->key) + free(omemo->identity->key); + if (omemo->identity) + free(omemo->identity); + free(omemo); + } } diff --git a/omemo.h b/omemo.h index faccd8e..3138849 100644 --- a/omemo.h +++ b/omemo.h @@ -5,10 +5,6 @@ #ifndef _WEECHAT_XMPP_OMEMO_H_ #define _WEECHAT_XMPP_OMEMO_H_ -#include "axc/src/axc.h" -#include "omemo/src/libomemo.h" -#include "omemo/src/libomemo_crypto.h" - struct t_identity { uint8_t *key; @@ -17,13 +13,12 @@ struct t_identity struct t_omemo { - omemo_crypto_provider provider; - - omemo_devicelist *devicelist; - - omemo_bundle *bundle; + //omemo_crypto_provider provider; + //axc_context *context; + //axc_bundle *a_bundle; + //omemo_bundle *o_bundle; - struct t_identity identity; + struct t_identity *identity; uint32_t device_id; }; diff --git a/xmpp/iq.c b/xmpp/iq.c index 1cf0b39..91c70e5 100644 --- a/xmpp/iq.c +++ b/xmpp/iq.c @@ -242,9 +242,10 @@ xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle(xmpp_ctx_t *context, xmpp_s } xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_signedPreKeyPublic( - xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *id) + xmpp_ctx_t *context, xmpp_stanza_t *base, xmpp_stanza_t **children, struct t_string *signedPreKeyId) { xmpp_stanza_t *parent = base; + xmpp_stanza_t **child = children; if (!parent) { @@ -252,34 +253,132 @@ xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_signedPreKeyPublic( xmpp_stanza_set_name(parent, "signedPreKeyPublic"); } - if (id) + if (signedPreKeyId) { - xmpp_stanza_set_id(parent, id->value); - id->finalize(id); - free(id); + xmpp_stanza_set_attribute(parent, "signedPreKeyId", signedPreKeyId->value); + signedPreKeyId->finalize(signedPreKeyId); + free(signedPreKeyId); + } + + while (child && *child) + { + xmpp_stanza_add_child(parent, *child); + xmpp_stanza_release(*child++); } return parent; } xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_signedPreKeySignature( - xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *signedPreKeySignature) + xmpp_ctx_t *context, xmpp_stanza_t *base, xmpp_stanza_t **children) { + xmpp_stanza_t *parent = base; + xmpp_stanza_t **child = children; + + if (!parent) + { + parent = xmpp_stanza_new(context); + xmpp_stanza_set_name(parent, "signedPreKeySignature"); + } + + while (child && *child) + { + xmpp_stanza_add_child(parent, *child); + xmpp_stanza_release(*child++); + } + + return parent; } xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_identityKey( - xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *identityKey) + xmpp_ctx_t *context, xmpp_stanza_t *base, xmpp_stanza_t **children) { + xmpp_stanza_t *parent = base; + xmpp_stanza_t **child = children; + + if (!parent) + { + parent = xmpp_stanza_new(context); + xmpp_stanza_set_name(parent, "identityKey"); + } + + while (child && *child) + { + xmpp_stanza_add_child(parent, *child); + xmpp_stanza_release(*child++); + } + + return parent; +} + +xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_prekeys( + xmpp_ctx_t *context, xmpp_stanza_t *base, xmpp_stanza_t **children) +{ + xmpp_stanza_t *parent = base; + xmpp_stanza_t **child = children; + + if (!parent) + { + parent = xmpp_stanza_new(context); + xmpp_stanza_set_name(parent, "prekeys"); + } + + while (child && *child) + { + xmpp_stanza_add_child(parent, *child); + xmpp_stanza_release(*child++); + } + + return parent; } -xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_preKeys( - xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *preKeys) +xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_prekeys_preKeyPublic( + xmpp_ctx_t *context, xmpp_stanza_t *base, xmpp_stanza_t **children, struct t_string *preKeyId) { + xmpp_stanza_t *parent = base; + xmpp_stanza_t **child = children; + + if (!parent) + { + parent = xmpp_stanza_new(context); + xmpp_stanza_set_name(parent, "preKeyPublic"); + } + + if (preKeyId) + { + xmpp_stanza_set_attribute(parent, "preKeyId", preKeyId->value); + preKeyId->finalize(preKeyId); + free(preKeyId); + } + + while (child && *child) + { + xmpp_stanza_add_child(parent, *child); + xmpp_stanza_release(*child++); + } + + return parent; } -xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_preKeys_preKeyPublic( - xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *preKeyPublic) +xmpp_stanza_t *stanza__iq_enable(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, "enable"); + } + + if (ns) + { + xmpp_stanza_set_ns(parent, ns->value); + ns->finalize(ns); + free(ns); + } + + return parent; } xmpp_stanza_t *stanza__iq_ping(xmpp_ctx_t *context, xmpp_stanza_t *base, diff --git a/xmpp/stanza.h b/xmpp/stanza.h index a03d054..e63f7de 100644 --- a/xmpp/stanza.h +++ b/xmpp/stanza.h @@ -78,19 +78,22 @@ xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle(xmpp_ctx_t *context, xmpp_s xmpp_stanza_t **children, struct t_string *ns); xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_signedPreKeyPublic( - xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *signedPreKeyId); + xmpp_ctx_t *context, xmpp_stanza_t *base, xmpp_stanza_t **children, struct t_string *signedPreKeyId); xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_signedPreKeySignature( - xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *signedPreKeySignature); + xmpp_ctx_t *context, xmpp_stanza_t *base, xmpp_stanza_t **children); xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_identityKey( - xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *identityKey); + xmpp_ctx_t *context, xmpp_stanza_t *base, xmpp_stanza_t **children); -xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_preKeys( - xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *preKeys); +xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_prekeys( + xmpp_ctx_t *context, xmpp_stanza_t *base, xmpp_stanza_t **children); -xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_preKeys_preKeyPublic( - xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *preKeyPublic); +xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle_prekeys_preKeyPublic( + xmpp_ctx_t *context, xmpp_stanza_t *base, xmpp_stanza_t **children, struct t_string *preKeyId); + +xmpp_stanza_t *stanza__iq_enable(xmpp_ctx_t *context, xmpp_stanza_t *base, + struct t_string *ns); xmpp_stanza_t *stanza__iq_ping(xmpp_ctx_t *context, xmpp_stanza_t *base, struct t_string *ns);