diff options
-rw-r--r-- | examples/weechat.c | 58 | ||||
-rw-r--r-- | src/rexmpp.c | 1 | ||||
-rw-r--r-- | src/rexmpp.h | 2 | ||||
-rw-r--r-- | src/rexmpp_roster.c | 12 |
4 files changed, 73 insertions, 0 deletions
diff --git a/examples/weechat.c b/examples/weechat.c index d247eb3..0c26f6e 100644 --- a/examples/weechat.c +++ b/examples/weechat.c @@ -140,6 +140,7 @@ int my_xml_in_cb (struct weechat_rexmpp *wr, xmlNodePtr node) { buf = weechat_buffer_new (from, &query_input_cb, wr, NULL, &query_close_cb, wr, NULL); + weechat_buffer_set(buf, "nicklist", "1"); } if (resource_removed) { from[i] = '/'; /* restore */ @@ -157,6 +158,39 @@ int my_xml_in_cb (struct weechat_rexmpp *wr, xmlNodePtr node) { xmlFree(from); } } + if (rexmpp_xml_match(node, "jabber:client", "presence")) { + char *presence_type = xmlGetProp(node, "type"); + char *jid = xmlGetProp(node, "from"); + int i; + char *resource = ""; + for (i = 0; i < strlen(jid); i++) { + if (jid[i] == '/') { + jid[i] = 0; + resource = jid + i + 1; + break; + } + } + if (rexmpp_xml_find_child(node, "http://jabber.org/protocol/muc#user", "x")) { + /* Update MUC nicklist */ + struct t_gui_buffer *buf = weechat_buffer_search("rexmpp", jid); + if (buf != NULL) { + if (presence_type != NULL && strcmp(presence_type, "unavailable") == 0) { + struct t_gui_nick *nick = + weechat_nicklist_search_nick(buf, NULL, resource); + if (nick != NULL) { + weechat_nicklist_remove_nick(buf, nick); + } + } else { + weechat_nicklist_add_nick(buf, NULL, resource, + "bar_fg", "", "lightgreen", 1); + } + } + } + free(jid); + if (presence_type != NULL) { + free(presence_type); + } + } free(xml_buf); return 0; } @@ -194,6 +228,7 @@ my_input_cb (const struct weechat_rexmpp *wr, void *data, buf = weechat_buffer_new (jid, &query_input_cb, wr, NULL, &query_close_cb, wr, NULL); + weechat_buffer_set(buf, "nicklist", "1"); } } else if (input_data[0] == 'j' && input_data[1] == ' ') { char *jid = input_data + 2; @@ -219,14 +254,35 @@ my_input_cb (const struct weechat_rexmpp *wr, void *data, buf = weechat_buffer_new (jid, &muc_input_cb, wrm, NULL, &muc_close_cb, wrm, NULL); + weechat_buffer_set(buf, "nicklist", "1"); } } return WEECHAT_RC_OK; } +void my_roster_modify_cb (struct weechat_rexmpp *wr, xmlNodePtr item) { + char *subscription = xmlGetProp(item, "subscription"); + char *jid = xmlGetProp(item, "jid"); + if (subscription != NULL && strcmp(subscription, "remove") == 0) { + /* delete */ + weechat_nicklist_remove_nick(wr->server_buffer, jid); + } else { + /* add or modify */ + weechat_nicklist_add_nick(wr->server_buffer, NULL, jid, + "bar_fg", "", "lightgreen", 1); + } + free(jid); + if (subscription != NULL) { + free(subscription); + } +} + int my_close_cb (struct weechat_rexmpp *wr, void *data, struct t_gui_buffer *buffer) { + /* todo: close MUC buffers first? or at least mark them somehow, so + that they won't attempt to send "unavailable" presence on + closing. */ wr->server_buffer = NULL; rexmpp_stop(&wr->rexmpp_state); return WEECHAT_RC_OK; @@ -331,6 +387,7 @@ command_xmpp_cb (const void *pointer, void *data, wr->server_buffer = weechat_buffer_new (argv[1], &my_input_cb, wr, NULL, &my_close_cb, wr, NULL); + weechat_buffer_set(wr->server_buffer, "nicklist", "1"); wr->password = strdup(argv[2]); wr->hooks = weechat_arraylist_new(42, 0, 0, NULL, NULL, hook_free_cb, NULL); rexmpp_t *s = &wr->rexmpp_state; @@ -339,6 +396,7 @@ command_xmpp_cb (const void *pointer, void *data, s->sasl_property_cb = my_sasl_property_cb; s->xml_in_cb = my_xml_in_cb; s->xml_out_cb = my_xml_out_cb; + s->roster_modify_cb = my_roster_modify_cb; fd_set read_fds, write_fds; FD_ZERO(&read_fds); FD_ZERO(&write_fds); diff --git a/src/rexmpp.c b/src/rexmpp.c index 02dcf5b..c4c1e1c 100644 --- a/src/rexmpp.c +++ b/src/rexmpp.c @@ -268,6 +268,7 @@ rexmpp_err_t rexmpp_init (rexmpp_t *s, const char *jid) s->sasl_property_cb = NULL; s->xml_in_cb = NULL; s->xml_out_cb = NULL; + s->roster_modify_cb = NULL; s->ping_delay = 600; s->ping_requested = 0; s->last_network_activity = 0; diff --git a/src/rexmpp.h b/src/rexmpp.h index 9f748cf..6157f86 100644 --- a/src/rexmpp.h +++ b/src/rexmpp.h @@ -202,6 +202,7 @@ typedef void (*log_function_t) (rexmpp_t *s, int priority, const char *format, v typedef int (*sasl_property_cb_t) (rexmpp_t *s, Gsasl_property prop); typedef int (*xml_in_cb_t) (rexmpp_t *s, xmlNodePtr node); typedef int (*xml_out_cb_t) (rexmpp_t *s, xmlNodePtr node); +typedef void (*roster_modify_cb_t) (rexmpp_t *s, xmlNodePtr item); /** @brief Complete connection state */ struct rexmpp @@ -248,6 +249,7 @@ struct rexmpp sasl_property_cb_t sasl_property_cb; xml_in_cb_t xml_in_cb; xml_out_cb_t xml_out_cb; + roster_modify_cb_t roster_modify_cb; /* Stream-related state. */ char *assigned_jid; diff --git a/src/rexmpp_roster.c b/src/rexmpp_roster.c index 8479c14..3d62613 100644 --- a/src/rexmpp_roster.c +++ b/src/rexmpp_roster.c @@ -81,6 +81,9 @@ rexmpp_err_t rexmpp_modify_roster (rexmpp_t *s, xmlNodePtr item) { if (subscription != NULL) { free(subscription); } + if (s->roster_modify_cb != NULL) { + s->roster_modify_cb(s, item); + } return ret; } @@ -93,6 +96,15 @@ void rexmpp_roster_set (rexmpp_t *s, xmlNodePtr query) { } s->roster_ver = xmlGetProp(query, "ver"); s->roster_items = xmlCopyNodeList(xmlFirstElementChild(query)); + if (s->roster_modify_cb != NULL) { + xmlNodePtr item; + for (item = xmlFirstElementChild(query); + item != NULL; + item = xmlNextElementSibling(item)) + { + s->roster_modify_cb(s, item); + } + } } void rexmpp_roster_cache_read (rexmpp_t *s) { |