Changeset 0d3f30f


Ignore:
Timestamp:
2006-11-12T23:06:08Z (17 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
16b5f86
Parents:
47d3ac4
Message:

Improved handling of JIDs: Bare JIDs are allowed (*sigh*) and case
insensitivity. Probably not complete yet...

Location:
protocols/jabber
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • protocols/jabber/jabber.c

    r47d3ac4 r0d3f30f  
    217217        int st;
    218218       
    219         bud = jabber_buddy_by_jid( gc, who );
     219        bud = jabber_buddy_by_jid( gc, who, 0 );
    220220       
    221221        node = xt_new_node( "body", message, NULL );
    222222        node = jabber_make_packet( "message", "chat", bud ? bud->full_jid : who, node );
    223223       
    224         if( ( jd->flags & JFLAG_WANT_TYPING ) && bud &&
     224        if( bud && ( jd->flags & JFLAG_WANT_TYPING ) &&
    225225            ( ( bud->flags & JBFLAG_DOES_XEP85 ) ||
    226226             !( bud->flags & JBFLAG_PROBED_XEP85 ) ) )
     
    266266       
    267267        if( strchr( who, '/' ) )
    268                 bud = jabber_buddy_by_jid( gc, who );
     268                bud = jabber_buddy_by_jid( gc, who, 0 );
    269269        else
    270                 bud = g_hash_table_lookup( jd->buddies, who );
     270        {
     271                char *s = jabber_normalize( who );
     272                bud = g_hash_table_lookup( jd->buddies, s );
     273                g_free( s );
     274        }
    271275       
    272276        while( bud )
    273277        {
    274                 serv_got_crap( gc, "Buddy %s/%s (%d) information:\nAway state: %s\nAway message: %s",
    275                                    bud->handle, bud->resource, bud->priority,
     278                serv_got_crap( gc, "Buddy %s (%d) information:\nAway state: %s\nAway message: %s",
     279                                   bud->full_jid, bud->priority,
    276280                                   bud->away_state ? bud->away_state->full_name : "(none)",
    277281                                   bud->away_message ? : "(none)" );
     
    279283        }
    280284       
    281         jabber_get_vcard( gc, bud ? bud->handle : who );
     285        jabber_get_vcard( gc, bud ? bud->full_jid : who );
    282286}
    283287
     
    329333        jd->flags |= JFLAG_WANT_TYPING;
    330334       
    331         if( ( bud = jabber_buddy_by_jid( gc, who ) ) == NULL )
     335        if( ( bud = jabber_buddy_by_jid( gc, who, 0 ) ) == NULL )
    332336        {
    333337                /* Sending typing notifications to unknown buddies is
  • protocols/jabber/jabber.h

    r47d3ac4 r0d3f30f  
    5050        JBFLAG_DOES_XEP85 = 2,          /* Set this when the resource seems to support
    5151                                           XEP85 (typing notification shite). */
    52 } jabber_buddy_flag_t;
     52} jabber_buddy_flags_t;
    5353
    5454struct jabber_data
     
    9393struct jabber_buddy
    9494{
    95         char *handle;
     95        char *bare_jid;
    9696        char *full_jid;
    9797        char *resource;
     
    102102       
    103103        time_t last_act;
    104         jabber_buddy_flag_t flags;
     104        jabber_buddy_flags_t flags;
    105105       
    106106        struct jabber_buddy *next;
     
    160160const struct jabber_away_state *jabber_away_state_by_name( char *name );
    161161void jabber_buddy_ask( struct gaim_connection *gc, char *handle );
     162char *jabber_normalize( char *orig );
     163
     164typedef enum
     165{
     166        GET_BUDDY_CREAT = 1,    /* Try to create it, if necessary. */
     167        GET_BUDDY_EXACT = 2,    /* Get an exact message (only makes sense with bare JIDs). */
     168} get_buddy_flags_t;
     169
    162170struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_jid );
    163 struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid );
     171struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid, get_buddy_flags_t flags );
    164172int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid );
    165173int jabber_buddy_remove_bare( struct gaim_connection *gc, char *bare_jid );
  • protocols/jabber/jabber_util.c

    r47d3ac4 r0d3f30f  
    251251}
    252252
     253/* Returns a new string. Don't leak it! */
     254char *jabber_normalize( char *orig )
     255{
     256        int len, i;
     257        char *new;
     258       
     259        len = strlen( orig );
     260        new = g_new( char, len + 1 );
     261        for( i = 0; i < len; i ++ )
     262                new[i] = tolower( orig[i] );
     263       
     264        new[i] = 0;
     265        return new;
     266}
     267
    253268/* Adds a buddy/resource to our list. Returns NULL if full_jid is not really a
    254    FULL jid or if we already have this buddy/resource. */
    255 struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_jid )
     269   FULL jid or if we already have this buddy/resource. XXX: No, great, actually
     270   buddies from transports don't (usually) have resources. So we'll really have
     271   to deal with that properly. Set their ->resource property to NULL. Do *NOT*
     272   allow to mix this stuff, though... */
     273struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_jid_ )
    256274{
    257275        struct jabber_data *jd = gc->proto_data;
    258276        struct jabber_buddy *bud, *new, *bi;
    259         char *s;
    260        
    261         if( !( s = strchr( full_jid, '/' ) ) )
    262                 return NULL;
     277        char *s, *full_jid;
     278       
     279        full_jid = jabber_normalize( full_jid_ );
     280       
     281        if( ( s = strchr( full_jid, '/' ) ) )
     282                *s = 0;
    263283       
    264284        new = g_new0( struct jabber_buddy, 1 );
    265285       
    266         *s = 0;
    267286        if( ( bud = g_hash_table_lookup( jd->buddies, full_jid ) ) )
    268287        {
    269                 new->handle = bud->handle;
     288                /* If this is a transport buddy or whatever, it can't have more
     289                   than one instance, so this is always wrong: */
     290                if( s == NULL || bud->resource == NULL )
     291                {
     292                        if( s ) *s = '/';
     293                        g_free( new );
     294                        g_free( full_jid );
     295                        return NULL;
     296                }
     297               
     298                new->bare_jid = bud->bare_jid;
    270299               
    271300                /* We already have another resource for this buddy, add the
     
    273302                for( bi = bud; bi; bi = bi->next )
    274303                {
    275                         /* Check for dupes. Resource seem to be case sensitive. */
    276                         if( strcmp( bi->resource, s + 1 ) == 0 )
     304                        /* Check for dupes. */
     305                        if( g_strcasecmp( bi->resource, s + 1 ) == 0 )
    277306                        {
    278307                                *s = '/';
    279308                                g_free( new );
     309                                g_free( full_jid );
    280310                                return NULL;
    281311                        }
     
    290320        else
    291321        {
    292                 new->handle = g_strdup( full_jid );
    293                 g_hash_table_insert( jd->buddies, new->handle, new );
    294         }
    295        
    296         *s = '/';
    297         new->full_jid = g_strdup( full_jid );
    298         new->resource = strchr( new->full_jid, '/' ) + 1;
     322                new->bare_jid = g_strdup( full_jid );
     323                g_hash_table_insert( jd->buddies, new->bare_jid, new );
     324        }
     325       
     326        if( s )
     327        {
     328                *s = '/';
     329                new->full_jid = full_jid;
     330                new->resource = strchr( new->full_jid, '/' ) + 1;
     331        }
     332        else
     333        {
     334                /* Let's waste some more bytes of RAM instead of to make
     335                   memory management a total disaster here.. */
     336                new->full_jid = full_jid;
     337        }
    299338       
    300339        return new;
     
    304343   asked for a bare JID, it uses the "resource_select" setting to see which
    305344   resource to pick. */
    306 struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid )
     345struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid_, get_buddy_flags_t flags )
    307346{
    308347        struct jabber_data *jd = gc->proto_data;
    309348        struct jabber_buddy *bud;
    310         char *s;
     349        char *s, *jid;
     350       
     351        jid = jabber_normalize( jid_ );
    311352       
    312353        if( ( s = strchr( jid, '/' ) ) )
     
    314355                *s = 0;
    315356                if( ( bud = g_hash_table_lookup( jd->buddies, jid ) ) )
    316                         for( ; bud; bud = bud->next )
    317                                 if( strcmp( bud->resource, s + 1 ) == 0 )
    318                                         break;
     357                {
     358                        /* Is this one of those no-resource buddies? */
     359                        if( bud->resource == NULL )
     360                        {
     361                                bud = NULL;
     362                        }
     363                        else
     364                        {
     365                                /* See if there's an exact match. */
     366                                for( ; bud; bud = bud->next )
     367                                        if( g_strcasecmp( bud->resource, s + 1 ) == 0 )
     368                                                break;
     369                        }
     370                }
     371               
     372                *s = '/';
     373                if( bud == NULL && ( flags & GET_BUDDY_CREAT ) )
     374                        bud = jabber_buddy_add( gc, jid );
     375               
     376                g_free( jid );
     377                return bud;
    319378        }
    320379        else
     
    323382                char *set;
    324383               
    325                 best_prio = best_time = bud = g_hash_table_lookup( jd->buddies, jid );
     384                bud = g_hash_table_lookup( jd->buddies, jid );
     385               
     386                g_free( jid );
     387               
     388                /* An exact match, or only one option. */
     389                if( bud == NULL )
     390                        return ( flags & GET_BUDDY_CREAT ) ? jabber_buddy_add( gc, jid ) : NULL;
     391                else if( ( bud->resource == NULL || bud->next == NULL ) )
     392                        return bud;
     393               
     394                best_prio = best_time = bud;
    326395                for( ; bud; bud = bud->next )
    327396                {
     
    339408                        return best_prio;
    340409        }
    341        
    342         *s = '/';
    343         return bud;
    344410}
    345411
    346412/* Remove one specific full JID from our list. Use this when a buddy goes
    347    off-line (because (s)he can still be online from a different location. */
    348 int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid )
     413   off-line (because (s)he can still be online from a different location.
     414   XXX: See above, we should accept bare JIDs too... */
     415int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid_ )
    349416{
    350417        struct jabber_data *jd = gc->proto_data;
    351418        struct jabber_buddy *bud, *prev, *bi;
    352         char *s;
    353        
    354         if( !( s = strchr( full_jid, '/' ) ) )
    355                 return 0;
    356        
    357         *s = 0;
     419        char *s, *full_jid;
     420       
     421        full_jid = jabber_normalize( full_jid_ );
     422       
     423        if( ( s = strchr( full_jid, '/' ) ) )
     424                *s = 0;
     425       
    358426        if( ( bud = g_hash_table_lookup( jd->buddies, full_jid ) ) )
    359427        {
     
    361429                   matches), removing it is simple. (And the hash reference
    362430                   should be removed too!) */
    363                 if( bud->next == NULL && strcmp( bud->resource, s + 1 ) == 0 )
    364                 {
    365                         g_hash_table_remove( jd->buddies, bud->handle );
    366                         g_free( bud->handle );
     431                if( bud->next == NULL && ( ( s == NULL || bud->resource == NULL ) || g_strcasecmp( bud->resource, s + 1 ) == 0 ) )
     432                {
     433                        g_hash_table_remove( jd->buddies, bud->bare_jid );
     434                        g_free( bud->bare_jid );
    367435                        g_free( bud->full_jid );
    368436                        g_free( bud->away_message );
    369437                        g_free( bud );
     438                       
     439                        g_free( full_jid );
     440                       
     441                        return 1;
     442                }
     443                else if( s == NULL || bud->resource == NULL )
     444                {
     445                        /* Tried to remove a bare JID while this JID does seem
     446                           to have resources... (Or the opposite.) *sigh* */
     447                        g_free( full_jid );
     448                        return 0;
    370449                }
    371450                else
    372451                {
    373452                        for( bi = bud, prev = NULL; bi; bi = (prev=bi)->next )
    374                                 if( strcmp( bi->resource, s + 1 ) == 0 )
     453                                if( g_strcasecmp( bi->resource, s + 1 ) == 0 )
    375454                                        break;
     455                       
     456                        g_free( full_jid );
    376457                       
    377458                        if( bi )
     
    382463                                        /* The hash table should point at the second
    383464                                           item, because we're removing the first. */
    384                                         g_hash_table_replace( jd->buddies, bi->handle, bi->next );
     465                                        g_hash_table_replace( jd->buddies, bi->bare_jid, bi->next );
    385466                               
    386467                                g_free( bi->full_jid );
    387468                                g_free( bi->away_message );
    388469                                g_free( bi );
     470                               
     471                                return 1;
    389472                        }
    390473                        else
    391474                        {
    392                                 *s = '/';
    393475                                return 0;
    394476                        }
    395477                }
    396                
    397                 *s = '/';
    398                 return 1;
    399         }
    400         else
    401         {
    402                 *s = '/';
     478        }
     479        else
     480        {
     481                g_free( full_jid );
    403482                return 0;
    404483        }
     
    408487   specified bare JID. Use this when removing someone from the contact
    409488   list, for example. */
    410 int jabber_buddy_remove_bare( struct gaim_connection *gc, char *bare_jid )
     489int jabber_buddy_remove_bare( struct gaim_connection *gc, char *bare_jid_ )
    411490{
    412491        struct jabber_data *jd = gc->proto_data;
    413492        struct jabber_buddy *bud, *next;
    414        
    415         if( strchr( bare_jid, '/' ) )
     493        char *bare_jid;
     494       
     495        if( strchr( bare_jid_, '/' ) )
    416496                return 0;
     497       
     498        bare_jid = jabber_normalize( bare_jid_ );
    417499       
    418500        if( ( bud = g_hash_table_lookup( jd->buddies, bare_jid ) ) )
     
    420502                /* Most important: Remove the hash reference. We don't know
    421503                   this buddy anymore. */
    422                 g_hash_table_remove( jd->buddies, bud->handle );
     504                g_hash_table_remove( jd->buddies, bud->bare_jid );
    423505               
    424506                /* Deallocate the linked list of resources. */
     
    432514                }
    433515               
     516                g_free( bare_jid );
    434517                return 1;
    435518        }
    436519        else
    437520        {
     521                g_free( bare_jid );
    438522                return 0;
    439523        }
  • protocols/jabber/message.c

    r47d3ac4 r0d3f30f  
    4747                if( ( s = strchr( from, '/' ) ) )
    4848                {
    49                         if( ( bud = jabber_buddy_by_jid( gc, from ) ) )
     49                        if( ( bud = jabber_buddy_by_jid( gc, from, GET_BUDDY_EXACT ) ) )
    5050                                bud->last_act = time( NULL );
    5151                        else
     
    7676               
    7777                if( fullmsg->len > 0 )
    78                         serv_got_im( gc, bud ? bud->handle : from, fullmsg->str, 0, 0, fullmsg->len );
     78                        serv_got_im( gc, bud ? bud->bare_jid : from, fullmsg->str, 0, 0, fullmsg->len );
    7979               
    8080                g_string_free( fullmsg, TRUE );
     
    8484                {
    8585                        bud->flags |= JBFLAG_DOES_XEP85;
    86                         serv_got_typing( gc, bud ? bud->handle : from, 0, 1 );
     86                        serv_got_typing( gc, bud ? bud->bare_jid : from, 0, 1 );
    8787                }
    8888                /* No need to send a "stopped typing" signal when there's a message. */
     
    9090                {
    9191                        bud->flags |= JBFLAG_DOES_XEP85;
    92                         serv_got_typing( gc, bud ? bud->handle : from, 0, 0 );
     92                        serv_got_typing( gc, bud ? bud->bare_jid : from, 0, 0 );
    9393                }
    9494                else if( xt_find_node( node->children, "paused" ) )
    9595                {
    9696                        bud->flags |= JBFLAG_DOES_XEP85;
    97                         serv_got_typing( gc, bud ? bud->handle : from, 0, 2 );
     97                        serv_got_typing( gc, bud ? bud->bare_jid : from, 0, 2 );
    9898                }
    9999               
  • protocols/jabber/presence.c

    r47d3ac4 r0d3f30f  
    3838        if( type == NULL )
    3939        {
    40                 if( ( s = strchr( from, '/' ) ) == NULL )
     40                if( !( bud = jabber_buddy_by_jid( gc, from, GET_BUDDY_EXACT | GET_BUDDY_CREAT ) ) )
    4141                {
    42                         char *s = xt_to_string( node );
    43                         serv_got_crap( gc, "WARNING: Ignoring presence tag with bare JID: %s", s );
    44                         g_free( s );
     42                        serv_got_crap( gc, "WARNING: Could not handle presence information from JID: %s", from );
    4543                        return XT_HANDLED;
    46                 }
    47                
    48                 if( !( bud = jabber_buddy_by_jid( gc, from ) ) )
    49                 {
    50                         /* FOR NOW, s still contains the location of the /.
    51                            Keep this in mind when changing things here. :-) */
    52                        
    53                         /* We check if the buddy is in the contact list,
    54                            because Jabber servers seem to like to send
    55                            presence information of buddies we removed
    56                            from our list sometimes, for example... */
    57                        
    58                         *s = 0;
    59                         if( find_buddy( gc, from ) == NULL )
    60                         {
    61                                 *s = '/';
    62                                 serv_got_crap( gc, "WARNING: Ignoring presence information from unknown JID: %s", from );
    63                                 return XT_HANDLED;
    64                         }
    65                         *s = '/';
    66                        
    67                         bud = jabber_buddy_add( gc, from );
    6844                }
    6945               
     
    8965                        bud->priority = 0;
    9066               
    91                 serv_got_update( gc, bud->handle, 1, 0, 0, 0,
     67                serv_got_update( gc, bud->bare_jid, 1, 0, 0, 0,
    9268                                 bud->away_state ? UC_UNAVAILABLE : 0, 0 );
    9369        }
    9470        else if( strcmp( type, "unavailable" ) == 0 )
    9571        {
    96                 char *s;
    97                
    98                 if( ( s = strchr( from, '/' ) ) == NULL )
    99                 {
    100                         char *s = xt_to_string( node );
    101                         serv_got_crap( gc, "WARNING: Ignoring presence tag with bare JID: %s\n", s );
    102                         g_free( s );
    103                         return XT_HANDLED;
    104                 }
    105                
    106                 if( jabber_buddy_by_jid( gc, from ) == NULL )
     72                if( jabber_buddy_by_jid( gc, from, GET_BUDDY_EXACT ) == NULL )
    10773                {
    10874                        serv_got_crap( gc, "WARNING: Received presence information from unknown JID: %s", from );
     
    11177               
    11278                jabber_buddy_remove( gc, from );
    113                 *s = 0;
    11479               
    115                 /* Only count this as offline if there's no other resource
    116                    available anymore. */
    117                 if( jabber_buddy_by_jid( gc, from ) == NULL )
     80                if( ( s = strchr( from, '/' ) ) )
     81                {
     82                        *s = 0;
     83               
     84                        /* Only count this as offline if there's no other resource
     85                           available anymore. */
     86                        if( jabber_buddy_by_jid( gc, from, 0 ) == NULL )
     87                                serv_got_update( gc, from, 0, 0, 0, 0, 0, 0 );
     88                       
     89                        *s = '/';
     90                }
     91                else
     92                {
    11893                        serv_got_update( gc, from, 0, 0, 0, 0, 0, 0 );
    119                
    120                 *s = '/';
     94                }
    12195        }
    12296        else if( strcmp( type, "subscribe" ) == 0 )
     
    126100        else if( strcmp( type, "subscribed" ) == 0 )
    127101        {
     102                /* Not sure about this one, actually... */
    128103                serv_got_crap( gc, "%s just accepted your authorization request", from );
    129104        }
Note: See TracChangeset for help on using the changeset viewer.