Changeset 1ba7e8f for protocols/jabber


Ignore:
Timestamp:
2008-02-15T17:38:57Z (17 years ago)
Author:
ulim <a.sporto+bee@…>
Branches:
master
Children:
506e61b
Parents:
0fbd3a6d (diff), eeb85a8 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merged with upstream r328

Wilmer van der Gaast 2008-02-11 Got rid of some noise at startup: complaining when the default configuration

Wilmer van der Gaast 2008-02-10 Added support for password-protected Jabber chatrooms.
Wilmer van der Gaast 2008-02-10 Making AI_ADDRCONFIG optional, it doesn't exist on at least NetBSD and
Wilmer van der Gaast 2008-02-09 Restored "add -tmp". A bit hackish, but it will do for now.
Wilmer van der Gaast 2008-02-07 Fixed getnameinfo() calls, this fixes Solaris stability issues. Thanks to
Wilmer van der Gaast 2008-02-04 Added bogus G_GNUC_MALLOC to restore GLib 2.4 compatibility (hopefully).
Wilmer van der Gaast 2008-02-03 Messages from the user are also included in backlogs when joining a Jabber
Wilmer van der Gaast 2008-02-03 Disabling "Unknown command" warnings since they're very noisy and pretty
Wilmer van der Gaast 2008-02-03 Implemented XEP-0115. This adds some info to the <presence/> tags so
Wilmer van der Gaast 2008-02-03 Saner garbage collection of cached packets in the Jabber module. Now
Wilmer van der Gaast 2008-02-02 Added help_free() and cleaned up some very stale help-related stuff I
Wilmer van der Gaast 2008-01-30 Fixed handling of OSCAR multi-part messages... They're not arrays, they're
Wilmer van der Gaast 2008-01-24 Keeping track of valid Jabber connections so _connected() events will be
Wilmer van der Gaast 2008-01-24 Fixed two valgrind warnings (partially uninitialized "struct tm" vars.)
Wilmer van der Gaast 2008-01-20 The Jabber module now uses imcb_chat_log() instead of imcb_log() where
Wilmer van der Gaast 2008-01-20 Added imcb_chat_log() for chatroom system messages, so they can be
Wilmer van der Gaast 2008-01-20 GET_BUDDY_FIRST wasn't actually implemented, even though it was in use
Wilmer van der Gaast 2008-01-19 Using test -f instead of test -e. This breaks if the include files are
Wilmer van der Gaast 2008-01-19 Added byte swapping code to the new MD5 checksumming code to make it work
Wilmer van der Gaast 2008-01-18 Moving imcb_chat_new() to a saner location (no code changes) and fixing
Wilmer van der Gaast 2008-01-17 Apparently ext_yahoo_got_im can be called with msg=NULL, so it should be
Wilmer van der Gaast 2008-01-17 Fixing some Solaris compiler warnings (u_int->uint, adding some typecasts
Wilmer van der Gaast 2008-01-13 Fixed handing of failed groupchat joins.
Wilmer van der Gaast 2008-01-13 Fixed "Conditional jump or move depends on uninitialised value(s)" at
Wilmer van der Gaast 2008-01-13 Fixed quickstart2. (Bug #349.)
Wilmer van der Gaast 2008-01-13 Different handling of charset mismatches before login time. Ignoring a
Wilmer van der Gaast 2008-01-12 When a switchboard connection dies (at the TCP level) and there are still
Wilmer van der Gaast 2008-01-12 Killed info_string_append() and now showing the IP address of ICQ users
Wilmer van der Gaast 2008-01-11 Fixing bug #344, now away states should always be correct, even when people
Wilmer van der Gaast 2008-01-11 Adding own handle to protocol name in blist output for people with multiple
Wilmer van der Gaast 2008-01-10 Now setting odata->icq properly again, this got lost some time ago, which
Wilmer van der Gaast 2008-01-06 More consistency in error/warning errors. Until now "WARNING:" was usually
Wilmer van der Gaast 2008-01-06 Changed warning message about unsent MSN messages. It should show the actual
Wilmer van der Gaast 2008-01-05 Added "mail_notifications" setting. Who needs those notifications anyway?
Wilmer van der Gaast 2008-01-05 Build fix from vmiklos.
Wilmer van der Gaast 2008-01-05 Added handling of MSN switchboard NAK messages. Untested, but hey, it
Wilmer van der Gaast 2008-01-05 Removed closure->result. I was planning to add some more stuff, but will
Miklos Vajna 2007-12-31 encode: md5.c is no longer in protocols/, it's in lib/
Wilmer van der Gaast 2007-12-28 Fixed return value check in proxy_connect(), since on some systems
Wilmer van der Gaast 2007-12-28 Added missing return in jabber_login().
Wilmer van der Gaast 2007-12-16 Implemented XEP-0199 (patch from misc@…).
Wilmer van der Gaast 2007-12-12 Checking conn->xcred before trying to clean it up since GnuTLS doesn't
Wilmer van der Gaast 2007-12-12 Killed the <server> parameter to "account add" and changed the default
Wilmer van der Gaast 2007-12-12 Fixed sockerr_again() usage in Jabber module to (hopefully) fix a 100% CPU
Wilmer van der Gaast 2007-12-10 Don't allow nicks that start with a number.
Wilmer van der Gaast 2007-12-10 Fixed "set xxx" syntax (it showed all settings instead of just xxx).
Wilmer van der Gaast 2007-12-09 If I keep forgetting to credit people in commit msgs I should probably add
Wilmer van der Gaast 2007-12-09 Added /invite support for Jabber chatrooms (and fixed the argument order

Location:
protocols/jabber
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • protocols/jabber/conference.c

    r0fbd3a6d r1ba7e8f  
    3737        xt_add_attr( node, "xmlns", XMLNS_MUC );
    3838        node = jabber_make_packet( "presence", NULL, roomjid, node );
     39        if( password )
     40                xt_add_child( node, xt_new_node( "password", password, NULL ) );
    3941        jabber_cache_add( ic, node, jabber_chat_join_failed );
    4042       
     
    7375       
    7476        room = xt_find_attr( orig, "to" );
    75         if( ( bud = jabber_buddy_by_jid( ic, room, 0 ) ) )
    76                 jabber_chat_free( jabber_chat_by_jid( ic, bud->bare_jid ) );
    77        
     77        bud = jabber_buddy_by_jid( ic, room, 0 );
    7878        err = jabber_error_parse( xt_find_node( node->children, "error" ), XMLNS_STANZA_ERROR );
    7979        if( err )
    8080        {
    81                 imcb_error( ic, "Error joining groupchat %s: %s%s%s",
    82                             bud->bare_jid, err->code, err->text ? ": " : "",
    83                             err->text ? err->text : "" );
     81                imcb_error( ic, "Error joining groupchat %s: %s%s%s", room, err->code,
     82                            err->text ? ": " : "", err->text ? err->text : "" );
    8483                jabber_error_free( err );
    8584        }
     85        if( bud )
     86                jabber_chat_free( jabber_chat_by_jid( ic, bud->bare_jid ) );
    8687       
    8788        return XT_HANDLED;
     
    123124        struct jabber_chat *jc = c->data;
    124125        struct xt_node *node;
     126       
     127        jc->flags |= JCFLAG_MESSAGE_SENT;
    125128       
    126129        node = xt_new_node( "body", message, NULL );
     
    296299        struct xt_node *subject = xt_find_node( node->children, "subject" );
    297300        struct xt_node *body = xt_find_node( node->children, "body" );
    298         struct groupchat *chat;
     301        struct groupchat *chat = bud ? jabber_chat_by_jid( ic, bud->bare_jid ) : NULL;
     302        struct jabber_chat *jc = chat ? chat->data : NULL;
    299303        char *s;
    300304       
    301         if( bud == NULL )
    302         {
     305        if( bud == NULL || ( jc && ~jc->flags & JCFLAG_MESSAGE_SENT && bud == jc->me ) )
     306        {
     307                char *nick;
     308               
     309                if( body == NULL || body->text_len == 0 )
     310                        /* Meh. Empty messages aren't very interesting, no matter
     311                           how much some servers love to send them. */
     312                        return;
     313               
    303314                s = xt_find_attr( node, "from" ); /* pkt_message() already NULL-checked this one. */
    304                 if( strchr( s, '/' ) == NULL )
     315                nick = strchr( s, '/' );
     316                if( nick )
     317                {
     318                        /* If this message included a resource/nick we don't know,
     319                           we might still know the groupchat itself. */
     320                        *nick = 0;
     321                        chat = jabber_chat_by_jid( ic, s );
     322                        *nick = '/';
     323                       
     324                        nick ++;
     325                }
     326                else
     327                {
     328                        /* message.c uses the EXACT_JID option, so bud should
     329                           always be NULL here for bare JIDs. */
     330                        chat = jabber_chat_by_jid( ic, s );
     331                }
     332               
     333                if( nick == NULL )
     334                {
    305335                        /* This is fine, the groupchat itself isn't in jd->buddies. */
    306                         imcb_log( ic, "System message from groupchat %s: %s", s, body? body->text : "NULL" );
     336                        if( chat )
     337                                imcb_chat_log( chat, "From conference server: %s", body->text );
     338                        else
     339                                imcb_log( ic, "System message from unknown groupchat %s: %s", s, body->text );
     340                }
    307341                else
    308                         /* This, however, isn't fine! */
    309                         imcb_log( ic, "Groupchat message from unknown participant %s: %s", s, body ? body->text : "NULL" );
     342                {
     343                        /* This can happen too, at least when receiving a backlog when
     344                           just joining a channel. */
     345                        if( chat )
     346                                imcb_chat_log( chat, "Message from unknown participant %s: %s", nick, body->text );
     347                        else
     348                                imcb_log( ic, "Groupchat message from unknown JID %s: %s", s, body->text );
     349                }
    310350               
    311351                return;
    312352        }
    313         else if( ( chat = jabber_chat_by_jid( ic, bud->bare_jid ) ) == NULL )
     353        else if( chat == NULL )
    314354        {
    315355                /* How could this happen?? We could do kill( self, 11 )
  • protocols/jabber/io.c

    r0fbd3a6d r1ba7e8f  
    249249        struct im_connection *ic = data;
    250250       
     251        if( g_slist_find( jabber_connections, ic ) == NULL )
     252                return FALSE;
     253       
    251254        if( source == -1 )
    252255        {
     
    264267{
    265268        struct im_connection *ic = data;
    266         struct jabber_data *jd = ic->proto_data;
     269        struct jabber_data *jd;
     270       
     271        if( g_slist_find( jabber_connections, ic ) == NULL )
     272                return FALSE;
     273       
     274        jd = ic->proto_data;
    267275       
    268276        if( source == NULL )
  • protocols/jabber/iq.c

    r0fbd3a6d r1ba7e8f  
    5454                    !( s = xt_find_attr( c, "xmlns" ) ) )
    5555                {
    56                         imcb_log( ic, "WARNING: Received incomplete IQ-%s packet", type );
     56                        imcb_log( ic, "Warning: Received incomplete IQ-%s packet", type );
    5757                        return XT_HANDLED;
    5858                }
     
    9292                else if( strcmp( s, XMLNS_DISCO_INFO ) == 0 )
    9393                {
    94                         const char *features[] = { XMLNS_VERSION,
     94                        const char *features[] = { XMLNS_DISCO_INFO,
     95                                                   XMLNS_VERSION,
    9596                                                   XMLNS_TIME,
    9697                                                   XMLNS_CHATSTATES,
     
    132133                    !( s = xt_find_attr( c, "xmlns" ) ) )
    133134                {
    134                         imcb_log( ic, "WARNING: Received incomplete IQ-%s packet", type );
     135                        imcb_log( ic, "Warning: Received incomplete IQ-%s packet", type );
    135136                        return XT_HANDLED;
    136137                } else if( strcmp( s, XMLNS_ROSTER ) == 0 )
     
    152153                        else
    153154                        {
    154                                 imcb_log( ic, "WARNING: %s tried to fake a roster push!", s ? s : "(unknown)" );
     155                                imcb_log( ic, "Warning: %s tried to fake a roster push!", s ? s : "(unknown)" );
    155156                               
    156157                                xt_free_node( reply );
     
    220221        if( !( query = xt_find_node( node->children, "query" ) ) )
    221222        {
    222                 imcb_log( ic, "WARNING: Received incomplete IQ packet while authenticating" );
     223                imcb_log( ic, "Warning: Received incomplete IQ packet while authenticating" );
    223224                imc_logout( ic, FALSE );
    224225                return XT_HANDLED;
     
    278279        if( !( type = xt_find_attr( node, "type" ) ) )
    279280        {
    280                 imcb_log( ic, "WARNING: Received incomplete IQ packet while authenticating" );
     281                imcb_log( ic, "Warning: Received incomplete IQ packet while authenticating" );
    281282                imc_logout( ic, FALSE );
    282283                return XT_HANDLED;
     
    354355        if( !( query = xt_find_node( node->children, "query" ) ) )
    355356        {
    356                 imcb_log( ic, "WARNING: Received NULL roster packet" );
     357                imcb_log( ic, "Warning: Received NULL roster packet" );
    357358                return XT_HANDLED;
    358359        }
  • protocols/jabber/jabber.c

    r0fbd3a6d r1ba7e8f  
    3535#include "base64.h"
    3636
     37GSList *jabber_connections;
     38
    3739static void jabber_init( account_t *acc )
    3840{
     
    7072        struct ns_srv_reply *srv = NULL;
    7173        char *connect_to, *s;
     74       
     75        /* For now this is needed in the _connected() handlers if using
     76           GLib event handling, to make sure we're not handling events
     77           on dead connections. */
     78        jabber_connections = g_slist_prepend( jabber_connections, ic );
    7279       
    7380        jd->ic = ic;
     
    197204                imcb_error( ic, "Could not connect to server" );
    198205                imc_logout( ic, TRUE );
     206               
     207                return;
    199208        }
    200209       
     
    261270        g_free( jd->username );
    262271        g_free( jd );
     272       
     273        jabber_connections = g_slist_remove( jabber_connections, ic );
    263274}
    264275
  • protocols/jabber/jabber.h

    r0fbd3a6d r1ba7e8f  
    2929#include "xmltree.h"
    3030#include "bitlbee.h"
     31
     32extern GSList *jabber_connections;
    3133
    3234typedef enum
     
    4749typedef enum
    4850{
    49         JBFLAG_PROBED_XEP85 = 1,        /* Set this when we sent our probe packet to make
     51        JBFLAG_PROBED_XEP85 = 1,        /* Set this when we sent our probe packet to make
    5052                                           sure it gets sent only once. */
    51         JBFLAG_DOES_XEP85 = 2,          /* Set this when the resource seems to support
     53        JBFLAG_DOES_XEP85 = 2,          /* Set this when the resource seems to support
    5254                                           XEP85 (typing notification shite). */
    53         JBFLAG_IS_CHATROOM = 4,         /* It's convenient to use this JID thingy for
     55        JBFLAG_IS_CHATROOM = 4,         /* It's convenient to use this JID thingy for
    5456                                           groupchat state info too. */
    55         JBFLAG_IS_ANONYMOUS = 8,        /* For anonymous chatrooms, when we don't have
     57        JBFLAG_IS_ANONYMOUS = 8,        /* For anonymous chatrooms, when we don't have
    5658                                           have a real JID. */
    5759} jabber_buddy_flags_t;
     
    6466        char port[6];
    6567} jabber_streamhost_t;
     68
     69typedef enum
     70{
     71        JCFLAG_MESSAGE_SENT = 1,        /* Set this after sending the first message, so
     72                                           we can detect echoes/backlogs. */
     73} jabber_chat_flags_t;
    6674
    6775struct jabber_data
     
    105113struct jabber_cache_entry
    106114{
     115        time_t saved_at;
    107116        struct xt_node *node;
    108117        jabber_cache_event func;
     
    175184#define JABBER_PACKET_ID "BeeP"
    176185#define JABBER_CACHED_ID "BeeC"
     186
     187/* The number of seconds to keep cached packets before garbage collecting
     188   them. This gc is done on every keepalive (every minute). */
     189#define JABBER_CACHE_MAX_AGE 600
    177190
    178191/* RFC 392[01] stuff */
     
    198211#define XMLNS_MUC          "http://jabber.org/protocol/muc"                      /* XEP-0045 */
    199212#define XMLNS_MUC_USER     "http://jabber.org/protocol/muc#user"                 /* XEP-0045 */
     213#define XMLNS_CAPS         "http://jabber.org/protocol/caps"                     /* XEP-0115 */
    200214#define XMLNS_FEATURE      "http://jabber.org/protocol/feature-neg"              /* XEP-0020 */
    201215#define XMLNS_SI           "http://jabber.org/protocol/si"                       /* XEP-0095 */
  • protocols/jabber/jabber_util.c

    r0fbd3a6d r1ba7e8f  
    146146        entry->node = node;
    147147        entry->func = func;
     148        entry->saved_at = time( NULL );
    148149        g_hash_table_insert( jd->node_cache, xt_find_attr( node, "id" ), entry );
    149150}
     
    167168{
    168169        struct jabber_data *jd = ic->proto_data;
    169        
    170         g_hash_table_foreach_remove( jd->node_cache, jabber_cache_clean_entry, NULL );
    171 }
    172 
    173 gboolean jabber_cache_clean_entry( gpointer key, gpointer entry_, gpointer nullpointer )
     170        time_t threshold = time( NULL ) - JABBER_CACHE_MAX_AGE;
     171       
     172        g_hash_table_foreach_remove( jd->node_cache, jabber_cache_clean_entry, &threshold );
     173}
     174
     175gboolean jabber_cache_clean_entry( gpointer key, gpointer entry_, gpointer threshold_ )
    174176{
    175177        struct jabber_cache_entry *entry = entry_;
    176         struct xt_node *node = entry->node;
    177        
    178         if( node->flags & XT_SEEN )
    179                 return TRUE;
    180         else
    181         {
    182                 node->flags |= XT_SEEN;
    183                 return FALSE;
    184         }
     178        time_t *threshold = threshold_;
     179       
     180        return entry->saved_at < *threshold;
    185181}
    186182
     
    204200        if( entry == NULL )
    205201        {
    206                 imcb_log( ic, "WARNING: Received %s-%s packet with unknown/expired ID %s!",
     202                imcb_log( ic, "Warning: Received %s-%s packet with unknown/expired ID %s!",
    207203                              node->name, xt_find_attr( node, "type" ) ? : "(no type)", s );
    208204        }
     
    403399                if( ( bud = g_hash_table_lookup( jd->buddies, jid ) ) )
    404400                {
     401                        /* Just return the first one for this bare JID. */
     402                        if( flags & GET_BUDDY_FIRST )
     403                        {
     404                                *s = '/';
     405                                g_free( jid );
     406                                return bud;
     407                        }
     408                       
    405409                        /* Is this one of those no-resource buddies? */
    406410                        if( bud->resource == NULL )
    407411                        {
     412                                *s = '/';
    408413                                g_free( jid );
    409414                                return NULL;
    410415                        }
    411                         else
    412                         {
    413                                 /* See if there's an exact match. */
    414                                 for( ; bud; bud = bud->next )
    415                                         if( g_strcasecmp( bud->resource, s + 1 ) == 0 )
    416                                                 break;
    417                         }
     416                       
     417                        /* See if there's an exact match. */
     418                        for( ; bud; bud = bud->next )
     419                                if( g_strcasecmp( bud->resource, s + 1 ) == 0 )
     420                                        break;
    418421                }
    419422                else
     
    424427                           is done to handle conferences properly. */
    425428                        none_found = 1;
     429                        /* TODO(wilmer): Find out what I was thinking when I
     430                           wrote this??? And then fix it. This makes me sad... */
    426431                }
    427432               
     
    453458                else if( ( bud->resource == NULL || bud->next == NULL ) )
    454459                        /* No need for selection if there's only one option. */
     460                        return bud;
     461                else if( flags & GET_BUDDY_FIRST )
     462                        /* Looks like the caller doesn't care about details. */
    455463                        return bud;
    456464               
  • protocols/jabber/presence.c

    r0fbd3a6d r1ba7e8f  
    2929        char *from = xt_find_attr( node, "from" );
    3030        char *type = xt_find_attr( node, "type" );      /* NULL should mean the person is online. */
    31         struct xt_node *c;
    32         struct jabber_buddy *bud;
    33         int is_chat = 0, is_away = 0;
     31        struct xt_node *c, *cap;
     32        struct jabber_buddy *bud, *send_presence = NULL;
     33        int is_chat = 0;
    3434        char *s;
    3535       
     
    5050                {
    5151                        if( set_getbool( &ic->irc->set, "debug" ) )
    52                                 imcb_log( ic, "WARNING: Could not handle presence information from JID: %s", from );
     52                                imcb_log( ic, "Warning: Could not handle presence information from JID: %s", from );
    5353                        return XT_HANDLED;
    5454                }
     
    6363                {
    6464                        bud->away_state = (void*) jabber_away_state_by_code( c->text );
    65                         if( strcmp( c->text, "chat" ) != 0 )
    66                                 is_away = OPT_AWAY;
    6765                }
    6866                else
     
    7977                        bud->priority = 0;
    8078               
     79                if( bud && ( cap = xt_find_node( node->children, "c" ) ) &&
     80                    ( s = xt_find_attr( cap, "xmlns" ) ) && strcmp( s, XMLNS_CAPS ) == 0 )
     81                {
     82                        /* This <presence> stanza includes an XEP-0115
     83                           capabilities part. Not too interesting, but we can
     84                           see if it has an ext= attribute. */
     85                        s = xt_find_attr( cap, "ext" );
     86                        if( s && ( strstr( s, "cstates" ) || strstr( s, "chatstate" ) ) )
     87                                bud->flags |= JBFLAG_DOES_XEP85;
     88                       
     89                        /* This field can contain more information like xhtml
     90                           support, but we don't support that ourselves.
     91                           Officially the ext= tag was deprecated, but enough
     92                           clients do send it.
     93                           
     94                           (I'm aware that this is not the right way to use
     95                           this field.) See for an explanation of ext=:
     96                           http://www.xmpp.org/extensions/attic/xep-0115-1.3.html*/
     97                }
     98               
    8199                if( is_chat )
    82100                        jabber_chat_pkt_presence( ic, bud, node );
    83                 else if( bud == jabber_buddy_by_jid( ic, bud->bare_jid, 0 ) )
    84                         imcb_buddy_status( ic, bud->bare_jid, OPT_LOGGED_IN | is_away,
    85                                            ( is_away && bud->away_state ) ? bud->away_state->full_name : NULL,
    86                                            bud->away_message );
     101                else
     102                        send_presence = jabber_buddy_by_jid( ic, bud->bare_jid, 0 );
    87103        }
    88104        else if( strcmp( type, "unavailable" ) == 0 )
     
    91107                {
    92108                        if( set_getbool( &ic->irc->set, "debug" ) )
    93                                 imcb_log( ic, "WARNING: Received presence information from unknown JID: %s", from );
     109                                imcb_log( ic, "Warning: Received presence information from unknown JID: %s", from );
    94110                        return XT_HANDLED;
    95111                }
     
    119135                        /* If another resource is still available, send its presence
    120136                           information. */
    121                         if( ( bud = jabber_buddy_by_jid( ic, from, 0 ) ) )
    122                         {
    123                                 if( bud->away_state && ( *bud->away_state->code == 0 ||
    124                                     strcmp( bud->away_state->code, "chat" ) == 0 ) )
    125                                         is_away = OPT_AWAY;
    126                                
    127                                 imcb_buddy_status( ic, bud->bare_jid, OPT_LOGGED_IN | is_away,
    128                                                    ( is_away && bud->away_state ) ? bud->away_state->full_name : NULL,
    129                                                    bud->away_message );
    130                         }
    131                         else
     137                        if( ( send_presence = jabber_buddy_by_jid( ic, from, 0 ) ) == NULL )
    132138                        {
    133139                                /* Otherwise, count him/her as offline now. */
     
    177183                } */
    178184        }
     185
     186        if( send_presence )
     187        {
     188                int is_away = 0;
     189
     190                if( send_presence->away_state && !( *send_presence->away_state->code == 0 ||
     191                    strcmp( send_presence->away_state->code, "chat" ) == 0 ) )
     192                        is_away = OPT_AWAY;
     193
     194                imcb_buddy_status( ic, send_presence->bare_jid, OPT_LOGGED_IN | is_away,
     195                                   ( is_away && send_presence->away_state ) ?
     196                                   send_presence->away_state->full_name : NULL,
     197                                   send_presence->away_message );
     198        }
    179199       
    180200        return XT_HANDLED;
     
    186206{
    187207        struct jabber_data *jd = ic->proto_data;
    188         struct xt_node *node;
     208        struct xt_node *node, *cap;
    189209        char *show = jd->away_state->code;
    190210        char *status = jd->away_message;
     
    199219                xt_add_child( node, xt_new_node( "status", status, NULL ) );
    200220       
     221        /* This makes the packet slightly bigger, but clients interested in
     222           capabilities can now cache the discovery info. This reduces the
     223           usual post-login iq-flood. See XEP-0115. At least libpurple and
     224           Trillian seem to do this right. */
     225        cap = xt_new_node( "c", NULL, NULL );
     226        xt_add_attr( cap, "xmlns", XMLNS_CAPS );
     227        xt_add_attr( cap, "node", "http://bitlbee.org/xmpp/caps" );
     228        xt_add_attr( cap, "ver", BITLBEE_VERSION ); /* The XEP wants this hashed, but nobody's doing that. */
     229        xt_add_child( node, cap );
     230       
    201231        st = jabber_write_packet( ic, node );
    202232       
Note: See TracChangeset for help on using the changeset viewer.