diff options
-rw-r--r-- | protocols/jabber/jabber.c | 25 | ||||
-rw-r--r-- | protocols/jabber/jabber.h | 9 | ||||
-rw-r--r-- | protocols/jabber/jabber_util.c | 57 | ||||
-rw-r--r-- | protocols/jabber/message.c | 31 | ||||
-rw-r--r-- | protocols/jabber/presence.c | 28 |
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; |