aboutsummaryrefslogtreecommitdiffstats
path: root/protocols/jabber
diff options
context:
space:
mode:
authorWilmer van der Gaast <wilmer@gaast.net>2006-10-15 22:24:01 +0200
committerWilmer van der Gaast <wilmer@gaast.net>2006-10-15 22:24:01 +0200
commit788a1afa9628aeaf9d69fc53f49131a4330253cf (patch)
treecaecf2ba1287434d3d94be165c12fb24a56a404a /protocols/jabber
parente617b35a6771362164aff194cb6e0b757552c0bd (diff)
Proper cleanup of jabber buddy structures when removing a buddy from the
list, proper checking (and handling) of events related to buddies that aren't "hashed" yet, limit checks on priorityto setting, renamed JEP85 to XEP85, support for more XEP85 states.
Diffstat (limited to 'protocols/jabber')
-rw-r--r--protocols/jabber/jabber.c25
-rw-r--r--protocols/jabber/jabber.h9
-rw-r--r--protocols/jabber/jabber_util.c57
-rw-r--r--protocols/jabber/message.c31
-rw-r--r--protocols/jabber/presence.c28
5 files changed, 122 insertions, 28 deletions
diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c
index 26d7bbab..abc3837b 100644
--- a/protocols/jabber/jabber.c
+++ b/protocols/jabber/jabber.c
@@ -146,23 +146,23 @@ static int jabber_send_im( struct gaim_connection *gc, char *who, char *message,
bud = jabber_buddy_by_jid( gc, who );
node = xt_new_node( "body", message, NULL );
- node = jabber_make_packet( "message", "chat", bud->full_jid, node );
+ node = jabber_make_packet( "message", "chat", bud ? bud->full_jid : who, node );
- if( ( jd->flags & JFLAG_WANT_TYPING ) &&
- ( ( bud->flags & JBFLAG_DOES_JEP85 ) ||
- !( bud->flags & JBFLAG_PROBED_JEP85 ) ) )
+ if( ( jd->flags & JFLAG_WANT_TYPING ) && bud &&
+ ( ( bud->flags & JBFLAG_DOES_XEP85 ) ||
+ !( bud->flags & JBFLAG_PROBED_XEP85 ) ) )
{
struct xt_node *act;
/* If the user likes typing notification and if we don't know
- (and didn't probe before) if this resource supports JEP85,
+ (and didn't probe before) if this resource supports XEP85,
include a probe in this packet now. */
act = xt_new_node( "active", NULL, NULL );
xt_add_attr( act, "xmlns", "http://jabber.org/protocol/chatstates" );
xt_add_child( node, act );
/* Just make sure we do this only once. */
- bud->flags |= JBFLAG_PROBED_JEP85;
+ bud->flags |= JBFLAG_PROBED_XEP85;
}
st = jabber_write_packet( gc, node );
@@ -225,6 +225,9 @@ static void jabber_add_buddy( struct gaim_connection *gc, char *who )
static void jabber_remove_buddy( struct gaim_connection *gc, char *who, char *group )
{
+ /* We should always do this part. Clean up our administration a little bit. */
+ jabber_buddy_remove_bare( gc, who );
+
if( jabber_remove_from_roster( gc, who ) )
presence_send_request( gc, who, "unsubscribe" );
}
@@ -247,8 +250,14 @@ static int jabber_send_typing( struct gaim_connection *gc, char *who, int typing
/* Enable typing notification related code from now. */
jd->flags |= JFLAG_WANT_TYPING;
- bud = jabber_buddy_by_jid( gc, who );
- if( bud->flags & JBFLAG_DOES_JEP85 )
+ if( ( bud = jabber_buddy_by_jid( gc, who ) ) == NULL )
+ {
+ /* Sending typing notifications to unknown buddies is
+ unsupported for now. Shouldn't be a problem, I think. */
+ return 0;
+ }
+
+ if( bud->flags & JBFLAG_DOES_XEP85 )
{
/* We're only allowed to send this stuff if we know the other
side supports it. */
diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h
index e5b85f39..d1d452b4 100644
--- a/protocols/jabber/jabber.h
+++ b/protocols/jabber/jabber.h
@@ -40,15 +40,15 @@ typedef enum
before we continue. */
JFLAG_WAIT_BIND = 16, /* ... for <bind> tag. */
JFLAG_WANT_TYPING = 32, /* Set if we ever sent a typing notification, this
- activates all JEP-85 related code. */
+ activates all XEP-85 related code. */
} jabber_flags_t;
typedef enum
{
- JBFLAG_PROBED_JEP85 = 1, /* Set this when we sent our probe packet to make
+ JBFLAG_PROBED_XEP85 = 1, /* Set this when we sent our probe packet to make
sure it gets sent only once. */
- JBFLAG_DOES_JEP85 = 2, /* Set this when the resource seems to support
- JEP85 (typing notification shite). */
+ JBFLAG_DOES_XEP85 = 2, /* Set this when the resource seems to support
+ XEP85 (typing notification shite). */
} jabber_buddy_flag_t;
struct jabber_data
@@ -137,6 +137,7 @@ void jabber_buddy_ask( struct gaim_connection *gc, char *handle );
struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_jid );
struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid );
int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid );
+int jabber_buddy_remove_bare( struct gaim_connection *gc, char *bare_jid );
extern const struct jabber_away_state jabber_away_state_list[];
diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c
index d9a89951..d5d038cf 100644
--- a/protocols/jabber/jabber_util.c
+++ b/protocols/jabber/jabber_util.c
@@ -28,13 +28,20 @@ static int next_id = 1;
char *set_eval_priority( set_t *set, char *value )
{
account_t *acc = set->data;
- char *ret;
+ int i;
- ret = set_eval_int( set, value );
+ if( sscanf( value, "%d", &i ) == 1 )
+ {
+ /* Priority is a signed 8-bit integer, according to RFC 3921. */
+ if( i < -128 || i > 127 )
+ return NULL;
+ }
+ else
+ return NULL;
/* Only run this stuff if the account is online ATM,
and if the setting seems to be acceptable. */
- if( acc->gc && ret )
+ if( acc->gc )
{
/* Although set_eval functions usually are very nice and
convenient, they have one disadvantage: If I would just
@@ -46,14 +53,14 @@ char *set_eval_priority( set_t *set, char *value )
functions next to evals, or just do this little hack: */
g_free( set->value );
- set->value = g_strdup( ret );
+ set->value = g_strdup( value );
/* (Yes, sorry, I prefer the hack. :-P) */
presence_send_update( acc->gc );
}
- return ret;
+ return value;
}
char *set_eval_tls( set_t *set, char *value )
@@ -282,6 +289,9 @@ struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_ji
return new;
}
+/* Finds a buddy from our structures. Can find both full- and bare JIDs. When
+ asked for a bare JID, it uses the "resource_select" setting to see which
+ resource to pick. */
struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid )
{
struct jabber_data *jd = gc->proto_data;
@@ -322,6 +332,8 @@ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid
return bud;
}
+/* Remove one specific full JID from our list. Use this when a buddy goes
+ off-line (because (s)he can still be online from a different location. */
int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid )
{
struct jabber_data *jd = gc->proto_data;
@@ -380,3 +392,38 @@ int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid )
return 0;
}
}
+
+/* Remove a buddy completely; removes all resources that belong to the
+ specified bare JID. Use this when removing someone from the contact
+ list, for example. */
+int jabber_buddy_remove_bare( struct gaim_connection *gc, char *bare_jid )
+{
+ struct jabber_data *jd = gc->proto_data;
+ struct jabber_buddy *bud, *next;
+
+ if( strchr( bare_jid, '/' ) )
+ return 0;
+
+ if( ( bud = g_hash_table_lookup( jd->buddies, bare_jid ) ) )
+ {
+ /* Most important: Remove the hash reference. We don't know
+ this buddy anymore. */
+ g_hash_table_remove( jd->buddies, bud->handle );
+
+ /* Deallocate the linked list of resources. */
+ while( bud )
+ {
+ next = bud->next;
+ g_free( bud->full_jid );
+ g_free( bud->away_message );
+ g_free( bud );
+ bud = next;
+ }
+
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
diff --git a/protocols/jabber/message.c b/protocols/jabber/message.c
index fea728e3..3ff1da1c 100644
--- a/protocols/jabber/message.c
+++ b/protocols/jabber/message.c
@@ -29,6 +29,7 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data )
char *from = xt_find_attr( node, "from" );
char *type = xt_find_attr( node, "type" );
struct xt_node *body = xt_find_node( node->children, "body" );
+ char *s;
if( !type )
return XT_HANDLED; /* Grmbl... FIXME */
@@ -37,7 +38,7 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data )
{
struct jabber_buddy *bud = NULL;
- if( strchr( from, '/' ) == NULL )
+ if( ( s = strchr( from, '/' ) ) == NULL )
{
/* It just shouldn't happen. */
hide_login_progress( gc, "Received message packet from bare JID" );
@@ -45,21 +46,34 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data )
return XT_ABORT;
}
- bud = jabber_buddy_by_jid( gc, from );
- bud->last_act = time( NULL );
+ if( ( bud = jabber_buddy_by_jid( gc, from ) ) )
+ bud->last_act = time( NULL );
+ else
+ *s = 0; /* We need to generate a bare JID now. */
if( body ) /* Could be just a typing notification. */
- serv_got_im( gc, bud->handle, body->text, 0, 0, 0 );
+ serv_got_im( gc, bud ? bud->handle : from, body->text, 0, 0, 0 );
+ /* Handling of incoming typing notifications. */
if( xt_find_node( node->children, "composing" ) )
{
- bud->flags |= JBFLAG_DOES_JEP85;
- serv_got_typing( gc, bud->handle, 0, 1 );
+ bud->flags |= JBFLAG_DOES_XEP85;
+ serv_got_typing( gc, bud ? bud->handle : from, 0, 1 );
}
- else if( xt_find_node( node->children, "active" ) )
+ /* No need to send a "stopped typing" signal when there's a message. */
+ else if( xt_find_node( node->children, "active" ) && ( body == NULL ) )
{
- bud->flags |= JBFLAG_DOES_JEP85;
+ bud->flags |= JBFLAG_DOES_XEP85;
+ serv_got_typing( gc, bud ? bud->handle : from, 0, 0 );
}
+ else if( xt_find_node( node->children, "paused" ) )
+ {
+ bud->flags |= JBFLAG_DOES_XEP85;
+ serv_got_typing( gc, bud ? bud->handle : from, 0, 2 );
+ }
+
+ if( s )
+ *s = '/'; /* And convert it back to a full JID. */
}
else
{
@@ -69,4 +83,3 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data )
return XT_HANDLED;
}
-
diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c
index b10ce634..ccd22f60 100644
--- a/protocols/jabber/presence.c
+++ b/protocols/jabber/presence.c
@@ -30,22 +30,40 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data )
char *type = xt_find_attr( node, "type" ); /* NULL should mean the person is online. */
struct xt_node *c;
struct jabber_buddy *bud;
+ char *s;
if( !from )
return XT_HANDLED;
if( type == NULL )
{
- if( strchr( from, '/' ) == NULL )
+ if( ( s = strchr( from, '/' ) ) == NULL )
{
char *s = xt_to_string( node );
- serv_got_crap( gc, "WARNING: Ignoring presence tag with bare JID: %s\n", s );
+ serv_got_crap( gc, "WARNING: Ignoring presence tag with bare JID: %s", s );
g_free( s );
return XT_HANDLED;
}
if( !( bud = jabber_buddy_by_jid( gc, from ) ) )
{
+ /* FOR NOW, s still contains the location of the /.
+ Keep this in mind when changing things here. :-) */
+
+ /* We check if the buddy is in the contact list,
+ because Jabber servers seem to like to send
+ presence information of buddies we removed
+ from our list sometimes, for example... */
+
+ *s = 0;
+ if( find_buddy( gc, from ) == NULL )
+ {
+ *s = '/';
+ serv_got_crap( gc, "WARNING: Ignoring presence information from unknown JID: %s", from );
+ return XT_HANDLED;
+ }
+ *s = '/';
+
bud = jabber_buddy_add( gc, from );
}
@@ -85,6 +103,12 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data )
return XT_HANDLED;
}
+ if( jabber_buddy_by_jid( gc, from ) == NULL )
+ {
+ serv_got_crap( gc, "WARNING: Received presence information from unknown JID: %s", from );
+ return XT_HANDLED;
+ }
+
jabber_buddy_remove( gc, from );
*s = 0;