Add /blocked command
This commit is contained in:
323
src/xmpp/blocking.c
Normal file
323
src/xmpp/blocking.c
Normal file
@@ -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;
|
||||
}
|
||||
41
src/xmpp/blocking.h
Normal file
41
src/xmpp/blocking.h
Normal file
@@ -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
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user