summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordefanor <defanor@uberspace.net>2020-11-25 21:53:18 +0300
committerdefanor <defanor@uberspace.net>2020-11-25 21:53:18 +0300
commit8bdb022b36c608deacd2a655207709e6ee3bf156 (patch)
tree7b4ddfff066bd377f13379643bd6cfa151d1ba65
parent470fda71e045f4921d93977f354a955af6a1195c (diff)
rexmpp_console: handle roster and subscription management
-rw-r--r--src/rexmpp_console.c186
1 files 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 <jid> <message>\n"
"publish-key <fingerprint>\n"
"join <conference> [as] <nick>\n"
+ "roster list\n"
+ "roster add <jid>\n"
+ "roster delete <jid>\n"
+ "subscription request <jid>\n"
+ "subscription approve <jid>\n"
+ "subscription deny <jid>\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);
+ }
+ }
}