From 8bdb022b36c608deacd2a655207709e6ee3bf156 Mon Sep 17 00:00:00 2001 From: defanor Date: Wed, 25 Nov 2020 21:53:18 +0300 Subject: rexmpp_console: handle roster and subscription management --- src/rexmpp_console.c | 186 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 177 insertions(+), 9 deletions(-) diff --git a/src/rexmpp_console.c b/src/rexmpp_console.c index 6b38f65..2c9b19a 100644 --- a/src/rexmpp_console.c +++ b/src/rexmpp_console.c @@ -81,10 +81,30 @@ void rexmpp_console_on_send (rexmpp_t *s, xmlNodePtr node) { } if (rexmpp_xml_match(node, "jabber:client", "presence")) { char *presence_type = xmlGetProp(node, "type"); - rexmpp_console_printf(s, "Becoming %s\n", - (presence_type == NULL) ? - "available" : - presence_type); + char *presence_to = xmlGetProp(node, "to"); + if (presence_to == NULL) { + rexmpp_console_printf(s, "Becoming %s\n", + (presence_type == NULL) ? + "available" : + presence_type); + } else { + if (presence_type != NULL && ! strcmp(presence_type, "subscribe")) { + rexmpp_console_printf(s, + "Requesting a subscription to %s's presence.\n", + presence_to); + } + if (presence_type != NULL && ! strcmp(presence_type, "subscribed")) { + rexmpp_console_printf(s, + "Approving %s's presence subscription request.\n", + presence_to); + } + if (presence_type != NULL && ! strcmp(presence_type, "unsubscribed")) { + rexmpp_console_printf(s, + "Denying %s's presence subscription request.\n", + presence_to); + } + free(presence_to); + } if (presence_type != NULL) { free(presence_type); } @@ -106,10 +126,18 @@ void rexmpp_console_on_recv (rexmpp_t *s, xmlNodePtr node) { if (rexmpp_xml_match(node, "jabber:client", "presence")) { char *presence_type = xmlGetProp(node, "type"); char *from = xmlGetProp(node, "from"); - rexmpp_console_printf(s, "%s is %s\n", from, - (presence_type == NULL) ? - "available" : - presence_type); + if (presence_type != NULL && ! strcmp(presence_type, "subscribe")) { + rexmpp_console_printf(s, "%s requests a presence subscription\n", from); + } else if (presence_type != NULL && ! strcmp(presence_type, "subscribed")) { + rexmpp_console_printf(s, "%s approves a presence subscription\n", from); + } else if (presence_type != NULL && ! strcmp(presence_type, "unsubscribed")) { + rexmpp_console_printf(s, "%s denies a presence subscription\n", from); + } else { + rexmpp_console_printf(s, "%s is %s\n", from, + (presence_type == NULL) ? + "available" : + presence_type); + } if (presence_type != NULL) { free(presence_type); } @@ -119,6 +147,47 @@ void rexmpp_console_on_recv (rexmpp_t *s, xmlNodePtr node) { } } + +void rexmpp_console_roster_deleted (rexmpp_t *s, + xmlNodePtr req, + xmlNodePtr response, + int success) +{ + (void)response; + xmlNodePtr item = + rexmpp_xml_find_child(rexmpp_xml_find_child(req, + "jabber:iq:roster", + "query"), + "jabber:iq:roster", "item"); + char *jid = xmlGetProp(item, "jid"); + if (success) { + rexmpp_console_printf(s, "Deleted %s from the roster.\n", jid); + } else { + rexmpp_console_printf(s, "Failed to delete %s from the roster.\n", jid); + } + free(jid); +} + +void rexmpp_console_roster_added (rexmpp_t *s, + xmlNodePtr req, + xmlNodePtr response, + int success) +{ + (void)response; + xmlNodePtr item = + rexmpp_xml_find_child(rexmpp_xml_find_child(req, + "jabber:iq:roster", + "query"), + "jabber:iq:roster", "item"); + char *jid = xmlGetProp(item, "jid"); + if (success) { + rexmpp_console_printf(s, "Added %s into the roster.\n", jid); + } else { + rexmpp_console_printf(s, "Failed to add %s into the roster.\n", jid); + } + free(jid); +} + void rexmpp_console_on_run (rexmpp_t *s, rexmpp_err_t result) { if (result == REXMPP_SUCCESS) { rexmpp_console_printf(s, "Done.\n"); @@ -130,6 +199,7 @@ void rexmpp_console_feed (rexmpp_t *s, char *str, ssize_t str_len) { /* todo: buffering */ (void)str_len; /* Unused for now (todo). */ char *words_save_ptr; + xmlNodePtr presence; char *word, *jid_str, *msg_text; struct rexmpp_jid jid; word = strtok_r(str, " ", &words_save_ptr); @@ -145,6 +215,12 @@ void rexmpp_console_feed (rexmpp_t *s, char *str, ssize_t str_len) { "signcrypt \n" "publish-key \n" "join [as] \n" + "roster list\n" + "roster add \n" + "roster delete \n" + "subscription request \n" + "subscription approve \n" + "subscription deny \n" ; if (! strcmp(word, "help")) { @@ -221,7 +297,7 @@ void rexmpp_console_feed (rexmpp_t *s, char *str, ssize_t str_len) { char *full_jid = malloc(strlen(jid.bare) + strlen(word) + 2); snprintf(full_jid, strlen(jid_str) + strlen(word) + 2, "%s/%s", jid.bare, word); - xmlNodePtr presence = rexmpp_xml_add_id(s, xmlNewNode(NULL, "presence")); + presence = rexmpp_xml_add_id(s, xmlNewNode(NULL, "presence")); xmlNewProp(presence, "from", s->assigned_jid.full); xmlNewProp(presence, "to", full_jid); xmlNodePtr x = xmlNewNode(NULL, "x"); @@ -229,4 +305,96 @@ void rexmpp_console_feed (rexmpp_t *s, char *str, ssize_t str_len) { xmlAddChild(presence, x); rexmpp_send(s, presence); } + + if (! strcmp(word, "roster")) { + word = strtok_r(NULL, " ", &words_save_ptr); + if (word == NULL) { + return; + } + if (! strcmp(word, "list")) { + xmlNodePtr item; + for (item = s->roster_items; + item != NULL; + item = xmlNextElementSibling(item)) { + char *item_jid = xmlGetProp(item, "jid"); + char *item_ask = xmlGetProp(item, "ask"); + char *item_subscription = xmlGetProp(item, "subscription"); + rexmpp_console_printf(s, "%s: subscription = %s, ask = %s\n", + item_jid, item_subscription, item_ask); + if (item_jid != NULL) { + free(item_jid); + } + if (item_ask != NULL) { + free(item_ask); + } + if (item_subscription != NULL) { + free(item_subscription); + } + } + } else if (! strcmp(word, "delete")) { + word = strtok_r(NULL, " ", &words_save_ptr); + if (word == NULL) { + return; + } + xmlNodePtr delete_item = xmlNewNode(NULL, "item"); + delete_item->ns = xmlNewNs(delete_item, "jabber:iq:roster", NULL); + xmlNewProp(delete_item, "jid", word); + xmlNewProp(delete_item, "subscription", "remove"); + xmlNodePtr delete_query = xmlNewNode(NULL, "query"); + delete_query->ns = xmlNewNs(delete_query, "jabber:iq:roster", NULL); + xmlAddChild(delete_query, delete_item); + rexmpp_iq_new(s, "set", NULL, delete_query, + rexmpp_console_roster_deleted); + } else if (! strcmp(word, "add")) { + word = strtok_r(NULL, " ", &words_save_ptr); + if (word == NULL) { + return; + } + xmlNodePtr delete_item = xmlNewNode(NULL, "item"); + delete_item->ns = xmlNewNs(delete_item, "jabber:iq:roster", NULL); + xmlNewProp(delete_item, "jid", word); + xmlNodePtr delete_query = xmlNewNode(NULL, "query"); + delete_query->ns = xmlNewNs(delete_query, "jabber:iq:roster", NULL); + xmlAddChild(delete_query, delete_item); + rexmpp_iq_new(s, "set", NULL, delete_query, + rexmpp_console_roster_added); + } + } + + if (! strcmp(word, "subscription")) { + word = strtok_r(NULL, " ", &words_save_ptr); + if (word == NULL) { + return; + } + if (! strcmp(word, "request")) { + word = strtok_r(NULL, " ", &words_save_ptr); + if (word == NULL) { + return; + } + presence = xmlNewNode(NULL, "presence"); + xmlNewProp(presence, "to", word); + xmlNewProp(presence, "type", "subscribe"); + rexmpp_send(s, presence); + } + if (! strcmp(word, "approve")) { + word = strtok_r(NULL, " ", &words_save_ptr); + if (word == NULL) { + return; + } + presence = xmlNewNode(NULL, "presence"); + xmlNewProp(presence, "to", word); + xmlNewProp(presence, "type", "subscribed"); + rexmpp_send(s, presence); + } + if (! strcmp(word, "deny")) { + word = strtok_r(NULL, " ", &words_save_ptr); + if (word == NULL) { + return; + } + presence = xmlNewNode(NULL, "presence"); + xmlNewProp(presence, "to", word); + xmlNewProp(presence, "type", "unsubscribed"); + rexmpp_send(s, presence); + } + } } -- cgit v1.2.3