diff options
author | James Booth <boothj5@gmail.com> | 2016-05-01 19:39:39 +0100 |
---|---|---|
committer | James Booth <boothj5@gmail.com> | 2016-05-01 19:39:39 +0100 |
commit | b8c94376aad2d5edf4390e47b8dc89db8ab1a517 (patch) | |
tree | ed498c6b0fed9428e5d0f0cdd28cdd12f82cb447 /src/xmpp | |
parent | c31913f8d582c57dc2d148739e190ddff743cb94 (diff) | |
download | profani-tty-b8c94376aad2d5edf4390e47b8dc89db8ab1a517.tar.gz |
Add /blocked command
Diffstat (limited to 'src/xmpp')
-rw-r--r-- | src/xmpp/blocking.c | 323 | ||||
-rw-r--r-- | src/xmpp/blocking.h | 41 | ||||
-rw-r--r-- | src/xmpp/connection.c | 17 | ||||
-rw-r--r-- | src/xmpp/iq.c | 6 | ||||
-rw-r--r-- | src/xmpp/stanza.c | 20 | ||||
-rw-r--r-- | src/xmpp/stanza.h | 6 | ||||
-rw-r--r-- | src/xmpp/xmpp.h | 9 |
7 files changed, 422 insertions, 0 deletions
diff --git a/src/xmpp/blocking.c b/src/xmpp/blocking.c new file mode 100644 index 00000000..06bbadf6 --- /dev/null +++ b/src/xmpp/blocking.c @@ -0,0 +1,323 @@ +/* + * blocking.c + * + * Copyright (C) 2012 - 2016 James Booth <boothj5@gmail.com> + * + * This file is part of Profanity. + * + * Profanity is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Profanity is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Profanity. If not, see <http://www.gnu.org/licenses/>. + * + * In addition, as a special exception, the copyright holders give permission to + * link the code of portions of this program with the OpenSSL library under + * certain conditions as described in each individual source file, and + * distribute linked combinations including the two. + * + * You must obey the GNU General Public License in all respects for all of the + * code used other than OpenSSL. If you modify file(s) with this exception, you + * may extend this exception to your version of the file(s), but you are not + * obligated to do so. If you do not wish to do so, delete this exception + * statement from your version. If you delete this exception statement from all + * source files in the program, then also delete it here. + * + */ + +#include <stdlib.h> + +#ifdef HAVE_LIBMESODE +#include <mesode.h> +#endif +#ifdef HAVE_LIBSTROPHE +#include <strophe.h> +#endif + +#include <glib.h> + +#include "log.h" +#include "common.h" +#include "ui/ui.h" +#include "xmpp/connection.h" +#include "xmpp/stanza.h" + +static int _blocklist_result_handler(xmpp_stanza_t *const stanza, void *const userdata); +static int _block_add_result_handler(xmpp_stanza_t *const stanza, void *const userdata); +static int _block_remove_result_handler(xmpp_stanza_t *const stanza, void *const userdata); + +static GList *blocked; +static Autocomplete blocked_ac; + +void +blocking_request(void) +{ + char *id = create_unique_id("blocked_list_request"); + xmpp_ctx_t *ctx = connection_get_ctx(); + xmpp_stanza_t *iq; + + if (blocked) { + g_list_free_full(blocked, free); + blocked = NULL; + } + + if (blocked_ac) { + autocomplete_free(blocked_ac); + } + blocked_ac = autocomplete_new(); + + id_handler_add(id, _blocklist_result_handler, id); + + iq = stanza_create_blocked_list_request(ctx); + xmpp_stanza_set_id(iq, id); + send_iq_stanza(iq); + xmpp_stanza_release(iq); + free(id); +} + +GList* +blocked_list(void) +{ + return blocked; +} + +char* +blocked_ac_find(const char *const search_str) +{ + return autocomplete_complete(blocked_ac, search_str, TRUE); +} + +void +blocked_ac_reset(void) +{ + if (blocked_ac) { + autocomplete_reset(blocked_ac); + } +} + +gboolean +blocked_add(char *jid) +{ + GList *found = g_list_find_custom(blocked, jid, (GCompareFunc)g_strcmp0); + if (found) { + return FALSE; + } + + xmpp_ctx_t *ctx = connection_get_ctx(); + + xmpp_stanza_t *iq = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(iq, STANZA_NAME_IQ); + xmpp_stanza_set_type(iq, STANZA_TYPE_SET); + char *id = create_unique_id("block"); + xmpp_stanza_set_id(iq, id); + + xmpp_stanza_t *block = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(block, STANZA_NAME_BLOCK); + xmpp_stanza_set_ns(block, STANZA_NS_BLOCKING); + + xmpp_stanza_t *item = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(item, STANZA_NAME_ITEM); + xmpp_stanza_set_attribute(item, STANZA_ATTR_JID, jid); + + xmpp_stanza_add_child(block, item); + xmpp_stanza_release(item); + + xmpp_stanza_add_child(iq, block); + xmpp_stanza_release(block); + + id_handler_add(id, _block_add_result_handler, strdup(jid)); + + send_iq_stanza(iq); + xmpp_stanza_release(iq); + free(id); + + return TRUE; +} + +gboolean +blocked_remove(char *jid) +{ + GList *found = g_list_find_custom(blocked, jid, (GCompareFunc)g_strcmp0); + if (!found) { + return FALSE; + } + + xmpp_ctx_t *ctx = connection_get_ctx(); + + xmpp_stanza_t *iq = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(iq, STANZA_NAME_IQ); + xmpp_stanza_set_type(iq, STANZA_TYPE_SET); + char *id = create_unique_id("unblock"); + xmpp_stanza_set_id(iq, id); + + xmpp_stanza_t *block = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(block, STANZA_NAME_UNBLOCK); + xmpp_stanza_set_ns(block, STANZA_NS_BLOCKING); + + xmpp_stanza_t *item = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(item, STANZA_NAME_ITEM); + xmpp_stanza_set_attribute(item, STANZA_ATTR_JID, jid); + + xmpp_stanza_add_child(block, item); + xmpp_stanza_release(item); + + xmpp_stanza_add_child(iq, block); + xmpp_stanza_release(block); + + id_handler_add(id, _block_remove_result_handler, strdup(jid)); + + send_iq_stanza(iq); + xmpp_stanza_release(iq); + free(id); + + return TRUE; +} + +int +blocked_set_handler(xmpp_stanza_t *stanza) +{ + xmpp_stanza_t *block = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BLOCK); + if (block) { + xmpp_stanza_t *child = xmpp_stanza_get_children(block); + while (child) { + if (g_strcmp0(xmpp_stanza_get_name(child), STANZA_NAME_ITEM) == 0) { + const char *jid = xmpp_stanza_get_attribute(child, STANZA_ATTR_JID); + if (jid) { + blocked = g_list_append(blocked, strdup(jid)); + autocomplete_add(blocked_ac, jid); + } + + } + + child = xmpp_stanza_get_next(child); + } + } + + xmpp_stanza_t *unblock = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_UNBLOCK); + if (unblock) { + xmpp_stanza_t *child = xmpp_stanza_get_children(unblock); + if (!child) { + g_list_free_full(blocked, free); + blocked = NULL; + autocomplete_clear(blocked_ac); + } else { + while (child) { + if (g_strcmp0(xmpp_stanza_get_name(child), STANZA_NAME_ITEM) == 0) { + const char *jid = xmpp_stanza_get_attribute(child, STANZA_ATTR_JID); + if (jid) { + GList *found = g_list_find_custom(blocked, jid, (GCompareFunc)g_strcmp0); + if (found) { + blocked = g_list_remove_link(blocked, found); + g_list_free_full(found, free); + autocomplete_remove(blocked_ac, jid); + } + } + + } + + child = xmpp_stanza_get_next(child); + } + } + } + + return 1; +} + +static int +_block_add_result_handler(xmpp_stanza_t *const stanza, void *const userdata) +{ + char *jid = (char*)userdata; + + const char *type = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TYPE); + if (type == NULL) { + log_info("Block response received for %s with no type attribute.", jid); + free(jid); + return 0; + } + + if (g_strcmp0(type, "result") != 0) { + log_info("Block response received for %s with unrecognised type attribute.", jid); + free(jid); + return 0; + } + + cons_show("User %s successfully blocked.", jid); + free(jid); + + return 0; +} + +static int +_block_remove_result_handler(xmpp_stanza_t *const stanza, void *const userdata) +{ + char *jid = (char*)userdata; + + const char *type = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TYPE); + if (type == NULL) { + log_info("Unblock response received for %s with no type attribute.", jid); + free(jid); + return 0; + } + + if (g_strcmp0(type, "result") != 0) { + log_info("Unblock response received for %s with unrecognised type attribute.", jid); + free(jid); + return 0; + } + + cons_show("User %s successfully unblocked.", jid); + free(jid); + + return 0; +} + +static int +_blocklist_result_handler(xmpp_stanza_t *const stanza, void *const userdata) +{ + log_info("Blocked list result handler fired."); + + const char *type = xmpp_stanza_get_type(stanza); + if (g_strcmp0(type, "result") != 0) { + log_info("Received blocklist without result type"); + return 0; + } + + xmpp_stanza_t *blocklist = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BLOCKLIST); + if (!blocklist) { + log_info("Received blocklist without blocklist element"); + return 0; + } + + if (blocked) { + g_list_free_full(blocked, free); + blocked = NULL; + } + + xmpp_stanza_t *items = xmpp_stanza_get_children(blocklist); + if (!items) { + log_info("No blocked users."); + return 0; + } + + xmpp_stanza_t *curr = items; + while (curr) { + const char *name = xmpp_stanza_get_name(curr); + if (g_strcmp0(name, "item") == 0) { + const char *jid = xmpp_stanza_get_attribute(curr, STANZA_ATTR_JID); + if (jid) { + blocked = g_list_append(blocked, strdup(jid)); + autocomplete_add(blocked_ac, jid); + } + } + curr = xmpp_stanza_get_next(curr); + } + + return 0; +} diff --git a/src/xmpp/blocking.h b/src/xmpp/blocking.h new file mode 100644 index 00000000..f541cef1 --- /dev/null +++ b/src/xmpp/blocking.h @@ -0,0 +1,41 @@ +/* + * blocking.h + * + * Copyright (C) 2012 - 2016 James Booth <boothj5@gmail.com> + * + * This file is part of Profanity. + * + * Profanity is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Profanity is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Profanity. If not, see <http://www.gnu.org/licenses/>. + * + * In addition, as a special exception, the copyright holders give permission to + * link the code of portions of this program with the OpenSSL library under + * certain conditions as described in each individual source file, and + * distribute linked combinations including the two. + * + * You must obey the GNU General Public License in all respects for all of the + * code used other than OpenSSL. If you modify file(s) with this exception, you + * may extend this exception to your version of the file(s), but you are not + * obligated to do so. If you do not wish to do so, delete this exception + * statement from your version. If you delete this exception statement from all + * source files in the program, then also delete it here. + * + */ + +#ifndef XMPP_BLOCKING_H +#define XMPP_BLOCKING_H + +void blocking_request(void); +int blocked_set_handler(xmpp_stanza_t *stanza); + +#endif diff --git a/src/xmpp/connection.c b/src/xmpp/connection.c index 710e71b2..7db3b2ed 100644 --- a/src/xmpp/connection.c +++ b/src/xmpp/connection.c @@ -55,6 +55,7 @@ #include "profanity.h" #include "event/server_events.h" #include "xmpp/bookmark.h" +#include "xmpp/blocking.h" #include "xmpp/capabilities.h" #include "xmpp/connection.h" #include "xmpp/iq.h" @@ -343,6 +344,21 @@ jabber_get_disco_items(void) return (disco_items); } +gboolean +jabber_service_supports(const char *const feature) +{ + DiscoInfo *disco_info; + while (disco_items) { + disco_info = disco_items->data; + if (g_hash_table_lookup_extended(disco_info->features, feature, NULL, NULL)) { + return TRUE; + } + disco_items = g_slist_next(disco_items); + } + + return FALSE; +} + void jabber_set_disco_items(GSList *_disco_items) { @@ -678,6 +694,7 @@ _connection_handler(xmpp_conn_t *const conn, const xmpp_conn_event_t status, con roster_request(); bookmark_request(); + blocking_request(); // items discovery DiscoInfo *info = malloc(sizeof(struct disco_info_t)); diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index c874a721..cba3d4d3 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -58,6 +58,7 @@ #include "config/preferences.h" #include "event/server_events.h" #include "xmpp/capabilities.h" +#include "xmpp/blocking.h" #include "xmpp/connection.h" #include "xmpp/stanza.h" #include "xmpp/form.h" @@ -170,6 +171,11 @@ _iq_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const us roster_result_handler(stanza); } + xmpp_stanza_t *blocking = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_BLOCKING); + if (blocking && (g_strcmp0(type, STANZA_TYPE_SET) == 0)) { + blocked_set_handler(stanza); + } + const char *id = xmpp_stanza_get_id(stanza); if (id) { ProfIdHandler *handler = g_hash_table_lookup(id_handlers, id); diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c index dc2fb68a..13450e20 100644 --- a/src/xmpp/stanza.c +++ b/src/xmpp/stanza.c @@ -117,6 +117,26 @@ stanza_create_bookmarks_storage_request(xmpp_ctx_t *ctx) return iq; } +xmpp_stanza_t* +stanza_create_blocked_list_request(xmpp_ctx_t *ctx) +{ + xmpp_stanza_t *iq, *blocklist; + + iq = xmpp_stanza_new(ctx); + blocklist = xmpp_stanza_new(ctx); + + xmpp_stanza_set_name(iq, STANZA_NAME_IQ); + xmpp_stanza_set_type(iq, STANZA_TYPE_GET); + + xmpp_stanza_set_name(blocklist, STANZA_NAME_BLOCKLIST); + xmpp_stanza_set_ns(blocklist, STANZA_NS_BLOCKING); + + xmpp_stanza_add_child(iq, blocklist); + xmpp_stanza_release(blocklist); + + return iq; +} + #if 0 xmpp_stanza_t* stanza_create_bookmarks_pubsub_add(xmpp_ctx_t *ctx, const char *const jid, diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index 977e34c5..d557b5c7 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -54,6 +54,9 @@ #define STANZA_NAME_MESSAGE "message" #define STANZA_NAME_BODY "body" +#define STANZA_NAME_BLOCK "block" +#define STANZA_NAME_UNBLOCK "unblock" +#define STANZA_NAME_BLOCKLIST "blocklist" #define STANZA_NAME_PRESENCE "presence" #define STANZA_NAME_PRIORITY "priority" #define STANZA_NAME_X "x" @@ -181,6 +184,7 @@ #define STANZA_NS_ENCRYPTED "jabber:x:encrypted" #define STANZA_NS_HTTP_UPLOAD "urn:xmpp:http:upload" #define STANZA_NS_X_OOB "jabber:x:oob" +#define STANZA_NS_BLOCKING "urn:xmpp:blocking" #define STANZA_DATAFORM_SOFTWARE "urn:xmpp:dataforms:softwareinfo" @@ -205,6 +209,8 @@ typedef enum { xmpp_stanza_t* stanza_create_bookmarks_storage_request(xmpp_ctx_t *ctx); +xmpp_stanza_t* stanza_create_blocked_list_request(xmpp_ctx_t *ctx); + xmpp_stanza_t* stanza_create_http_upload_request(xmpp_ctx_t *ctx, const char *const id, const char *const jid, HTTPUpload *upload); xmpp_stanza_t* stanza_enable_carbons(xmpp_ctx_t *ctx); diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h index d6e6031b..bf7bbbac 100644 --- a/src/xmpp/xmpp.h +++ b/src/xmpp/xmpp.h @@ -54,6 +54,8 @@ #define JABBER_PRIORITY_MIN -128 #define JABBER_PRIORITY_MAX 127 +#define XMPP_FEATURE_BLOCKING "urn:xmpp:blocking" + typedef enum { JABBER_UNDEFINED, JABBER_STARTED, @@ -126,6 +128,7 @@ TLSCertificate* jabber_get_tls_peer_cert(void); #endif gboolean jabber_conn_is_secured(void); gboolean jabber_send_stanza(const char *const stanza); +gboolean jabber_service_supports(const char *const feature); // message functions char* message_send_chat(const char *const barejid, const char *const msg, const char *const oob_url); @@ -206,6 +209,12 @@ void roster_send_remove_from_group(const char *const group, PContact contact); void roster_send_add_new(const char *const barejid, const char *const name); void roster_send_remove(const char *const barejid); +GList* blocked_list(void); +gboolean blocked_add(char *jid); +gboolean blocked_remove(char *jid); +char* blocked_ac_find(const char *const search_str); +void blocked_ac_reset(void); + void form_destroy(DataForm *form); char* form_get_form_type_field(DataForm *form); void form_set_value(DataForm *form, const char *const tag, char *value); |