aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;