Ignore:
Timestamp:
2006-10-08T18:41:11Z (16 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
6a1128d
Parents:
038d17f
Message:

Moved handling of all IQ packets to event handlers. Cleaned up a LOT of
mess in iq.c!

File:
1 edited

Legend:

Unmodified
Added
Removed
  • protocols/jabber/iq.c

    r038d17f r861c199  
    2828        struct gaim_connection *gc = data;
    2929        struct jabber_data *jd = gc->proto_data;
    30         struct xt_node *query, *reply = NULL, *orig = NULL, *c;
    31         char *s, *type, *xmlns;
    32         int st;
    33        
    34         query = xt_find_node( node->children, "query" );
     30        char *type, *s;
     31       
    3532        type = xt_find_attr( node, "type" );
    3633       
    3734        if( !type )
    38                 return XT_HANDLED;      /* Ignore it for now, don't know what's best... */
    39        
    40         xmlns = xt_find_attr( query, "xmlns" );
    41        
    42         if( ( s = xt_find_attr( node, "id" ) ) )
    43                 orig = jabber_cache_get( gc, s );
    44        
    45         if( strcmp( type, "result" ) == 0 && xmlns && strcmp( xmlns, "jabber:iq:auth" ) == 0 )
    46         {
    47                 /* Time to authenticate ourselves! */
    48                 reply = xt_new_node( "query", NULL, NULL );
    49                 xt_add_attr( reply, "xmlns", "jabber:iq:auth" );
    50                 xt_add_child( reply, xt_new_node( "username", jd->username, NULL ) );
    51                 xt_add_child( reply, xt_new_node( "resource", set_getstr( &gc->acc->set, "resource" ), NULL ) );
    52                
    53                 if( xt_find_node( query->children, "digest" ) && ( s = xt_find_attr( jd->xt->root, "id" ) ) )
    54                 {
    55                         /* We can do digest authentication, it seems, and of
    56                            course we prefer that. */
    57                         SHA_CTX sha;
    58                         char hash_hex[40];
    59                         unsigned char hash[20];
    60                         int i;
    61                        
    62                         shaInit( &sha );
    63                         shaUpdate( &sha, (unsigned char*) s, strlen( s ) );
    64                         shaUpdate( &sha, (unsigned char*) gc->acc->pass, strlen( gc->acc->pass ) );
    65                         shaFinal( &sha, hash );
    66                        
    67                         for( i = 0; i < 20; i ++ )
    68                                 sprintf( hash_hex + i * 2, "%02x", hash[i] );
    69                        
    70                         xt_add_child( reply, xt_new_node( "digest", hash_hex, NULL ) );
    71                 }
    72                 else if( xt_find_node( query->children, "password" ) )
    73                 {
    74                         /* We'll have to stick with plaintext. Let's hope we're using SSL/TLS... */
    75                         xt_add_child( reply, xt_new_node( "password", gc->acc->pass, NULL ) );
    76                 }
    77                 else
    78                 {
    79                         xt_free_node( reply );
    80                        
    81                         hide_login_progress( gc, "Can't find suitable authentication method" );
    82                         signoff( gc );
    83                         return XT_ABORT;
    84                 }
    85                
    86                 reply = jabber_make_packet( "iq", "set", NULL, reply );
    87                 jabber_cache_add( gc, reply );
    88                 st = jabber_write_packet( gc, reply );
    89                
    90                 return st ? XT_HANDLED : XT_ABORT;
    91         }
    92         if( strcmp( type, "result" ) == 0 && xmlns && strcmp( xmlns, "jabber:iq:roster" ) == 0 )
    93         {
    94                 struct xt_node *node;
    95                
    96                 node = query->children;
    97                 while( ( node = xt_find_node( node, "item" ) ) )
    98                 {
    99                         char *jid = xt_find_attr( node, "jid" );
    100                         char *name = xt_find_attr( node, "name" );
    101                         char *sub = xt_find_attr( node, "subscription" );
    102                        
    103                         if( jid && sub && ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) )
    104                                 add_buddy( gc, NULL, jid, name );
    105                        
    106                         node = node->next;
    107                 }
    108                
    109                 account_online( gc );
    110         }
    111         else if( strcmp( type, "result" ) == 0 && orig )
    112         {
    113                 struct xt_node *c;
    114                
    115                 if( !( jd->flags & JFLAG_AUTHENTICATED ) &&
    116                     ( c = xt_find_node( orig->children, "query" ) ) &&
    117                     ( c = xt_find_node( c->children, "username" ) ) &&
    118                     c->text_len )
    119                 {
    120                         /* This happens when we just successfully authenticated
    121                            the old (non-SASL) way. */
    122                         jd->flags |= JFLAG_AUTHENTICATED;
    123                         if( !jabber_get_roster( gc ) )
    124                                 return XT_ABORT;
    125                 }
    126                 /* Tricky: Look for <bind> in the reply, because the server
    127                    should confirm the chosen resource string there. For
    128                    <session>, however, look in the cache, because the server
    129                    will probably not include it in its reply. */
    130                 else if( ( c = xt_find_node( node->children, "bind" ) ) ||
    131                          ( c = xt_find_node( orig->children, "session" ) ) )
    132                 {
    133                         if( strcmp( c->name, "bind" ) == 0 )
    134                         {
    135                                 c = xt_find_node( c->children, "jid" );
    136                                 if( c && c->text_len && ( s = strchr( c->text, '/' ) ) &&
    137                                     strcmp( s + 1, set_getstr( &gc->acc->set, "resource" ) ) != 0 )
    138                                         serv_got_crap( gc, "Server changed session resource string to `%s'", s + 1 );
    139                                
    140                                 jd->flags &= ~JFLAG_WAIT_BIND;
    141                         }
    142                         else if( strcmp( c->name, "session" ) == 0 )
    143                                 jd->flags &= ~JFLAG_WAIT_SESSION;
    144                        
    145                         if( ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 )
    146                         {
    147                                 if( !jabber_get_roster( gc ) )
    148                                         return XT_ABORT;
    149                         }
    150                 }
    151         }
    152         else if( strcmp( type, "error" ) == 0 )
    153         {
    154                 if( !( jd->flags & JFLAG_AUTHENTICATED ) &&
    155                       orig &&
    156                     ( c = xt_find_node( orig->children, "query" ) ) &&
    157                     ( c = xt_find_node( c->children, "username" ) ) &&
    158                     c->text_len )
    159                 {
    160                         hide_login_progress( gc, "Authentication failure" );
    161                         signoff( gc );
    162                         return XT_ABORT;
    163                 }
    164         }
    165        
    166         return XT_HANDLED;
    167 }
    168 
    169 int jabber_start_iq_auth( struct gaim_connection *gc )
     35        {
     36                hide_login_progress_error( gc, "Received IQ packet without type!" );
     37                signoff( gc );
     38                return XT_ABORT;
     39        }
     40       
     41        if( ( s = xt_find_attr( node, "id" ) ) &&
     42            ( strcmp( type, "result" ) == 0 || strcmp( type, "error" ) == 0 ) )
     43        {
     44                struct jabber_cache_entry *entry;
     45               
     46                entry = g_hash_table_lookup( jd->node_cache, s );
     47               
     48                if( entry == NULL )
     49                        serv_got_crap( gc, "WARNING: Received IQ %s packet with unknown/expired ID %s!", type, s );
     50                else if( entry->func )
     51                        return entry->func( gc, node, entry->node );
     52        }
     53       
     54        return XT_HANDLED;
     55}
     56
     57static xt_status jabber_do_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig );
     58static xt_status jabber_finish_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig );
     59
     60int jabber_init_iq_auth( struct gaim_connection *gc )
    17061{
    17162        struct jabber_data *jd = gc->proto_data;
     
    17768        node = jabber_make_packet( "iq", "get", NULL, node );
    17869       
    179         st = jabber_write_packet( gc, node );
    180        
    181         xt_free_node( node );
    182         return st;
    183 }
     70        jabber_cache_add( gc, node, jabber_do_iq_auth );
     71        st = jabber_write_packet( gc, node );
     72       
     73        return st;
     74}
     75
     76static xt_status jabber_do_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig )
     77{
     78        struct jabber_data *jd = gc->proto_data;
     79        struct xt_node *reply, *query;
     80        xt_status st;
     81        char *s;
     82       
     83        query = xt_find_node( node->children, "query" );
     84       
     85        /* Time to authenticate ourselves! */
     86        reply = xt_new_node( "query", NULL, NULL );
     87        xt_add_attr( reply, "xmlns", "jabber:iq:auth" );
     88        xt_add_child( reply, xt_new_node( "username", jd->username, NULL ) );
     89        xt_add_child( reply, xt_new_node( "resource", set_getstr( &gc->acc->set, "resource" ), NULL ) );
     90       
     91        if( xt_find_node( query->children, "digest" ) && ( s = xt_find_attr( jd->xt->root, "id" ) ) )
     92        {
     93                /* We can do digest authentication, it seems, and of
     94                   course we prefer that. */
     95                SHA_CTX sha;
     96                char hash_hex[40];
     97                unsigned char hash[20];
     98                int i;
     99               
     100                shaInit( &sha );
     101                shaUpdate( &sha, (unsigned char*) s, strlen( s ) );
     102                shaUpdate( &sha, (unsigned char*) gc->acc->pass, strlen( gc->acc->pass ) );
     103                shaFinal( &sha, hash );
     104               
     105                for( i = 0; i < 20; i ++ )
     106                        sprintf( hash_hex + i * 2, "%02x", hash[i] );
     107               
     108                xt_add_child( reply, xt_new_node( "digest", hash_hex, NULL ) );
     109        }
     110        else if( xt_find_node( query->children, "password" ) )
     111        {
     112                /* We'll have to stick with plaintext. Let's hope we're using SSL/TLS... */
     113                xt_add_child( reply, xt_new_node( "password", gc->acc->pass, NULL ) );
     114        }
     115        else
     116        {
     117                xt_free_node( reply );
     118               
     119                hide_login_progress( gc, "Can't find suitable authentication method" );
     120                signoff( gc );
     121                return XT_ABORT;
     122        }
     123       
     124        reply = jabber_make_packet( "iq", "set", NULL, reply );
     125        jabber_cache_add( gc, reply, jabber_finish_iq_auth );
     126        st = jabber_write_packet( gc, reply );
     127       
     128        return st ? XT_HANDLED : XT_ABORT;
     129}
     130
     131static xt_status jabber_finish_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig )
     132{
     133        char *type = xt_find_attr( node, "type" );
     134        struct jabber_data *jd = gc->proto_data;
     135       
     136        if( strcmp( type, "error" ) == 0 )
     137        {
     138                hide_login_progress( gc, "Authentication failure" );
     139                signoff( gc );
     140                return XT_ABORT;
     141        }
     142        else if( strcmp( type, "result" ) == 0 )
     143        {
     144                /* This happens when we just successfully authenticated the
     145                   old (non-SASL) way. */
     146                jd->flags |= JFLAG_AUTHENTICATED;
     147                if( !jabber_get_roster( gc ) )
     148                        return XT_ABORT;
     149        }
     150       
     151        return XT_HANDLED;
     152}
     153
     154xt_status jabber_pkt_bind_sess( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig )
     155{
     156        struct jabber_data *jd = gc->proto_data;
     157        struct xt_node *c;
     158        char *s;
     159       
     160        if( ( c = xt_find_node( node->children, "bind" ) ) )
     161        {
     162                c = xt_find_node( c->children, "jid" );
     163                if( c && c->text_len && ( s = strchr( c->text, '/' ) ) &&
     164                    strcmp( s + 1, set_getstr( &gc->acc->set, "resource" ) ) != 0 )
     165                        serv_got_crap( gc, "Server changed session resource string to `%s'", s + 1 );
     166               
     167                jd->flags &= ~JFLAG_WAIT_BIND;
     168        }
     169        else
     170        {
     171                jd->flags &= ~JFLAG_WAIT_SESSION;
     172        }
     173       
     174        if( ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 )
     175        {
     176                if( !jabber_get_roster( gc ) )
     177                        return XT_ABORT;
     178        }
     179       
     180        return XT_HANDLED;
     181}
     182
     183static xt_status jabber_parse_roster( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig );
    184184
    185185int jabber_get_roster( struct gaim_connection *gc )
     
    194194        node = jabber_make_packet( "iq", "get", NULL, node );
    195195       
    196         st = jabber_write_packet( gc, node );
    197        
    198         xt_free_node( node );
    199         return st;
     196        jabber_cache_add( gc, node, jabber_parse_roster );
     197        st = jabber_write_packet( gc, node );
     198       
     199        return st;
     200}
     201
     202static xt_status jabber_parse_roster( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig )
     203{
     204        struct xt_node *query, *c;
     205       
     206        query = xt_find_node( node->children, "query" );
     207       
     208        c = query->children;
     209        while( ( c = xt_find_node( c, "item" ) ) )
     210        {
     211                char *jid = xt_find_attr( c, "jid" );
     212                char *name = xt_find_attr( c, "name" );
     213                char *sub = xt_find_attr( c, "subscription" );
     214               
     215                if( jid && sub && ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) )
     216                        add_buddy( gc, NULL, jid, name );
     217               
     218                c = c->next;
     219        }
     220       
     221        account_online( gc );
     222       
     223        return XT_HANDLED;
    200224}
    201225
Note: See TracChangeset for help on using the changeset viewer.