From 2837c4054f0c46f9cbbd0f09571e7d91501f2253 Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Sun, 30 Jun 2013 18:59:38 +0300 Subject: [PATCH] initial support of autojoin for MUC --- Makefile.am | 2 + src/xmpp/bookmark.c | 116 ++++++++++++++++++++++++++++++++++++++++++ src/xmpp/bookmark.h | 7 +++ src/xmpp/connection.c | 15 ++++++ src/xmpp/connection.h | 1 + src/xmpp/stanza.c | 57 +++++++++++++++++++++ src/xmpp/stanza.h | 6 +++ 7 files changed, 204 insertions(+) create mode 100644 src/xmpp/bookmark.c create mode 100644 src/xmpp/bookmark.h diff --git a/Makefile.am b/Makefile.am index f161b92a..72503004 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,6 +10,7 @@ profanity_SOURCES = \ src/xmpp/stanza.h src/xmpp/message.h src/xmpp/iq.h src/xmpp/presence.h \ src/xmpp/capabilities.h src/xmpp/connection.h \ src/xmpp/roster.c src/xmpp/roster.h \ + src/xmpp/bookmark.c src/xmpp/bookmark.h \ src/ui/ui.h src/ui/window.c src/ui/window.h src/ui/core.c \ src/ui/titlebar.c src/ui/statusbar.c src/ui/inputwin.c \ src/ui/console.c src/ui/notifier.c src/ui/notifier.h \ @@ -36,6 +37,7 @@ tests_testsuite_SOURCES = \ src/xmpp/stanza.h src/xmpp/message.h src/xmpp/iq.h src/xmpp/presence.h \ src/xmpp/capabilities.h src/xmpp/connection.h \ src/xmpp/roster.c src/xmpp/roster.h \ + src/xmpp/bookmark.c src/xmpp/bookmark.h \ src/ui/ui.h src/ui/window.c src/ui/window.h src/ui/core.c \ src/ui/titlebar.c src/ui/statusbar.c src/ui/inputwin.c \ src/ui/console.c src/ui/notifier.c src/ui/notifier.h \ diff --git a/src/xmpp/bookmark.c b/src/xmpp/bookmark.c new file mode 100644 index 00000000..e6d5efe3 --- /dev/null +++ b/src/xmpp/bookmark.c @@ -0,0 +1,116 @@ + +#include +#include +#include +#include +#include + +#include "log.h" +#include "muc.h" +#include "ui/ui.h" +#include "xmpp/connection.h" +#include "xmpp/stanza.h" +#include "xmpp/xmpp.h" + +static int _bookmark_handle_result(xmpp_conn_t * const conn, + xmpp_stanza_t * const stanza, void * const userdata); + +void +bookmark_request(void) +{ + int id; + char id_str[10]; + xmpp_conn_t * const conn = connection_get_conn(); + xmpp_ctx_t * const ctx = connection_get_ctx(); + xmpp_stanza_t *iq = stanza_create_storage_bookmarks(ctx); + + id = jabber_get_id(); + snprintf(id_str, sizeof(id_str), "%u", id); + + /* TODO: timed handler to remove this id_handler */ + xmpp_id_handler_add(conn, _bookmark_handle_result, id_str, ctx); + + xmpp_stanza_set_id(iq, id_str); + xmpp_send(conn, iq); + xmpp_stanza_release(iq); +} + +static int +_bookmark_handle_result(xmpp_conn_t * const conn, + xmpp_stanza_t * const stanza, void * const userdata) +{ + xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata; + xmpp_stanza_t *ptr; + xmpp_stanza_t *nick; + char *name; + char *jid; + char *autojoin; + Jid *my_jid; + + name = xmpp_stanza_get_name(stanza); + if (!name || strcmp(name, STANZA_NAME_IQ) != 0) { + return 0; + } + + ptr = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY); + if (!ptr) { + return 0; + } + ptr = xmpp_stanza_get_child_by_name(ptr, STANZA_NAME_STORAGE); + if (!ptr) { + return 0; + } + + my_jid = jid_create(jabber_get_fulljid()); + + ptr = xmpp_stanza_get_children(ptr); + while (ptr) { + name = xmpp_stanza_get_name(ptr); + if (strcmp(name, STANZA_NAME_CONFERENCE) != 0) { + continue; + } + jid = xmpp_stanza_get_attribute(ptr, STANZA_ATTR_JID); + if (!jid) { + continue; + } + + log_debug("Handle bookmark for %s", jid); + + autojoin = xmpp_stanza_get_attribute(ptr, "autojoin"); + if (autojoin && strcmp(autojoin, "1") == 0) { + name = NULL; + nick = xmpp_stanza_get_child_by_name(ptr, "nick"); + if (nick) { + char *tmp; + tmp = xmpp_stanza_get_text(nick); + if (tmp) { + name = strdup(tmp); + xmpp_free(ctx, tmp); + } + } else { + name = strdup(my_jid->localpart); + } + + if (name) { + /* TODO: autojoin maximum (e.g. 5) rooms */ + log_debug("Autojoin %s with nick=%s", jid, name); + Jid *room_jid = jid_create_from_bare_and_resource(jid, name); + if (!muc_room_is_active(room_jid)) { + presence_join_room(room_jid); + /* XXX: this should be removed after fixing #195 */ + ui_room_join(room_jid); + } + jid_destroy(room_jid); + free(name); + } + } + + /* TODO: add to autocompleter */ + + ptr = xmpp_stanza_get_next(ptr); + } + + jid_destroy(my_jid); + + return 0; +} diff --git a/src/xmpp/bookmark.h b/src/xmpp/bookmark.h new file mode 100644 index 00000000..d4ab8b5b --- /dev/null +++ b/src/xmpp/bookmark.h @@ -0,0 +1,7 @@ + +#ifndef BOOKMARK_H +#define BOOKMARK_H + +void bookmark_request(void); + +#endif diff --git a/src/xmpp/connection.c b/src/xmpp/connection.c index 85ddfa45..600e813a 100644 --- a/src/xmpp/connection.c +++ b/src/xmpp/connection.c @@ -33,6 +33,7 @@ #include "log.h" #include "muc.h" #include "profanity.h" +#include "xmpp/bookmark.h" #include "xmpp/capabilities.h" #include "xmpp/connection.h" #include "xmpp/iq.h" @@ -231,6 +232,19 @@ jabber_set_autoping(const int seconds) } } +int +jabber_get_id(void) +{ + static int xmpp_id; + + ++xmpp_id; + if (xmpp_id < 0) { + xmpp_id = 1; + } + + return xmpp_id; +} + GList * jabber_get_available_resources(void) { @@ -494,6 +508,7 @@ _connection_handler(xmpp_conn_t * const conn, } roster_request(); + bookmark_request(); jabber_conn.conn_status = JABBER_CONNECTED; if (prefs_get_reconnect() != 0) { diff --git a/src/xmpp/connection.h b/src/xmpp/connection.h index b5701252..81a6e3b3 100644 --- a/src/xmpp/connection.h +++ b/src/xmpp/connection.h @@ -31,6 +31,7 @@ xmpp_conn_t *connection_get_conn(void); xmpp_ctx_t *connection_get_ctx(void); int connection_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata); +int jabber_get_id(void); void connection_set_priority(int priority); void connection_set_presence_message(const char * const message); void connection_add_available_resource(Resource *resource); diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c index d2de44f0..e1178ccf 100644 --- a/src/xmpp/stanza.c +++ b/src/xmpp/stanza.c @@ -33,6 +33,63 @@ static int _field_compare(FormField *f1, FormField *f2); +#if 0 +xmpp_stanza_t * +stanza_create_storage_bookmarks(xmpp_ctx_t *ctx) +{ + xmpp_stanza_t *iq, *pubsub, *items; + + /* TODO: check pointers for NULL */ + iq = xmpp_stanza_new(ctx); + pubsub = xmpp_stanza_new(ctx); + items = xmpp_stanza_new(ctx); + + xmpp_stanza_set_name(iq, STANZA_NAME_IQ); + xmpp_stanza_set_type(iq, STANZA_TYPE_GET); + + xmpp_stanza_set_name(pubsub, STANZA_NAME_PUBSUB); + xmpp_stanza_set_ns(pubsub, STANZA_NS_PUBSUB); + + xmpp_stanza_set_name(items, STANZA_NAME_ITEMS); + xmpp_stanza_set_attribute(items, "node", "storage:bookmarks"); + + xmpp_stanza_add_child(pubsub, items); + xmpp_stanza_add_child(iq, pubsub); + xmpp_stanza_release(items); + xmpp_stanza_release(pubsub); + + return iq; +} +#endif + +xmpp_stanza_t * +stanza_create_storage_bookmarks(xmpp_ctx_t *ctx) +{ + xmpp_stanza_t *iq, *query, *storage; + + /* TODO: check pointers for NULL */ + iq = xmpp_stanza_new(ctx); + query = xmpp_stanza_new(ctx); + storage = xmpp_stanza_new(ctx); + + xmpp_stanza_set_name(iq, STANZA_NAME_IQ); + xmpp_stanza_set_type(iq, STANZA_TYPE_GET); + xmpp_stanza_set_ns(iq, "jabber:client"); + + xmpp_stanza_set_name(query, STANZA_NAME_QUERY); + xmpp_stanza_set_ns(query, "jabber:iq:private"); + + xmpp_stanza_set_name(storage, STANZA_NAME_STORAGE); + xmpp_stanza_set_ns(storage, "storage:bookmarks"); + + xmpp_stanza_add_child(query, storage); + xmpp_stanza_add_child(iq, query); + xmpp_stanza_release(storage); + xmpp_stanza_release(query); + + return iq; +} + xmpp_stanza_t * stanza_create_chat_state(xmpp_ctx_t *ctx, const char * const recipient, const char * const state) diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index ad777f24..108b0806 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -52,6 +52,9 @@ #define STANZA_NAME_INVITE "invite" #define STANZA_NAME_REASON "reason" #define STANZA_NAME_GROUP "group" +#define STANZA_NAME_PUBSUB "pubsub" +#define STANZA_NAME_STORAGE "storage" +#define STANZA_NAME_CONFERENCE "conference" #define STANZA_TYPE_CHAT "chat" #define STANZA_TYPE_GROUPCHAT "groupchat" @@ -100,6 +103,7 @@ #define STANZA_NS_VERSION "jabber:iq:version" #define STANZA_NS_CONFERENCE "jabber:x:conference" #define STANZA_NS_CAPTCHA "urn:xmpp:captcha" +#define STANZA_NS_PUBSUB "http://jabber.org/protocol/pubsub" #define STANZA_DATAFORM_SOFTWARE "urn:xmpp:dataforms:softwareinfo" @@ -113,6 +117,8 @@ typedef struct data_form_t { GSList *fields; } DataForm; +xmpp_stanza_t* stanza_create_storage_bookmarks(xmpp_ctx_t *ctx); + xmpp_stanza_t* stanza_create_chat_state(xmpp_ctx_t *ctx, const char * const recipient, const char * const state);