aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--protocols/jabber/io.c2
-rw-r--r--protocols/jabber/iq.c119
-rw-r--r--protocols/jabber/jabber.c10
-rw-r--r--protocols/jabber/jabber.h8
4 files changed, 131 insertions, 8 deletions
diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c
index 3bc967e0..f62e059a 100644
--- a/protocols/jabber/io.c
+++ b/protocols/jabber/io.c
@@ -334,7 +334,7 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data )
to bind/initialize the session. */
if( jd->flags & JFLAG_AUTHENTICATED && ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 )
{
- if( !jabber_get_roster( gc ) )
+ if( !jabber_get_roster( gc ) || !jabber_get_privacy( gc ) )
return XT_ABORT;
}
diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c
index a7783fcb..0411d4ad 100644
--- a/protocols/jabber/iq.c
+++ b/protocols/jabber/iq.c
@@ -27,7 +27,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data )
{
struct gaim_connection *gc = data;
struct jabber_data *jd = gc->proto_data;
- struct xt_node *query, *reply = NULL, *orig = NULL;
+ struct xt_node *query, *reply = NULL, *orig = NULL, *c;
char *s, *type, *xmlns;
int st;
@@ -108,10 +108,45 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data )
account_online( gc );
}
+ if( strcmp( type, "result" ) == 0 && xmlns && strcmp( xmlns, "jabber:iq:privacy" ) == 0 )
+ {
+ struct xt_node *node;
+
+ /* When receiving a list of lists: */
+ if( ( node = xt_find_node( query->children, "active" ) ) )
+ {
+ if( ( s = xt_find_attr( node, "name" ) ) )
+ {
+ set_t *set;
+
+ g_free( jd->privacy_active );
+ jd->privacy_active = g_strdup( s );
+
+ /* Save it so the user can see it. */
+ if( ( set = set_find( &gc->acc->set, "privacy_list" ) ) )
+ {
+ g_free( set->value );
+ set->value = g_strdup( s );
+ }
+
+ if( !jabber_get_privacy( gc ) )
+ return XT_ABORT;
+ }
+ }
+ /* When receiving an actual list: */
+ else if( ( node = xt_find_node( query->children, "list" ) ) )
+ {
+ xt_free_node( jd->privacy_list );
+ jd->privacy_list = xt_dup( node );
+ }
+ else if( query->children == NULL )
+ {
+ /* What to do here if there is no privacy list defined yet... */
+ }
+ }
else if( strcmp( type, "result" ) == 0 && orig )
{
struct xt_node *c;
-
if( !( jd->flags & JFLAG_AUTHENTICATED ) &&
( c = xt_find_node( orig->children, "query" ) ) &&
( c = xt_find_node( c->children, "username" ) ) &&
@@ -120,7 +155,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data )
/* This happens when we just successfully authenticated
the old (non-SASL) way. */
jd->flags |= JFLAG_AUTHENTICATED;
- if( !jabber_get_roster( gc ) )
+ if( !jabber_get_roster( gc ) || !jabber_get_privacy( gc ) )
return XT_ABORT;
}
/* Tricky: Look for <bind> in the reply, because the server
@@ -144,19 +179,39 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data )
if( ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 )
{
- if( !jabber_get_roster( gc ) )
+ if( !jabber_get_roster( gc ) || !jabber_get_privacy( gc ) )
return XT_ABORT;
}
}
+ else if( ( c = xt_find_node( orig->children, "query" ) ) &&
+ ( c = xt_find_node( c->children, "active" ) ) )
+ {
+ /* We just successfully activated a (different)
+ privacy list. Fetch it now. */
+ g_free( jd->privacy_active );
+ jd->privacy_active = g_strdup( xt_find_attr( c, "name" ) );
+
+ if( !jabber_get_privacy( gc ) )
+ return XT_ABORT;
+ }
}
else if( strcmp( type, "error" ) == 0 )
{
- if( !( jd->flags & JFLAG_AUTHENTICATED ) )
+ if( !( jd->flags & JFLAG_AUTHENTICATED ) &&
+ ( c = xt_find_node( orig->children, "query" ) ) &&
+ ( c = xt_find_node( c->children, "username" ) ) &&
+ c->text_len )
{
hide_login_progress( gc, "Authentication failure" );
signoff( gc );
return XT_ABORT;
}
+ else if( orig &&
+ ( c = xt_find_node( orig->children, "query" ) ) &&
+ ( c = xt_find_node( c->children, "active" ) ) )
+ {
+ serv_got_crap( gc, "Error while activating privacy list, maybe it doesn't exist" );
+ }
}
return XT_HANDLED;
@@ -237,3 +292,57 @@ int jabber_remove_from_roster( struct gaim_connection *gc, char *handle )
xt_free_node( node );
return st;
}
+
+/* Request the privacy list from the server. We need this, because every
+ time we remove/add something we have to send the whole new list to the
+ server again... If no privacy list is specified yet, this function will
+ first ask for the list of lists (XMPP supports multiple "privacy lists",
+ don't ask me why), later we can then fetch the list we want to use. */
+int jabber_get_privacy( struct gaim_connection *gc )
+{
+ struct jabber_data *jd = gc->proto_data;
+ struct xt_node *node = NULL;
+ char *name;
+ int st;
+
+ if( jd->privacy_active )
+ {
+ /* If we know what is the active list right now, fetch it. */
+ node = xt_new_node( "list", NULL, NULL );
+ xt_add_attr( node, "name", jd->privacy_active );
+ }
+ /* Okay, we don't know yet. If the user set a specific list, we'll
+ activate that one. Otherwise, we should figure out which list is
+ currently active. */
+ else if( ( name = set_getstr( &gc->acc->set, "privacy_list" ) ) )
+ {
+ return jabber_set_privacy( gc, name );
+ }
+ /* else: sending this packet without a <list/> element will give
+ a list of available lists and information about the currently
+ active list. */
+
+ node = xt_new_node( "query", NULL, node );
+ xt_add_attr( node, "xmlns", "jabber:iq:privacy" );
+ node = jabber_make_packet( "iq", "get", NULL, node );
+
+ st = jabber_write_packet( gc, node );
+
+ xt_free_node( node );
+ return st;
+}
+
+int jabber_set_privacy( struct gaim_connection *gc, char *name )
+{
+ struct xt_node *node;
+
+ node = xt_new_node( "active", NULL, NULL );
+ xt_add_attr( node, "name", name );
+ node = xt_new_node( "query", NULL, node );
+ xt_add_attr( node, "xmlns", "jabber:iq:privacy" );
+
+ node = jabber_make_packet( "iq", "set", NULL, node );
+ jabber_cache_packet( gc, node );
+
+ return jabber_write_packet( gc, node );
+}
diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c
index df518956..8ec6b70c 100644
--- a/protocols/jabber/jabber.c
+++ b/protocols/jabber/jabber.c
@@ -41,6 +41,9 @@ static void jabber_acc_init( account_t *acc )
s = set_add( &acc->set, "priority", "0", set_eval_priority, acc );
+ s = set_add( &acc->set, "privacy_list", NULL, NULL, acc );
+ /* TODO: Add evaluator. */
+
s = set_add( &acc->set, "resource", "BitlBee", NULL, acc );
s->flags |= ACC_SET_OFFLINE_ONLY;
@@ -80,12 +83,12 @@ static void jabber_login( account_t *acc )
if( set_getbool( &acc->set, "ssl" ) )
{
- jd->ssl = ssl_connect( jd->server, set_getint( &acc->set, "port" ), jabber_connected_ssl, gc );
+ jd->ssl = ssl_connect( acc->server ? acc->server : jd->server, set_getint( &acc->set, "port" ), jabber_connected_ssl, gc );
jd->fd = ssl_getfd( jd->ssl );
}
else
{
- jd->fd = proxy_connect( jd->server, set_getint( &acc->set, "port" ), jabber_connected_plain, gc );
+ jd->fd = proxy_connect( acc->server ? acc->server : jd->server, set_getint( &acc->set, "port" ), jabber_connected_plain, gc );
}
}
@@ -108,6 +111,9 @@ static void jabber_close( struct gaim_connection *gc )
if( jd->tx_len )
g_free( jd->txq );
+ xt_free_node( jd->privacy_list );
+ g_free( jd->privacy_active );
+
xt_free_node( jd->node_cache );
xt_free( jd->xt );
diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h
index 8ca7d545..1ee02d3e 100644
--- a/protocols/jabber/jabber.h
+++ b/protocols/jabber/jabber.h
@@ -59,6 +59,10 @@ struct jabber_data
struct jabber_away_state *away_state;
char *away_message;
+ /* Updates to this one should be synchronized using jabber_privacy_update(). */
+ struct xt_node *privacy_list;
+ char *privacy_active;
+
struct xt_node *node_cache;
};
@@ -68,12 +72,16 @@ struct jabber_away_state
char *full_name;
};
+#define DEFAULT_PRIVACY_LIST "simple_blocklist"
+
/* iq.c */
xt_status jabber_pkt_iq( struct xt_node *node, gpointer data );
int jabber_start_iq_auth( struct gaim_connection *gc );
int jabber_get_roster( struct gaim_connection *gc );
int jabber_add_to_roster( struct gaim_connection *gc, char *handle, char *name );
int jabber_remove_from_roster( struct gaim_connection *gc, char *handle );
+int jabber_get_privacy( struct gaim_connection *gc );
+int jabber_set_privacy( struct gaim_connection *gc, char *name );
/* message.c */
xt_status jabber_pkt_message( struct xt_node *node, gpointer data );