Changes in / [0c41177:c5bc47b]


Ignore:
Files:
2 added
38 edited

Legend:

Unmodified
Added
Removed
  • Makefile

    r0c41177 rc5bc47b  
    1010
    1111# Program variables
    12 objects = account.o bitlbee.o crypting.o help.o ipc.o irc.o irc_commands.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS) user.o
     12objects = account.o bitlbee.o chat.o crypting.o help.o ipc.o irc.o irc_commands.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS) user.o
    1313headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h user.h lib/events.h lib/http_client.h lib/ini.h lib/md5.h lib/misc.h lib/proxy.h lib/sha1.h lib/ssl_client.h lib/url.h protocols/nogaim.h
    1414subdirs = lib protocols
  • account.c

    r0c41177 rc5bc47b  
    190190{
    191191        account_t *a, *l = NULL;
     192        struct chat *c, *nc;
    192193       
    193194        if( acc->ic )
     
    202203                        else
    203204                                irc->accounts = a->next;
     205                       
     206                        for( c = irc->chatrooms; c; c = nc )
     207                        {
     208                                nc = c->next;
     209                                if( acc == c->acc )
     210                                        chat_del( irc, c );
     211                        }
    204212                       
    205213                        while( a->set )
  • bitlbee.h

    r0c41177 rc5bc47b  
    3333
    3434#define PACKAGE "BitlBee"
    35 #define BITLBEE_VERSION "1.2.3"
     35#define BITLBEE_VERSION "1.2.4"
    3636#define VERSION BITLBEE_VERSION
    3737
     
    129129#include "account.h"
    130130#include "nick.h"
     131#include "chat.h"
    131132#include "conf.h"
    132133#include "log.h"
  • conf.c

    r0c41177 rc5bc47b  
    308308                        else
    309309                        {
    310                                 fprintf( stderr, "Error: Unknown setting `%s` in configuration file.\n", ini->key );
     310                                fprintf( stderr, "Error: Unknown setting `%s` in configuration file (line %d).\n", ini->key, ini->line );
    311311                                return 0;
    312312                                /* For now just ignore unknown keys... */
     
    315315                else if( g_strcasecmp( ini->section, "defaults" ) != 0 )
    316316                {
    317                         fprintf( stderr, "Error: Unknown section [%s] in configuration file. "
    318                                          "BitlBee configuration must be put in a [settings] section!\n", ini->section );
     317                        fprintf( stderr, "Error: Unknown section [%s] in configuration file (line %d). "
     318                                         "BitlBee configuration must be put in a [settings] section!\n", ini->section, ini->line );
    319319                        return 0;
    320320                }
  • doc/CHANGES

    r0c41177 rc5bc47b  
    33
    44http://bugs.bitlbee.org/bitlbee/timeline?daysback=90&changeset=on
     5
     6Version 1.2.4:
     7- Most important change (and main reason for releasing now): Upgraded Yahoo!
     8  module to a newer version to get it working again.
     9- join_chat command replaced with the much better chat command:
     10  * Similar to how account replaced login/slist/logout. Add a chatroom once,
     11    then just /join it like any other room. Also automatic joining at login
     12    time is now possible.
     13  * Note that the old way of starting groupchats (/join #nickname) is now
     14    also deprecated, use "chat with" instead.
     15  * See "help chat" and "help chat add" for more information.
     16- Rewrote bitlbee.conf parser to be less dumb.
     17- Fixed compatibility (hopefully) with AIM mobile messages, certain kinds
     18  of Google Talk chatrooms.
     19- Fixed numerous stability/reliability bugs over the last year.
     20
     21Finished 17 Oct 2009
    522
    623Version 1.2.3:
  • doc/user-guide/commands.xml

    r0c41177 rc5bc47b  
    125125                        <description>
    126126                                <para>
    127                                         This command gives you a list of all the accounts known by BitlBee, including the numbers you'll need for most account commands.
     127                                        This command gives you a list of all the accounts known by BitlBee.
    128128                                </para>
    129129                        </description>
     
    138138                        <description>
    139139                                <para>
    140                                         This account can be used to change various settings for IM accounts. For all protocols, this command can be used to change the handle or the password BitlBee uses to log in and if it should be logged in automatically. Some protocols have additional settings. You can see the settings available for a connection by typing <emphasis>account set &lt;account id&gt;</emphasis>.
     140                                        This command can be used to change various settings for IM accounts. For all protocols, this command can be used to change the handle or the password BitlBee uses to log in and if it should be logged in automatically. Some protocols have additional settings. You can see the settings available for a connection by typing <emphasis>account set &lt;account id&gt;</emphasis>.
    141141                                </para>
    142142                               
    143143                                <para>
    144                                         For more infomation about a setting, see <emphasis>help set &lt;setting&gt;</emphasis>. For details about the syntax of this command, see <emphasis>help set</emphasis>.
     144                                        For more infomation about a setting, see <emphasis>help set &lt;setting&gt;</emphasis>.
    145145                                </para>
    146146                               
    147147                                <para>
    148148                                        The account ID can be a number (see <emphasis>account list</emphasis>), the protocol name or (part of) the screenname, as long as it matches only one connection.
     149                                </para>
     150                        </description>
     151                </bitlbee-command>
     152        </bitlbee-command>
     153
     154        <bitlbee-command name="chat">
     155                <short-description>Chatroom list maintenance</short-description>
     156                <syntax>chat &lt;action&gt; [&lt;arguments&gt;]</syntax>
     157
     158                <description>
     159
     160                        <para>
     161                                Available actions: add, del, list, with and set. See <emphasis>help chat &lt;action&gt;</emphasis> for more information.
     162                        </para>
     163
     164                </description>
     165
     166                <bitlbee-command name="add">
     167                        <syntax>chat add &lt;account&gt; &lt;room&gt; [&lt;channel&gt;]</syntax>
     168
     169                        <description>
     170                                <para>
     171                                        Add a chatroom to the list of chatrooms you're interested in. BitlBee needs this list to map room names to a proper IRC channel name.
     172                                </para>
     173
     174                                <para>
     175                                        After adding a room to your list, you can simply use the IRC /join command to enter the room. Also, you can tell BitlBee to automatically join the room when you log in. (See <emphasis>chat set</emphasis>)
     176                                </para>
     177
     178                                <para>
     179                                        Password-protected rooms work exactly like on IRC, by passing the password as an extra argument to /join.
     180                                </para>
     181                        </description>
     182
     183                </bitlbee-command>
     184
     185                <bitlbee-command name="del">
     186                        <syntax>chat del &lt;chat id&gt;</syntax>
     187
     188                        <description>
     189                                <para>
     190                                        This commands deletes an chatroom from your list.
     191                                </para>
     192
     193                                <para>
     194                                        The room ID can be a number (see <emphasis>chat list</emphasis>), or (part of) the name of the room/channel.
     195                                </para>
     196                        </description>
     197                </bitlbee-command>
     198
     199                <bitlbee-command name="list">
     200                        <syntax>chat list</syntax>
     201
     202                        <description>
     203                                <para>
     204                                        This command gives you a list of all the chatrooms known by BitlBee.
     205                                </para>
     206                        </description>
     207                </bitlbee-command>
     208
     209                <bitlbee-command name="with">
     210                        <syntax>chat with &lt;nickname&gt;</syntax>
     211
     212                        <description>
     213                                <para>
     214                                        While most <emphasis>chat</emphasis> subcommands are about named chatrooms, this command can be used to open an unnamed groupchat with one or more persons. This command is what <emphasis>/join #nickname</emphasis> used to do in older BitlBee versions.
     215                                </para>
     216                        </description>
     217                </bitlbee-command>
     218
     219                <bitlbee-command name="set">
     220                        <syntax>chat set &lt;chat id&gt;</syntax>
     221                        <syntax>chat set &lt;chat id&gt;/&lt;setting&gt;</syntax>
     222                        <syntax>chat set &lt;chat id&gt;/&lt;setting&gt; &lt;value&gt;</syntax>
     223                        <syntax>chat set -del &lt;chat id&gt;/&lt;setting&gt;</syntax>
     224
     225                        <description>
     226                                <para>
     227                                        This command can be used to change various settings for chatrooms.
     228                                </para>
     229                               
     230                                <para>
     231                                        For more infomation about a setting, see <emphasis>help set &lt;setting&gt;</emphasis>.
     232                                </para>
     233                               
     234                                <para>
     235                                        The room ID can be a number (see <emphasis>chat list</emphasis>), or (part of) the name of the room/channel.
    149236                                </para>
    150237                        </description>
     
    303390        </bitlbee-setting>
    304391
     392        <bitlbee-setting name="auto_join" type="boolean" scope="chat">
     393                <default>false</default>
     394
     395                <description>
     396                        <para>
     397                                With this option enabled, BitlBee will automatically join this chatroom when you log in.
     398                        </para>
     399                </description>
     400        </bitlbee-setting>
     401
    305402        <bitlbee-setting name="auto_reconnect" type="boolean" scope="both">
    306403                <default>false</default>
     
    486583        </bitlbee-setting>
    487584
     585        <bitlbee-setting name="nick" type="string" scope="chat">
     586
     587                <description>
     588                        <para>
     589                                You can use this option to set your nickname in a chatroom. You won't see this nickname yourself, but other people in the room will. By default, BitlBee will use your username as the chatroom nickname.
     590                        </para>
     591                </description>
     592        </bitlbee-setting>
     593
    488594        <bitlbee-setting name="ops" type="string" scope="global">
    489595                <default>both</default>
     
    580686        <bitlbee-setting name="resource_select" type="string" scope="account">
    581687                <default>priority</default>
    582                 <possible-values>priority, time</possible-values>
     688                <possible-values>priority, activity</possible-values>
    583689
    584690                <description>
     
    588694
    589695                        <para>
    590                                 Normally it's set to <emphasis>priority</emphasis> which means messages will always be delivered to the buddy's resource with the highest priority. If the setting is set to <emphasis>time</emphasis>, messages will be delivered to the resource that was last used to send you a message (or the resource that most recently connected).
     696                                Normally it's set to <emphasis>priority</emphasis> which means messages will always be delivered to the buddy's resource with the highest priority. If the setting is set to <emphasis>activity</emphasis>, messages will be delivered to the resource that was last used to send you a message (or the resource that most recently connected).
    591697                        </para>
    592698                </description>
     
    854960
    855961        </bitlbee-command>
    856 
    857         <bitlbee-command name="join_chat">
    858                 <short-description>Join a named groupchat/conference room</short-description>
    859                 <syntax>join_chat &lt;connection&gt; &lt;room name&gt; [&lt;channel name&gt;] [&lt;room nickname&gt;] [&lt;password&gt;]</syntax>
    860 
    861                 <description>
    862                         <para>
    863                                 On most IM-networks groupchats can be started using the /join command. (<emphasis>/join #foo</emphasis> to start a chatroom with you and <emphasis>foo</emphasis>) This doesn't work with names groupchats though (which exist on Jabber networks and AIM, for example), instead you can use this command.
    864                         </para>
    865 
    866                         <para>
    867                                 The first two arguments are required. <emphasis>room name</emphasis> is the name of the chatroom on the IM-network. <emphasis>channel name</emphasis> is the IRC channel name BitlBee should map this to. <emphasis>room nickname</emphasis> is the nickname you want to have in this channel. If you don't give these options, BitlBee will do the right guesses.
    868                         </para>
    869 
    870                         <para>
    871                                 The following command will join you to the chatroom called <emphasis>bitlbee@conference.bitlbee.org</emphasis>. The channel will be called <emphasis>&amp;bitlbee-help</emphasis> because <emphasis>&amp;bitlbee</emphasis> will already be in use. Your nickname will be <emphasis>help-me</emphasis>.
    872                         </para>
    873                 </description>
    874 
    875                 <ircexample>
    876                         <ircline nick="wilmer">join_chat jabber bitlbee@conference.bitlbee.org &amp;bitlbee-help help-me</ircline>
    877                 </ircexample>
    878 
    879         </bitlbee-command>
    880962</chapter>
  • doc/user-guide/misc.xml

    r0c41177 rc5bc47b  
    6969
    7070<para>
    71 If you want to start a groupchat with the person <emphasis>lisa_msn</emphasis> in it, just join the channel <emphasis>#lisa_msn</emphasis>. BitlBee will refuse to join you to the channel with that name, but it will create a new virtual channel with root, you and lisa_msn in it.
     71To open a groupchat, use the <emphasis>chat with</emphasis> command. For example,  to start a groupchat with the person <emphasis>lisa_msn</emphasis> in it, just type <emphasis>chat with lisa_msn</emphasis>. BitlBee will create a new virtual channel with root, you and lisa_msn in it.
    7272</para>
    7373
    7474<para>
    75 Of course a channel with only two people isn't really exciting yet. So the next step is to invite some other people to the channel. For this, you can use the <emphasis>/invite</emphasis> command of your IRC client. Please do keep in mind that all the people have to be on the same network and contact list! You can't invite Yahoo! buddies into an MSN groupchat.
     75Then, just use the ordinary IRC <emphasis>/invite</emphasis> command to invite more people. Please do keep in mind that all the people have to be on the same network and contact list! You can't invite Yahoo! buddies into an MSN groupchat.
    7676</para>
    7777
    7878<para>
    79 Some protocols (like Jabber) also support named groupchats. BitlBee now supports these too. You can use the <emphasis>join_chat</emphasis> command to join them. See <emphasis>help join_chat</emphasis> for more information.
     79Some protocols (like Jabber) also support named groupchats. BitlBee now supports these too. You can use the <emphasis>chat add</emphasis> command to join them. See <emphasis>help chat_add</emphasis> for more information.
    8080</para>
    8181
  • irc.c

    r0c41177 rc5bc47b  
    407407                        }
    408408                       
    409                         if( lines[i] )
    410                         {
    411                                 if( ( cmd = irc_parse_line( lines[i] ) ) == NULL )
    412                                         continue;
     409                        if( lines[i] && ( cmd = irc_parse_line( lines[i] ) ) )
     410                        {
    413411                                irc_exec( irc, cmd );
    414412                                g_free( cmd );
     
    485483        if( line[0] == ':' )
    486484        {
    487                 for( i = 0; line[i] != ' '; i ++ );
     485                for( i = 0; line[i] && line[i] != ' '; i ++ );
    488486                line = line + i;
    489487        }
     
    781779        irc_reply( irc,   3, ":%s", IRCD_INFO );
    782780        irc_reply( irc,   4, "%s %s %s %s", irc->myhost, BITLBEE_VERSION, UMODES UMODES_PRIV, CMODES );
    783         irc_reply( irc,   5, "PREFIX=(ov)@+ CHANTYPES=#& CHANMODES=,,,%s NICKLEN=%d NETWORK=BitlBee CASEMAPPING=rfc1459 MAXTARGETS=1 WATCH=128 :are supported by this server", CMODES, MAX_NICK_LENGTH - 1 );
     781        irc_reply( irc,   5, "PREFIX=(ov)@+ CHANTYPES=%s CHANMODES=,,,%s NICKLEN=%d NETWORK=BitlBee "
     782                             "CASEMAPPING=rfc1459 MAXTARGETS=1 WATCH=128 :are supported by this server",
     783                             CTYPES, CMODES, MAX_NICK_LENGTH - 1 );
    784784        irc_motd( irc );
    785785        irc->umode[0] = '\0';
     
    10221022        user_t *u = NULL;
    10231023       
    1024         if( *nick == '#' || *nick == '&' )
     1024        if( strchr( CTYPES, *nick ) )
    10251025        {
    10261026                if( !( c = irc_chat_by_channel( irc, nick ) ) )
  • irc.h

    r0c41177 rc5bc47b  
    3838#define CMODE "t"
    3939#define UMODE "s"
     40#define CTYPES "&#"
    4041
    4142typedef enum
     
    4748        USTATUS_SHUTDOWN = 8
    4849} irc_status_t;
    49 
    50 typedef struct channel
    51 {
    52         char *name;
    53 } channel_t;
    5450
    5551typedef struct irc
     
    8783        struct query *queries;
    8884        struct account *accounts;
     85        struct chat *chatrooms;
    8986       
    9087        struct __USER *users;
     
    10097
    10198#include "user.h"
    102 // #include "nick.h"
    10399
    104100extern GSList *irc_connection_list;
  • irc_commands.c

    r0c41177 rc5bc47b  
    125125static void irc_cmd_mode( irc_t *irc, char **cmd )
    126126{
    127         if( *cmd[1] == '#' || *cmd[1] == '&' )
     127        if( strchr( CTYPES, *cmd[1] ) )
    128128        {
    129129                if( cmd[2] )
     
    193193        else if( cmd[1] )
    194194        {
    195                 if( ( cmd[1][0] == '#' || cmd[1][0] == '&' ) && cmd[1][1] )
    196                 {
    197                         user_t *u = user_find( irc, cmd[1] + 1 );
    198                        
    199                         if( u && u->ic && u->ic->acc->prpl->chat_with )
    200                         {
    201                                 irc_reply( irc, 403, "%s :Initializing groupchat in a different channel", cmd[1] );
    202                                
    203                                 if( !u->ic->acc->prpl->chat_with( u->ic, u->handle ) )
    204                                 {
    205                                         irc_usermsg( irc, "Could not open a groupchat with %s.", u->nick );
    206                                 }
    207                         }
    208                         else if( u )
    209                         {
    210                                 irc_reply( irc, 403, "%s :Groupchats are not possible with %s", cmd[1], cmd[1]+1 );
    211                         }
    212                         else
    213                         {
    214                                 irc_reply( irc, 403, "%s :No such nick", cmd[1] );
    215                         }
    216                 }
     195                struct chat *c;
     196               
     197                if( strchr( CTYPES, cmd[1][0] ) == NULL || cmd[1][1] == 0 )
     198                        irc_reply( irc, 479, "%s :Invalid channel name", cmd[1] );
     199                else if( ( c = chat_bychannel( irc, cmd[1] ) ) && c->acc && c->acc->ic )
     200                        chat_join( irc, c, cmd[2] );
    217201                else
    218                 {
    219202                        irc_reply( irc, 403, "%s :No such channel", cmd[1] );
    220                 }
    221203        }
    222204}
     
    433415                        if( g_hash_table_lookup_extended( irc->watches, nick, &okey, &ovalue ) )
    434416                        {
     417                                g_hash_table_remove( irc->watches, okey );
    435418                                g_free( okey );
    436                                 g_hash_table_remove( irc->watches, okey );
    437419                               
    438420                                irc_reply( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" );
  • lib/events_libevent.c

    r0c41177 rc5bc47b  
    3737
    3838static void b_main_restart();
    39 static guint id_next = 1;
     39static guint id_next = 1; /* Next ID to be allocated to an event handler. */
     40static guint id_cur = 0; /* Event ID that we're currently handling. */
     41static guint id_dead; /* Set to 1 if b_event_remove removes id_cur. */
    4042static GHashTable *id_hash;
    41 static int quitting = 0;
     43static int quitting = 0; /* Prepare to quit, stop handling events. */
    4244
    4345/* Since libevent doesn't handle two event handlers for one fd-condition
     
    119121        struct b_event_data *b_ev = data;
    120122        b_input_condition cond = 0;
    121         int id;
     123        gboolean st;
    122124       
    123125        if( fd >= 0 )
     
    133135        /* Since the called function might cancel this handler already
    134136           (which free()s b_ev), we have to remember the ID here. */
    135         id = b_ev->id;
     137        id_cur = b_ev->id;
     138        id_dead = 0;
    136139       
    137140        if( quitting )
    138141        {
    139                 b_event_remove( id );
     142                b_event_remove( id_cur );
    140143                return;
    141144        }
    142145       
    143         if( !b_ev->function( b_ev->data, fd, cond ) )
     146        st = b_ev->function( b_ev->data, fd, cond );
     147        if( id_dead )
     148        {
     149                /* This event was killed already, don't touch it! */
     150                return;
     151        }
     152        else if( !st )
    144153        {
    145154                event_debug( "Handler returned FALSE: " );
    146                 b_event_remove( id );
     155                b_event_remove( id_cur );
    147156        }
    148157        else if( fd == -1 )
    149158        {
     159                /* fd == -1 means it was a timer. These can't be auto-repeated
     160                   so it has to be recreated every time. */
    150161                struct timeval tv;
    151162               
     
    236247        if( b_ev )
    237248        {
     249                if( id == id_cur )
     250                        id_dead = TRUE;
     251               
    238252                g_hash_table_remove( id_hash, &b_ev->id );
    239253                if( b_ev->evinfo.ev_fd >= 0 )
  • lib/http_client.c

    r0c41177 rc5bc47b  
    5959        if( error )
    6060        {
    61                 g_free( req );
    62                 return( NULL );
     61                http_free( req );
     62                return NULL;
    6363        }
    6464       
     
    160160       
    161161        req->func( req );
    162        
    163         g_free( req->request );
    164         g_free( req );
    165        
     162        http_free( req );
    166163        return FALSE;
    167164}
     
    444441       
    445442        req->func( req );
    446        
     443        http_free( req );
     444        return FALSE;
     445}
     446
     447void http_free( struct http_request *req )
     448{
    447449        g_free( req->request );
    448450        g_free( req->reply_headers );
    449451        g_free( req->status_string );
    450452        g_free( req );
    451        
    452         return FALSE;
    453 }
     453}
     454
  • lib/http_client.h

    r0c41177 rc5bc47b  
    8181void *http_dorequest( char *host, int port, int ssl, char *request, http_input_function func, gpointer data );
    8282void *http_dorequest_url( char *url_string, http_input_function func, gpointer data );
     83
     84void http_free( struct http_request *req );
  • lib/ini.c

    r0c41177 rc5bc47b  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2005 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2008 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    2828ini_t *ini_open( char *file )
    2929{
    30         ini_t *ini = g_new0( ini_t, 1 );
     30        int fd;
     31        ini_t *ini = NULL;
     32        struct stat fi;
    3133       
    32         if( ( ini->fp = fopen( file, "r" ) ) == NULL )
     34        if( ( fd = open( file, O_RDONLY ) ) != -1 &&
     35            fstat( fd, &fi ) == 0 &&
     36            fi.st_size <= 16384 &&
     37            ( ini = g_malloc( sizeof( ini_t ) + fi.st_size + 1 ) ) &&
     38            read( fd, ini->file, fi.st_size ) == fi.st_size )
    3339        {
    34                 g_free( ini );
    35                 return( NULL );
     40                memset( ini, 0, sizeof( ini_t ) );
     41                ini->size = fi.st_size;
     42                ini->file[ini->size] = 0;
     43                ini->cur = ini->file;
     44                ini->c_section = "";
     45               
     46                close( fd );
     47               
     48                return ini;
    3649        }
     50
     51        if( fd >= 0 )
     52                close( fd );
    3753       
    38         return( ini );
     54        ini_close( ini );
     55
     56        return NULL;
     57}
     58
     59/* Strips leading and trailing whitespace and returns a pointer to the first
     60   non-ws character of the given string. */
     61static char *ini_strip_whitespace( char *in )
     62{
     63        char *e;
     64
     65        while( isspace( *in ) )
     66                in++;
     67
     68        e = in + strlen( in ) - 1;
     69        while( e > in && isspace( *e ) )
     70                e--;
     71        e[1] = 0;
     72       
     73        return in;
    3974}
    4075
    4176int ini_read( ini_t *file )
    4277{
    43         char key[MAX_STRING], s[MAX_STRING], *t;
    44         int i;
     78        char *s;
    4579       
    46         while( !feof( file->fp ) )
     80        while( file->cur && file->cur < file->file + file->size )
    4781        {
    48                 *s = 0;
    49                 fscanf( file->fp, "%127[^\n#]s", s );
    50                 fscanf( file->fp, "%*[^\n]s" );
    51                 fgetc( file->fp );              /* Skip newline         */
    52                 file->line ++;
    53                 if( strchr( s, '=' ) )
     82                char *e, *next;
     83               
     84                file->line++;
     85
     86                /* Find the end of line */
     87                if( ( e = strchr( file->cur, '\n' ) ) != NULL )
    5488                {
    55                         sscanf( s, "%[^ =]s", key );
    56                         if( ( t = strchr( key, '.' ) ) )
     89                        *e = 0;
     90                        next = e + 1;
     91                }
     92                else
     93                {
     94                        /* No more lines. */
     95                        e = file->cur + strlen( file->cur );
     96                        next = NULL;
     97                }
     98               
     99                /* Comment? */
     100                if( ( s = strchr( file->cur, '#' ) ) != NULL )
     101                        *s = 0;
     102               
     103                file->cur = ini_strip_whitespace( file->cur );
     104               
     105                if( *file->cur == '[' )
     106                {
     107                        file->cur++;
     108                        if( ( s = strchr( file->cur, ']' ) ) != NULL )
    57109                        {
    58                                 *t = 0;
    59                                 strcpy( file->section, key );
    60                                 t ++;
     110                                *s = 0;
     111                                file->c_section = file->cur;
     112                        }
     113                }
     114                else if( ( s = strchr( file->cur, '=' ) ) != NULL )
     115                {
     116                        *s = 0;
     117                        file->key = ini_strip_whitespace( file->cur );
     118                        file->value = ini_strip_whitespace( s + 1 );
     119                       
     120                        if( ( s = strchr( file->key, '.' ) ) != NULL )
     121                        {
     122                                *s = 0;
     123                                file->section = file->key;
     124                                file->key = s + 1;
    61125                        }
    62126                        else
    63127                        {
    64                                 strcpy( file->section, file->c_section );
    65                                 t = key;
     128                                file->section = file->c_section;
    66129                        }
    67                         sscanf( t, "%s", file->key );
    68                         t = strchr( s, '=' ) + 1;
    69                         for( i = 0; t[i] == ' '; i ++ );
    70                         strcpy( file->value, &t[i] );
    71                         for( i = strlen( file->value ) - 1; file->value[i] == 32; i -- )
    72                                 file->value[i] = 0;
    73130                       
    74                         return( 1 );
     131                        file->cur = next;
     132                        return 1;
    75133                }
    76                 else if( ( t = strchr( s, '[' ) ) )
    77                 {
    78                         strcpy( file->c_section, t + 1 );
    79                         t = strchr( file->c_section, ']' );
    80                         *t = 0;
    81                 }
     134                /* else: noise/comment/etc, let's just ignore it. */
     135
     136                file->cur = next;
    82137        }
    83         return( 0 );
     138       
     139        return 0;
    84140}
    85141
    86142void ini_close( ini_t *file )
    87143{
    88         fclose( file->fp );
    89144        g_free( file );
    90145}
  • lib/ini.h

    r0c41177 rc5bc47b  
    2929typedef struct
    3030{
    31         FILE *fp;
    3231        int line;
    33         char c_section[MAX_STRING];
    34         char section[MAX_STRING];
    35         char key[MAX_STRING];
    36         char value[MAX_STRING];
     32        char *c_section;
     33        char *section;
     34        char *key;
     35        char *value;
     36        int size;
     37        char *cur, *tok;
     38        char file[];
    3739} ini_t;
    3840
  • lib/proxy.c

    r0c41177 rc5bc47b  
    558558                return proxy_connect_socks5(host, port, phb);
    559559       
    560         if (phb->host) g_free(phb);
    561560        g_free(phb);
    562561        return -1;
  • lib/xmltree.c

    r0c41177 rc5bc47b  
    472472}
    473473
    474 struct xt_node *xt_new_node( char *name, char *text, struct xt_node *children )
     474struct xt_node *xt_new_node( char *name, const char *text, struct xt_node *children )
    475475{
    476476        struct xt_node *node, *c;
  • lib/xmltree.h

    r0c41177 rc5bc47b  
    9090char *xt_find_attr( struct xt_node *node, const char *key );
    9191
    92 struct xt_node *xt_new_node( char *name, char *text, struct xt_node *children );
     92struct xt_node *xt_new_node( char *name, const char *text, struct xt_node *children );
    9393void xt_add_child( struct xt_node *parent, struct xt_node *child );
    9494void xt_add_attr( struct xt_node *node, const char *key, const char *value );
  • protocols/jabber/conference.c

    r0c41177 rc5bc47b  
    2626static xt_status jabber_chat_join_failed( struct im_connection *ic, struct xt_node *node, struct xt_node *orig );
    2727
    28 struct groupchat *jabber_chat_join( struct im_connection *ic, char *room, char *nick, char *password )
     28struct groupchat *jabber_chat_join( struct im_connection *ic, const char *room, const char *nick, const char *password )
    2929{
    3030        struct jabber_chat *jc;
     
    3636        node = xt_new_node( "x", NULL, NULL );
    3737        xt_add_attr( node, "xmlns", XMLNS_MUC );
    38         node = jabber_make_packet( "presence", NULL, roomjid, node );
    3938        if( password )
    4039                xt_add_child( node, xt_new_node( "password", password, NULL ) );
     40        node = jabber_make_packet( "presence", NULL, roomjid, node );
    4141        jabber_cache_add( ic, node, jabber_chat_join_failed );
    4242       
     
    234234                            ( strcmp( s, XMLNS_MUC_USER ) == 0 ) )
    235235                        {
    236                                 c = xt_find_node( c->children, "item" );
    237                                 if( ( s = xt_find_attr( c, "jid" ) ) )
     236                                struct xt_node *item;
     237                               
     238                                item = xt_find_node( c->children, "item" );
     239                                if( ( s = xt_find_attr( item, "jid" ) ) )
    238240                                {
    239241                                        /* Yay, found what we need. :-) */
     
    283285        else if( type ) /* type can only be NULL or "unavailable" in this function */
    284286        {
    285                 s = strchr( bud->ext_jid, '/' );
    286                 if( s ) *s = 0;
    287                 imcb_chat_remove_buddy( chat, bud->ext_jid, NULL );
    288                 if( bud != jc->me && bud->flags & JBFLAG_IS_ANONYMOUS )
    289                         imcb_remove_buddy( ic, bud->ext_jid, NULL );
    290                 if( s ) *s = '/';
     287                if( ( bud->flags & JBFLAG_IS_CHATROOM ) && bud->ext_jid )
     288                {
     289                        s = strchr( bud->ext_jid, '/' );
     290                        if( s ) *s = 0;
     291                        imcb_chat_remove_buddy( chat, bud->ext_jid, NULL );
     292                        if( bud != jc->me && bud->flags & JBFLAG_IS_ANONYMOUS )
     293                                imcb_remove_buddy( ic, bud->ext_jid, NULL );
     294                        if( s ) *s = '/';
     295                }
    291296               
    292297                if( bud == jc->me )
  • protocols/jabber/iq.c

    r0c41177 rc5bc47b  
    5151        {
    5252                if( !( ( c = xt_find_node( node->children, "query" ) ) ||
    53                        ( c = xt_find_node( node->children, "ping" ) ) ) || /* O_o WHAT is wrong with just <query/> ????? */
     53                       ( c = xt_find_node( node->children, "ping" ) ) ) ||
    5454                    !( s = xt_find_attr( c, "xmlns" ) ) )
    5555                {
    56                         imcb_log( ic, "Warning: Received incomplete IQ-%s packet", type );
     56                        /* Sigh. Who decided to suddenly invent new elements
     57                           instead of just sticking with <query/>? */
    5758                        return XT_HANDLED;
    5859                }
  • protocols/jabber/jabber.c

    r0c41177 rc5bc47b  
    425425}
    426426
    427 static struct groupchat *jabber_chat_join_( struct im_connection *ic, char *room, char *nick, char *password )
     427static struct groupchat *jabber_chat_join_( struct im_connection *ic, const char *room, const char *nick, const char *password )
    428428{
    429429        if( strchr( room, '@' ) == NULL )
  • protocols/jabber/jabber.h

    r0c41177 rc5bc47b  
    240240
    241241/* conference.c */
    242 struct groupchat *jabber_chat_join( struct im_connection *ic, char *room, char *nick, char *password );
     242struct groupchat *jabber_chat_join( struct im_connection *ic, const char *room, const char *nick, const char *password );
    243243struct groupchat *jabber_chat_by_jid( struct im_connection *ic, const char *name );
    244244void jabber_chat_free( struct groupchat *c );
  • protocols/jabber/presence.c

    r0c41177 rc5bc47b  
    4949                if( !( bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT | GET_BUDDY_CREAT ) ) )
    5050                {
    51                         if( set_getbool( &ic->irc->set, "debug" ) )
    52                                 imcb_log( ic, "Warning: Could not handle presence information from JID: %s", from );
     51                        /*
     52                        imcb_log( ic, "Warning: Could not handle presence information from JID: %s", from );
     53                        */
    5354                        return XT_HANDLED;
    5455                }
     
    106107                if( ( bud = jabber_buddy_by_jid( ic, from, 0 ) ) == NULL )
    107108                {
    108                         if( set_getbool( &ic->irc->set, "debug" ) )
    109                                 imcb_log( ic, "Warning: Received presence information from unknown JID: %s", from );
     109                        /*
     110                        imcb_log( ic, "Warning: Received presence information from unknown JID: %s", from );
     111                        */
    110112                        return XT_HANDLED;
    111113                }
  • protocols/nogaim.c

    r0c41177 rc5bc47b  
    249249void imcb_connected( struct im_connection *ic )
    250250{
     251        irc_t *irc = ic->irc;
     252        struct chat *c;
    251253        user_t *u;
    252254       
     
    271273           exponential backoff timer. */
    272274        ic->acc->auto_reconnect_delay = 0;
     275       
     276        for( c = irc->chatrooms; c; c = c->next )
     277        {
     278                if( c->acc != ic->acc )
     279                        continue;
     280               
     281                if( set_getbool( &c->set, "auto_join" ) )
     282                        chat_join( irc, c, NULL );
     283        }
    273284}
    274285
     
    309320        ic->acc->prpl->logout( ic );
    310321        b_event_remove( ic->inpa );
     322       
     323        g_free( ic->away );
     324        ic->away = NULL;
    311325       
    312326        u = irc->users;
     
    492506}
    493507
    494 /* prpl.c */
    495 
    496 struct show_got_added_data
     508
     509struct imcb_ask_cb_data
    497510{
    498511        struct im_connection *ic;
     
    500513};
    501514
    502 void show_got_added_no( void *data )
    503 {
    504         g_free( ((struct show_got_added_data*)data)->handle );
     515static void imcb_ask_auth_cb_no( void *data )
     516{
     517        struct imcb_ask_cb_data *cbd = data;
     518       
     519        cbd->ic->acc->prpl->auth_deny( cbd->ic, cbd->handle );
     520       
     521        g_free( cbd->handle );
     522        g_free( cbd );
     523}
     524
     525static void imcb_ask_auth_cb_yes( void *data )
     526{
     527        struct imcb_ask_cb_data *cbd = data;
     528       
     529        cbd->ic->acc->prpl->auth_allow( cbd->ic, cbd->handle );
     530       
     531        g_free( cbd->handle );
     532        g_free( cbd );
     533}
     534
     535void imcb_ask_auth( struct im_connection *ic, const char *handle, const char *realname )
     536{
     537        struct imcb_ask_cb_data *data = g_new0( struct imcb_ask_cb_data, 1 );
     538        char *s, *realname_ = NULL;
     539       
     540        if( realname != NULL )
     541                realname_ = g_strdup_printf( " (%s)", realname );
     542       
     543        s = g_strdup_printf( "The user %s%s wants to add you to his/her buddy list.",
     544                             handle, realname_ ?: "" );
     545       
     546        g_free( realname_ );
     547       
     548        data->ic = ic;
     549        data->handle = g_strdup( handle );
     550        query_add( ic->irc, ic, s, imcb_ask_auth_cb_yes, imcb_ask_auth_cb_no, data );
     551}
     552
     553
     554static void imcb_ask_add_cb_no( void *data )
     555{
     556        g_free( ((struct imcb_ask_cb_data*)data)->handle );
    505557        g_free( data );
    506558}
    507559
    508 void show_got_added_yes( void *data )
    509 {
    510         struct show_got_added_data *sga = data;
    511        
    512         sga->ic->acc->prpl->add_buddy( sga->ic, sga->handle, NULL );
    513         /* imcb_add_buddy( sga->ic, NULL, sga->handle, sga->handle ); */
    514        
    515         return show_got_added_no( data );
    516 }
    517 
    518 void imcb_ask_add( struct im_connection *ic, char *handle, const char *realname )
    519 {
    520         struct show_got_added_data *data = g_new0( struct show_got_added_data, 1 );
     560static void imcb_ask_add_cb_yes( void *data )
     561{
     562        struct imcb_ask_cb_data *cbd = data;
     563       
     564        cbd->ic->acc->prpl->add_buddy( cbd->ic, cbd->handle, NULL );
     565       
     566        return imcb_ask_add_cb_no( data );
     567}
     568
     569void imcb_ask_add( struct im_connection *ic, const char *handle, const char *realname )
     570{
     571        struct imcb_ask_cb_data *data = g_new0( struct imcb_ask_cb_data, 1 );
    521572        char *s;
    522573       
     
    529580        data->ic = ic;
    530581        data->handle = g_strdup( handle );
    531         query_add( ic->irc, ic, s, show_got_added_yes, show_got_added_no, data );
     582        query_add( ic->irc, ic, s, imcb_ask_add_cb_yes, imcb_ask_add_cb_no, data );
    532583}
    533584
     
    699750}
    700751
    701 struct groupchat *imcb_chat_new( struct im_connection *ic, char *handle )
     752struct groupchat *imcb_chat_new( struct im_connection *ic, const char *handle )
    702753{
    703754        struct groupchat *c;
  • protocols/nogaim.h

    r0c41177 rc5bc47b  
    209209         * not implement this. */
    210210        struct groupchat *
    211              (* chat_join)      (struct im_connection *, char *room, char *nick, char *password);
     211             (* chat_join)      (struct im_connection *, const char *room, const char *nick, const char *password);
    212212        /* Change the topic, if supported. Note that BitlBee expects the IM
    213213           server to confirm the topic change with a regular topic change
     
    224224         * - Most protocols will just want to set this to g_strcasecmp().*/
    225225        int (* handle_cmp) (const char *who1, const char *who2);
     226
     227        /* Implement these callbacks if you want to use imcb_ask_auth() */
     228        void (* auth_allow)     (struct im_connection *, const char *who);
     229        void (* auth_deny)      (struct im_connection *, const char *who);
    226230};
    227231
     
    239243 * the account_t parameter. */
    240244G_MODULE_EXPORT struct im_connection *imcb_new( account_t *acc );
    241 G_MODULE_EXPORT void imcb_free( struct im_connection *ic );
     245G_MODULE_EXPORT void imc_free( struct im_connection *ic );
    242246/* Once you're connected, you should call this function, so that the user will
    243247 * see the success. */
     
    252256/* To tell the user an error, ie. before logging out when an error occurs. */
    253257G_MODULE_EXPORT void imcb_error( struct im_connection *ic, char *format, ... ) G_GNUC_PRINTF( 2, 3 );
     258
    254259/* To ask a your about something.
    255260 * - 'msg' is the question.
     
    258263 */
    259264G_MODULE_EXPORT void imcb_ask( struct im_connection *ic, char *msg, void *data, query_callback doit, query_callback dont );
    260 G_MODULE_EXPORT void imcb_ask_add( struct im_connection *ic, char *handle, const char *realname );
     265
     266/* Two common questions you may want to ask:
     267 * - X added you to his contact list, allow?
     268 * - X is not in your contact list, want to add?
     269 */
     270G_MODULE_EXPORT void imcb_ask_auth( struct im_connection *ic, const char *handle, const char *realname );
     271G_MODULE_EXPORT void imcb_ask_add( struct im_connection *ic, const char *handle, const char *realname );
    261272
    262273/* Buddy management */
     
    290301 *   the user her/himself. At that point the group chat will be visible to the
    291302 *   user, too. */
    292 G_MODULE_EXPORT struct groupchat *imcb_chat_new( struct im_connection *ic, char *handle );
     303G_MODULE_EXPORT struct groupchat *imcb_chat_new( struct im_connection *ic, const char *handle );
    293304G_MODULE_EXPORT void imcb_chat_add_buddy( struct groupchat *b, char *handle );
    294305/* To remove a handle from a group chat. Reason can be NULL. */
  • protocols/oscar/aim.h

    r0c41177 rc5bc47b  
    144144}
    145145
     146#define AIM_CLIENTINFO_KNOWNGOOD_5_1_3036 { \
     147        "AOL Instant Messenger, version 5.1.3036/WIN32", \
     148        0x0109, \
     149        0x0005, \
     150        0x0001, \
     151        0x0000, \
     152        0x0bdc, \
     153        "us", \
     154        "en", \
     155}
     156
    146157/*
    147158 * I would make 4.1.2010 the default, but they seem to have found
     
    152163 * around. (see login.c::memrequest())
    153164 */
    154 #define AIM_CLIENTINFO_KNOWNGOOD AIM_CLIENTINFO_KNOWNGOOD_3_5_1670
     165#define AIM_CLIENTINFO_KNOWNGOOD AIM_CLIENTINFO_KNOWNGOOD_5_1_3036
    155166
    156167#ifndef TRUE
  • protocols/oscar/oscar.c

    r0c41177 rc5bc47b  
    9191        GSList *oscar_chats;
    9292
    93         gboolean killme;
     93        gboolean killme, no_reconnect;
    9494        gboolean icq;
    9595        GSList *evilhack;
     
    181181static int gaim_parse_auth_resp  (aim_session_t *, aim_frame_t *, ...);
    182182static int gaim_parse_login      (aim_session_t *, aim_frame_t *, ...);
     183static int gaim_parse_logout     (aim_session_t *, aim_frame_t *, ...);
    183184static int gaim_handle_redirect  (aim_session_t *, aim_frame_t *, ...);
    184185static int gaim_parse_oncoming   (aim_session_t *, aim_frame_t *, ...);
     
    294295                        aim_rxdispatch(odata->sess);
    295296                               if (odata->killme)
    296                                        imc_logout(ic, TRUE);
     297                                       imc_logout(ic, !odata->no_reconnect);
    297298                } else {
    298299                        if ((conn->type == AIM_CONN_TYPE_BOS) ||
     
    520521                case 0x18:
    521522                        /* connecting too frequently */
     523                        od->no_reconnect = TRUE;
    522524                        imcb_error(ic, _("You have been connecting and disconnecting too frequently. Wait ten minutes and try again. If you continue to try, you will need to wait even longer."));
    523525                        break;
     
    572574        aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, gaim_parseaiminfo, 0);
    573575        aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MTN, gaim_parsemtn, 0);
     576        aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_parse_logout, 0);
    574577
    575578        ((struct oscar_data *)ic->proto_data)->conn = bosconn;
     
    747750
    748751        aim_send_login(sess, fr->conn, ic->acc->user, ic->acc->pass, &info, key);
     752
     753        return 1;
     754}
     755
     756static int gaim_parse_logout(aim_session_t *sess, aim_frame_t *fr, ...) {
     757        struct im_connection *ic = sess->aux_data;
     758        struct oscar_data *odata = ic->proto_data;
     759        int code;
     760        va_list ap;
     761
     762        va_start(ap, fr);
     763        code = va_arg(ap, int);
     764        va_end(ap);
     765       
     766        imcb_error( ic, "Connection aborted by server: %s", code == 1 ?
     767                        "someone else logged in with your account" :
     768                        "unknown reason" );
     769       
     770        /* Tell BitlBee to disable auto_reconnect if code == 1, since that
     771           means a concurrent login somewhere else. */
     772        odata->no_reconnect = code == 1;
     773       
     774        /* DO NOT log out here! Just tell the callback to do it. */
     775        odata->killme = TRUE;
    749776
    750777        return 1;
     
    19391966        aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL);
    19401967
    1941         if (ic->away)
    1942                 g_free(ic->away);
     1968        g_free(ic->away);
    19431969        ic->away = NULL;
    19441970
     
    19601986static void oscar_set_away_icq(struct im_connection *ic, struct oscar_data *od, const char *state, const char *message)
    19611987{
    1962     const char *msg = NULL;
     1988        const char *msg = NULL;
    19631989        gboolean no_message = FALSE;
    19641990
    19651991        /* clean old states */
    1966     if (ic->away) {
    1967                 g_free(ic->away);
    1968                 ic->away = NULL;
    1969     }
     1992        g_free(ic->away);
     1993        ic->away = NULL;
    19701994        od->sess->aim_icq_state = 0;
    19711995
    19721996        /* if no message, then use an empty message */
    1973     if (message) {
    1974         msg = message;
    1975     } else {
    1976         msg = "";
     1997        if (message) {
     1998                msg = message;
     1999        } else {
     2000                msg = "";
    19772001                no_message = TRUE;
    1978     }
     2002        }
    19792003
    19802004        if (!g_strcasecmp(state, "Online")) {
     
    19822006        } else if (!g_strcasecmp(state, "Away")) {
    19832007                aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_AWAY);
    1984         ic->away = g_strdup(msg);
     2008                ic->away = g_strdup(msg);
    19852009                od->sess->aim_icq_state = AIM_MTYPE_AUTOAWAY;
    19862010        } else if (!g_strcasecmp(state, "Do Not Disturb")) {
    19872011                aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_DND | AIM_ICQ_STATE_BUSY);
    1988         ic->away = g_strdup(msg);
     2012                ic->away = g_strdup(msg);
    19892013                od->sess->aim_icq_state = AIM_MTYPE_AUTODND;
    19902014        } else if (!g_strcasecmp(state, "Not Available")) {
    19912015                aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_OUT | AIM_ICQ_STATE_AWAY);
    1992         ic->away = g_strdup(msg);
     2016                ic->away = g_strdup(msg);
    19932017                od->sess->aim_icq_state = AIM_MTYPE_AUTONA;
    19942018        } else if (!g_strcasecmp(state, "Occupied")) {
    19952019                aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_BUSY);
    1996         ic->away = g_strdup(msg);
     2020                ic->away = g_strdup(msg);
    19972021                od->sess->aim_icq_state = AIM_MTYPE_AUTOBUSY;
    19982022        } else if (!g_strcasecmp(state, "Free For Chat")) {
    19992023                aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_CHAT);
    2000         ic->away = g_strdup(msg);
     2024                ic->away = g_strdup(msg);
    20012025                od->sess->aim_icq_state = AIM_MTYPE_AUTOFFC;
    20022026        } else if (!g_strcasecmp(state, "Invisible")) {
    20032027                aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_INVISIBLE);
    2004         ic->away = g_strdup(msg);
     2028                ic->away = g_strdup(msg);
    20052029        } else if (!g_strcasecmp(state, GAIM_AWAY_CUSTOM)) {
    20062030                if (no_message) {
     
    20082032                } else {
    20092033                        aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_AWAY);
    2010             ic->away = g_strdup(msg);
     2034                        ic->away = g_strdup(msg);
    20112035                        od->sess->aim_icq_state = AIM_MTYPE_AUTOAWAY;
    20122036                }
     
    20202044        struct oscar_data *od = (struct oscar_data *)ic->proto_data;
    20212045
    2022     oscar_set_away_aim(ic, od, state, message);
     2046        oscar_set_away_aim(ic, od, state, message);
    20232047        if (od->icq)
    20242048                oscar_set_away_icq(ic, od, state, message);
     
    25812605}
    25822606
    2583 struct groupchat *oscar_chat_join(struct im_connection * ic, char * room, char * nick, char * password )
     2607struct groupchat *oscar_chat_join(struct im_connection * ic, const char * room, const char * nick, const char * password )
    25842608{
    25852609        struct oscar_data * od = (struct oscar_data *)ic->proto_data;
  • protocols/yahoo/libyahoo2.c

    r0c41177 rc5bc47b  
    8989
    9090#include "base64.h"
     91#include "http_client.h"
    9192
    9293#ifdef USE_STRUCT_CALLBACKS
     
    169170        YAHOO_SERVICE_GOTGROUPRENAME, /* < 1, 36(old), 37(new) */
    170171        YAHOO_SERVICE_SYSMESSAGE = 0x14,
     172        YAHOO_SERVICE_SKINNAME = 0x15,
    171173        YAHOO_SERVICE_PASSTHROUGH2 = 0x16,
    172174        YAHOO_SERVICE_CONFINVITE = 0x18,
     
    192194        YAHOO_SERVICE_LIST,
    193195        YAHOO_SERVICE_AUTH = 0x57,
     196        YAHOO_SERVICE_AUTHBUDDY = 0x6d,
    194197        YAHOO_SERVICE_ADDBUDDY = 0x83,
    195198        YAHOO_SERVICE_REMBUDDY,
     
    197200        YAHOO_SERVICE_REJECTCONTACT,
    198201        YAHOO_SERVICE_GROUPRENAME = 0x89, /* > 1, 65(new), 66(0), 67(old) */
     202        YAHOO_SERVICE_Y7_PING = 0x8A, /* 0 - id and that's it?? */
    199203        YAHOO_SERVICE_CHATONLINE = 0x96, /* > 109(id), 1, 6(abcde) < 0,1*/
    200204        YAHOO_SERVICE_CHATGOTO,
     
    202206        YAHOO_SERVICE_CHATLEAVE,
    203207        YAHOO_SERVICE_CHATEXIT = 0x9b,
     208        YAHOO_SERVICE_CHATADDINVITE = 0x9d,
    204209        YAHOO_SERVICE_CHATLOGOUT = 0xa0,
    205210        YAHOO_SERVICE_CHATPING,
     
    209214        YAHOO_SERVICE_PICTURE = 0xbe,
    210215        YAHOO_SERVICE_PICTURE_UPDATE = 0xc1,
    211         YAHOO_SERVICE_PICTURE_UPLOAD = 0xc2
     216        YAHOO_SERVICE_PICTURE_UPLOAD = 0xc2,
     217        YAHOO_SERVICE_Y6_VISIBILITY=0xc5,
     218        YAHOO_SERVICE_Y6_STATUS_UPDATE=0xc6,
     219        YAHOO_PHOTOSHARE_INIT=0xd2,     
     220        YAHOO_SERVICE_CONTACT_YMSG13=0xd6,
     221        YAHOO_PHOTOSHARE_PREV=0xd7,
     222        YAHOO_PHOTOSHARE_KEY=0xd8,
     223        YAHOO_PHOTOSHARE_TRANS=0xda,
     224        YAHOO_FILE_TRANSFER_INIT_YMSG13=0xdc,
     225        YAHOO_FILE_TRANSFER_GET_YMSG13=0xdd,
     226        YAHOO_FILE_TRANSFER_PUT_YMSG13=0xde,
     227        YAHOO_SERVICE_YMSG15_STATUS=0xf0,
     228        YAHOO_SERVICE_YMSG15_BUDDY_LIST=0xf1,
    212229};
    213230
     
    733750
    734751        memcpy(data + pos, "YMSG", 4); pos += 4;
    735         pos += yahoo_put16(data + pos, 0x000c);
     752        pos += yahoo_put16(data + pos, YAHOO_PROTO_VER);
    736753        pos += yahoo_put16(data + pos, 0x0000);
    737754        pos += yahoo_put16(data + pos, pktlen + extra_pad);
     
    747764                yahoo_send_data(yid->fd, data, len);
    748765        else
    749         yahoo_add_to_send_queue(yid, data, len);
     766                yahoo_add_to_send_queue(yid, data, len);
    750767        FREE(data);
    751768}
     
    14671484
    14681485                if (u->name != NULL) {
    1469                         if (pkt->service == YAHOO_SERVICE_LOGOFF || u->flags == 0) {
     1486                        if (pkt->service == YAHOO_SERVICE_LOGOFF) { /* || u->flags == 0) { Not in YMSG16 */
    14701487                                YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, u->name, YAHOO_STATUS_OFFLINE, NULL, 1, 0, 0);
    14711488                        } else {
     1489                                /* Key 47 always seems to be 1 for YMSG16 */
     1490                                if(!u->state)
     1491                                        u->away = 0;
     1492                                else
     1493                                        u->away = 1;
     1494
    14721495                                YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, u->name, u->state, u->msg, u->away, u->idle, u->mobile);
    14731496                        }
     
    14771500                y_list_free_1(t);
    14781501                FREE(u);
     1502        }
     1503}
     1504
     1505static void yahoo_process_buddy_list(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
     1506{
     1507        struct yahoo_data *yd = yid->yd;
     1508        YList *l;
     1509        int last_packet = 0;
     1510        char *cur_group = NULL;
     1511        struct yahoo_buddy *newbud = NULL;
     1512
     1513        /* we could be getting multiple packets here */
     1514        for (l = pkt->hash; l; l = l->next) {
     1515                struct yahoo_pair *pair = l->data;
     1516
     1517                switch(pair->key) {
     1518                case 300:
     1519                case 301:
     1520                case 302:
     1521                case 303:
     1522                        if ( 315 == atoi(pair->value) )
     1523                                last_packet = 1;
     1524                        break;
     1525                case 65:
     1526                        g_free(cur_group);
     1527                        cur_group = strdup(pair->value);
     1528                        break;
     1529                case 7:
     1530                        newbud = y_new0(struct yahoo_buddy, 1);
     1531                        newbud->id = strdup(pair->value);
     1532                        if(cur_group)
     1533                                newbud->group = strdup(cur_group);
     1534                        else {
     1535                                struct yahoo_buddy *lastbud = (struct yahoo_buddy *)y_list_nth(
     1536                                                                yd->buddies, y_list_length(yd->buddies)-1)->data;
     1537                                newbud->group = strdup(lastbud->group);
     1538                        }
     1539
     1540                        yd->buddies = y_list_append(yd->buddies, newbud);
     1541
     1542                        break;
     1543                }
     1544        }
     1545       
     1546        g_free(cur_group);
     1547
     1548        /* we could be getting multiple packets here */
     1549        if (last_packet)
     1550                return;
     1551
     1552        YAHOO_CALLBACK(ext_yahoo_got_buddies)(yd->client_id, yd->buddies);
     1553
     1554        /*** We login at the very end of the packet communication */
     1555        if (!yd->logged_in) {
     1556                yd->logged_in = TRUE;
     1557                if(yd->current_status < 0)
     1558                        yd->current_status = yd->initial_status;
     1559                YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_OK, NULL);
    14791560        }
    14801561}
     
    15491630                        }
    15501631
    1551                         if(yd->cookie_y && yd->cookie_t && yd->cookie_c)
     1632                        if(yd->cookie_y && yd->cookie_t)
    15521633                                YAHOO_CALLBACK(ext_yahoo_got_cookies)(yd->client_id);
    15531634
     
    22262307}
    22272308
     2309struct yahoo_https_auth_data
     2310{
     2311        struct yahoo_input_data *yid;
     2312        char *token;
     2313        char *chal;
     2314};
     2315
     2316static void yahoo_https_auth_token_init(struct yahoo_https_auth_data *had);
     2317static void yahoo_https_auth_token_finish(struct http_request *req);
     2318static void yahoo_https_auth_init(struct yahoo_https_auth_data *had);
     2319static void yahoo_https_auth_finish(struct http_request *req);
     2320
     2321/* Extract a value from a login.yahoo.com response. Assume CRLF-linebreaks
     2322   and FAIL miserably if they're not there... */
     2323static char *yahoo_ha_find_key(char *response, char *key)
     2324{
     2325        char *s, *end;
     2326        int len = strlen(key);
     2327       
     2328        s = response;
     2329        do {
     2330                if (strncmp(s, key, len) == 0 && s[len] == '=') {
     2331                        s += len + 1;
     2332                        if ((end = strchr(s, '\r')))
     2333                                return g_strndup(s, end - s);
     2334                        else
     2335                                return g_strdup(s);
     2336                }
     2337               
     2338                if ((s = strchr(s, '\n')))
     2339                        s ++;
     2340        } while (s && *s);
     2341       
     2342        return NULL;
     2343}
     2344
     2345static enum yahoo_status yahoo_https_status_parse(int code)
     2346{
     2347        switch (code)
     2348        {
     2349                case 1212: return YAHOO_LOGIN_PASSWD;
     2350                case 1213: return YAHOO_LOGIN_LOCK;
     2351                case 1235: return YAHOO_LOGIN_UNAME;
     2352                default: return (enum yahoo_status) code;
     2353        }
     2354}
     2355
     2356static void yahoo_process_auth_0x10(struct yahoo_input_data *yid, const char *seed, const char *sn)
     2357{
     2358        struct yahoo_https_auth_data *had = g_new0(struct yahoo_https_auth_data, 1);
     2359       
     2360        had->yid = yid;
     2361        had->chal = g_strdup(seed);
     2362       
     2363        yahoo_https_auth_token_init(had);
     2364}
     2365
     2366static void yahoo_https_auth_token_init(struct yahoo_https_auth_data *had)
     2367{
     2368        struct yahoo_input_data *yid = had->yid;
     2369        struct yahoo_data *yd = yid->yd;
     2370        struct http_request *req;
     2371        char *login, *passwd, *chal;
     2372        char *url;
     2373       
     2374        login = g_strndup(yd->user, 3 * strlen(yd->user));
     2375        http_encode(login);
     2376        passwd = g_strndup(yd->password, 3 * strlen(yd->password));
     2377        http_encode(passwd);
     2378        chal = g_strndup(had->chal, 3 * strlen(had->chal));
     2379        http_encode(chal);
     2380       
     2381        url = g_strdup_printf("https://login.yahoo.com/config/pwtoken_get?src=ymsgr&ts=%d&login=%s&passwd=%s&chal=%s",
     2382                               (int) time(NULL), login, passwd, chal);
     2383       
     2384        req = http_dorequest_url(url, yahoo_https_auth_token_finish, had);
     2385       
     2386        g_free(url);
     2387        g_free(chal);
     2388        g_free(passwd);
     2389        g_free(login);
     2390}
     2391
     2392static void yahoo_https_auth_token_finish(struct http_request *req)
     2393{
     2394        struct yahoo_https_auth_data *had = req->data;
     2395        struct yahoo_input_data *yid = had->yid;
     2396        struct yahoo_data *yd = yid->yd;
     2397        int st;
     2398       
     2399        if (req->status_code != 200) {
     2400                YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, 2000 + req->status_code, NULL);
     2401                goto fail;
     2402        }
     2403       
     2404        if (sscanf(req->reply_body, "%d", &st) != 1 || st != 0) {
     2405                YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, yahoo_https_status_parse(st), NULL);
     2406                goto fail;
     2407        }
     2408       
     2409        if ((had->token = yahoo_ha_find_key(req->reply_body, "ymsgr")) == NULL) {
     2410                YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, 3001, NULL);
     2411                goto fail;
     2412        }
     2413       
     2414        return yahoo_https_auth_init(had);
     2415       
     2416fail:
     2417        g_free(had->token);
     2418        g_free(had->chal);
     2419        g_free(had);
     2420}
     2421
     2422static void yahoo_https_auth_init(struct yahoo_https_auth_data *had)
     2423{
     2424        struct http_request *req;
     2425        char *url;
     2426       
     2427        url = g_strdup_printf("https://login.yahoo.com/config/pwtoken_login?src=ymsgr&ts=%d&token=%s",
     2428                              (int) time(NULL), had->token);
     2429       
     2430        req = http_dorequest_url(url, yahoo_https_auth_finish, had);
     2431       
     2432        g_free(url);
     2433}
     2434
     2435static void yahoo_https_auth_finish(struct http_request *req)
     2436{
     2437        struct yahoo_https_auth_data *had = req->data;
     2438        struct yahoo_input_data *yid = had->yid;
     2439        struct yahoo_data *yd = yid->yd;
     2440        struct yahoo_packet *pack;
     2441        char *crumb;
     2442        int st;
     2443       
     2444        md5_byte_t result[16];
     2445        md5_state_t ctx;
     2446       
     2447        unsigned char yhash[32];
     2448
     2449        if (req->status_code != 200) {
     2450                YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, 2000 + req->status_code, NULL);
     2451                goto fail;
     2452        }
     2453       
     2454        if (sscanf(req->reply_body, "%d", &st) != 1 || st != 0) {
     2455                YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, yahoo_https_status_parse(st), NULL);
     2456                goto fail;
     2457        }
     2458       
     2459        if ((yd->cookie_y = yahoo_ha_find_key(req->reply_body, "Y")) == NULL ||
     2460            (yd->cookie_t = yahoo_ha_find_key(req->reply_body, "T")) == NULL ||
     2461            (crumb = yahoo_ha_find_key(req->reply_body, "crumb")) == NULL) {
     2462                YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, 3002, NULL);
     2463                goto fail;
     2464        }
     2465       
     2466        md5_init(&ctx); 
     2467        md5_append(&ctx, (unsigned char*) crumb, 11);
     2468        md5_append(&ctx, (unsigned char*) had->chal, strlen(had->chal));
     2469        md5_finish(&ctx, result);
     2470        to_y64(yhash, result, 16);
     2471
     2472        pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, yd->initial_status, yd->session_id);
     2473        yahoo_packet_hash(pack, 1, yd->user);
     2474        yahoo_packet_hash(pack, 0, yd->user);
     2475        yahoo_packet_hash(pack, 277, yd->cookie_y);
     2476        yahoo_packet_hash(pack, 278, yd->cookie_t);
     2477        yahoo_packet_hash(pack, 307, (char*) yhash);
     2478        yahoo_packet_hash(pack, 244, "524223");
     2479        yahoo_packet_hash(pack, 2, yd->user);
     2480        yahoo_packet_hash(pack, 2, "1");
     2481        yahoo_packet_hash(pack, 98, "us");
     2482        yahoo_packet_hash(pack, 135, "7.5.0.647");
     2483       
     2484        yahoo_send_packet(yid, pack, 0);
     2485               
     2486        yahoo_packet_free(pack);
     2487       
     2488fail:
     2489        g_free(crumb);
     2490        g_free(had->token);
     2491        g_free(had->chal);
     2492        g_free(had);
     2493}
     2494
    22282495static void yahoo_process_auth(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
    22292496{
     
    22532520                case 1:
    22542521                        yahoo_process_auth_0x0b(yid, seed, sn);
     2522                        break;
     2523                case 2:
     2524                        yahoo_process_auth_0x10(yid, seed, sn);
    22552525                        break;
    22562526                default:
     
    24082678               
    24092679                yd->buddies = y_list_append(yd->buddies, bud);
    2410                
     2680       
    24112681                /* Possibly called already, but at least the call above doesn't
    24122682                   seem to happen every time (not anytime I tried). */
     
    24152685
    24162686/*      YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, who, status, NULL, (status==YAHOO_STATUS_AVAILABLE?0:1)); */
     2687}
     2688
     2689static void yahoo_process_contact_ymsg13(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
     2690{
     2691        char* who=NULL;
     2692        char* me=NULL; 
     2693        char* msg=NULL;
     2694        YList *l;
     2695        for (l = pkt->hash; l; l = l->next) {
     2696                struct yahoo_pair *pair = l->data;
     2697                if (pair->key == 4)
     2698                        who = pair->value;
     2699                else if (pair->key == 5)
     2700                        me = pair->value;
     2701                else
     2702                        DEBUG_MSG(("unknown key: %d = %s", pair->key, pair->value));
     2703        }
     2704
     2705        if(pkt->status==3)
     2706                YAHOO_CALLBACK(ext_yahoo_contact_auth_request)(yid->yd->client_id, me, who, msg);
    24172707}
    24182708
     
    26282918
    26292919        YList *l;
    2630         yahoo_dump_unhandled(pkt);
     2920        // yahoo_dump_unhandled(pkt);
    26312921        for (l = pkt->hash; l; l = l->next) {
    26322922                struct yahoo_pair *pair = l->data;
     
    26502940{
    26512941        DEBUG_MSG(("yahoo_packet_process: 0x%02x", pkt->service));
     2942        yahoo_dump_unhandled(pkt);
    26522943        switch (pkt->service)
    26532944        {
     
    26612952        case YAHOO_SERVICE_IDACT:
    26622953        case YAHOO_SERVICE_IDDEACT:
     2954        case YAHOO_SERVICE_Y6_STATUS_UPDATE:
     2955        case YAHOO_SERVICE_YMSG15_STATUS:
    26632956                yahoo_process_status(yid, pkt);
    26642957                break;
     
    26742967                yahoo_process_mail(yid, pkt);
    26752968                break;
     2969        case YAHOO_SERVICE_REJECTCONTACT:
    26762970        case YAHOO_SERVICE_NEWCONTACT:
    26772971                yahoo_process_contact(yid, pkt);
     
    27143008                yahoo_process_buddyadd(yid, pkt);
    27153009                break;
     3010        case YAHOO_SERVICE_CONTACT_YMSG13:
     3011                yahoo_process_contact_ymsg13(yid,pkt);
     3012                break;
    27163013        case YAHOO_SERVICE_REMBUDDY:
    27173014                yahoo_process_buddydel(yid, pkt);
     
    27423039        case YAHOO_SERVICE_CHATLOGOFF:
    27433040        case YAHOO_SERVICE_CHATMSG:
    2744         case YAHOO_SERVICE_REJECTCONTACT:
    27453041        case YAHOO_SERVICE_PEERTOPEER:
    27463042                WARNING(("unhandled service 0x%02x", pkt->service));
     
    27563052                yahoo_process_picture_upload(yid, pkt);
    27573053                break; 
     3054        case YAHOO_SERVICE_YMSG15_BUDDY_LIST:   /* Buddy List */
     3055                yahoo_process_buddy_list(yid, pkt);
    27583056        default:
    27593057                WARNING(("unknown service 0x%02x", pkt->service));
     
    35393837        yahoo_process_webcam_connection,
    35403838        yahoo_process_chatcat_connection,
    3541         yahoo_process_search_connection
     3839        yahoo_process_search_connection,
    35423840};
    35433841
     
    35573855        } while(len == -1 && errno == EINTR);
    35583856
    3559         if(len == -1 && errno == EAGAIN)        /* we'll try again later */
     3857        if(len == -1 && (errno == EAGAIN||errno == EINTR))      /* we'll try again later */
    35603858                return 1;
    35613859
     
    37604058
    37614059        yahoo_packet_hash(pkt, 5, who);
    3762         yahoo_packet_hash(pkt, 4, from?from:yd->user);
     4060        yahoo_packet_hash(pkt, 1, from?from:yd->user);
    37634061        yahoo_packet_hash(pkt, 14, " ");
    37644062        yahoo_packet_hash(pkt, 13, typ ? "1" : "0");
     
    37754073        struct yahoo_data *yd;
    37764074        struct yahoo_packet *pkt = NULL;
    3777         int service;
     4075        int old_status;
    37784076        char s[4];
    37794077
     
    37834081        yd = yid->yd;
    37844082
    3785         if (msg) {
     4083        old_status = yd->current_status;
     4084
     4085        if (msg && strncmp(msg,"Invisible",9)) {
    37864086                yd->current_status = YAHOO_STATUS_CUSTOM;
    37874087        } else {
     
    37894089        }
    37904090
    3791         if (yd->current_status == YAHOO_STATUS_AVAILABLE)
    3792                 service = YAHOO_SERVICE_ISBACK;
    3793         else
    3794                 service = YAHOO_SERVICE_ISAWAY;
     4091        /* Thank you libpurple :) */
     4092        if (yd->current_status == YAHOO_STATUS_INVISIBLE) {
     4093                pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_VISIBILITY, YAHOO_STATUS_AVAILABLE, 0);
     4094                yahoo_packet_hash(pkt, 13, "2");
     4095                yahoo_send_packet(yid, pkt, 0);
     4096                yahoo_packet_free(pkt);
     4097
     4098                return;
     4099        }
     4100
     4101        pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_STATUS_UPDATE, yd->current_status, yd->session_id);
     4102        snprintf(s, sizeof(s), "%d", yd->current_status);
     4103        yahoo_packet_hash(pkt, 10, s);
    37954104         
    3796         if ((away == 2) && (yd->current_status == YAHOO_STATUS_AVAILABLE)) {
    3797                 pkt = yahoo_packet_new(YAHOO_SERVICE_ISAWAY, YAHOO_STATUS_BRB, yd->session_id);
    3798                 yahoo_packet_hash(pkt, 10, "999");
    3799                 yahoo_packet_hash(pkt, 47, "2");
    3800         }else {
    3801                 pkt = yahoo_packet_new(service, YAHOO_STATUS_AVAILABLE, yd->session_id);
    3802                 snprintf(s, sizeof(s), "%d", yd->current_status);
    3803                 yahoo_packet_hash(pkt, 10, s);
    3804                 if (yd->current_status == YAHOO_STATUS_CUSTOM) {
    3805                         yahoo_packet_hash(pkt, 19, msg);
    3806                         yahoo_packet_hash(pkt, 47, (away == 2)? "2": (away) ?"1":"0");
    3807                 } else {
    3808                         yahoo_packet_hash(pkt, 47, (away == 2)? "2": (away) ?"1":"0");
    3809                 }
    3810                
    3811                
    3812                
    3813         }
     4105        if (yd->current_status == YAHOO_STATUS_CUSTOM) {
     4106                yahoo_packet_hash(pkt, 19, msg);
     4107        } else {
     4108                yahoo_packet_hash(pkt, 19, "");
     4109        }
     4110       
     4111        yahoo_packet_hash(pkt, 47, (away == 2)? "2": (away) ?"1":"0");
    38144112
    38154113        yahoo_send_packet(yid, pkt, 0);
    38164114        yahoo_packet_free(pkt);
     4115
     4116        if(old_status == YAHOO_STATUS_INVISIBLE) {
     4117                pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_VISIBILITY, YAHOO_STATUS_AVAILABLE, 0);
     4118                yahoo_packet_hash(pkt, 13, "1");
     4119                yahoo_send_packet(yid, pkt, 0);
     4120                yahoo_packet_free(pkt);
     4121        }
    38174122}
    38184123
     
    38294134        LOG(("yahoo_logoff: current status: %d", yd->current_status));
    38304135
    3831         if(yd->current_status != -1) {
     4136        if(yd->current_status != -1 && 0) {
     4137                /* Meh. Don't send this. The event handlers are not going to
     4138                   get to do this so it'll just leak memory. And the TCP
     4139                   connection reset will hopefully be clear enough. */
    38324140                pkt = yahoo_packet_new(YAHOO_SERVICE_LOGOFF, YAHOO_STATUS_AVAILABLE, yd->session_id);
    38334141                yd->current_status = -1;
     
    40624370                return;
    40634371
    4064         pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YAHOO_STATUS_AVAILABLE, yd->session_id);
    4065         yahoo_packet_hash(pkt, 1, yd->user);
    4066         yahoo_packet_hash(pkt, 7, who);
    4067         yahoo_packet_hash(pkt, 65, group);
     4372        pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YPACKET_STATUS_DEFAULT, yd->session_id);
     4373
    40684374        if (msg != NULL) /* add message/request "it's me add me" */
    40694375                yahoo_packet_hash(pkt, 14, msg);
     4376        else
     4377                yahoo_packet_hash(pkt,14,"");
     4378
     4379        yahoo_packet_hash(pkt, 65, group);
     4380        yahoo_packet_hash(pkt, 97, "1");
     4381        yahoo_packet_hash(pkt, 1, yd->user);
     4382        yahoo_packet_hash(pkt, 302, "319");
     4383        yahoo_packet_hash(pkt, 300, "319");
     4384        yahoo_packet_hash(pkt, 7, who);
     4385        yahoo_packet_hash(pkt, 334, "0");
     4386        yahoo_packet_hash(pkt, 301, "319");
     4387        yahoo_packet_hash(pkt, 303, "319");
     4388
     4389
    40704390        yahoo_send_packet(yid, pkt, 0);
    40714391        yahoo_packet_free(pkt);
     
    40894409        yahoo_send_packet(yid, pkt, 0);
    40904410        yahoo_packet_free(pkt);
     4411}
     4412
     4413void yahoo_accept_buddy_ymsg13(int id,const char* me,const char* who){
     4414        struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
     4415        struct yahoo_data *yd;
     4416
     4417        if(!yid)
     4418                return;
     4419        yd = yid->yd;
     4420
     4421        struct yahoo_packet* pkt=NULL;
     4422        pkt= yahoo_packet_new(YAHOO_SERVICE_CONTACT_YMSG13,YAHOO_STATUS_AVAILABLE,0);
     4423
     4424        yahoo_packet_hash(pkt,1,me ?: yd->user);       
     4425        yahoo_packet_hash(pkt,5,who);
     4426        yahoo_packet_hash(pkt,13,"1");
     4427        yahoo_packet_hash(pkt,334,"0");
     4428        yahoo_send_packet(yid, pkt, 0);
     4429        yahoo_packet_free(pkt);
     4430}
     4431
     4432void yahoo_reject_buddy_ymsg13(int id,const char* me,const char* who,const char* msg){
     4433        struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
     4434        struct yahoo_data *yd;
     4435
     4436        if(!yid)
     4437                return;
     4438        yd = yid->yd;
     4439
     4440        struct yahoo_packet* pkt=NULL;
     4441        pkt= yahoo_packet_new(YAHOO_SERVICE_CONTACT_YMSG13,YAHOO_STATUS_AVAILABLE,0);
     4442
     4443        yahoo_packet_hash(pkt,1,me ?: yd->user);       
     4444        yahoo_packet_hash(pkt,5,who);
     4445//      yahoo_packet_hash(pkt,241,YAHOO_PROTO_VER);
     4446        yahoo_packet_hash(pkt,13,"2");
     4447        yahoo_packet_hash(pkt,334,"0");
     4448        yahoo_packet_hash(pkt,97,"1");
     4449        yahoo_packet_hash(pkt,14,msg?:"");
     4450
     4451        yahoo_send_packet(yid, pkt, 0);
     4452        yahoo_packet_free(pkt);
     4453
    40914454}
    40924455
  • protocols/yahoo/yahoo.c

    r0c41177 rc5bc47b  
    197197{
    198198        struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data;
    199        
    200         ic->away = NULL;
     199        char *away;
     200       
     201        away = NULL;
    201202       
    202203        if( state && msg && g_strcasecmp( state, msg ) != 0 )
    203204        {
    204205                yd->current_status = YAHOO_STATUS_CUSTOM;
    205                 ic->away = "";
     206                away = "";
    206207        }
    207208        else if( state )
     
    212213                msg = NULL;
    213214               
    214                 ic->away = "";
     215                away = "";
    215216                if( g_strcasecmp( state, "Available" ) == 0 )
    216217                {
    217218                        yd->current_status = YAHOO_STATUS_AVAILABLE;
    218                         ic->away = NULL;
     219                        away = NULL;
    219220                }
    220221                else if( g_strcasecmp( state, "Be Right Back" ) == 0 )
     
    242243                        yd->current_status = YAHOO_STATUS_AVAILABLE;
    243244                       
    244                         ic->away = NULL;
     245                        away = NULL;
    245246                }
    246247        }
     
    248249                yd->current_status = YAHOO_STATUS_AVAILABLE;
    249250       
    250         yahoo_set_away( yd->y2_id, yd->current_status, msg, ic->away != NULL ? 2 : 0 );
     251        yahoo_set_away( yd->y2_id, yd->current_status, msg, away != NULL ? 2 : 0 );
    251252}
    252253
    253254static GList *byahoo_away_states( struct im_connection *ic )
    254255{
    255         GList *m = NULL;
    256 
    257         m = g_list_append( m, "Available" );
    258         m = g_list_append( m, "Be Right Back" );
    259         m = g_list_append( m, "Busy" );
    260         m = g_list_append( m, "Not At Home" );
    261         m = g_list_append( m, "Not At Desk" );
    262         m = g_list_append( m, "Not In Office" );
    263         m = g_list_append( m, "On Phone" );
    264         m = g_list_append( m, "On Vacation" );
    265         m = g_list_append( m, "Out To Lunch" );
    266         m = g_list_append( m, "Stepped Out" );
    267         m = g_list_append( m, "Invisible" );
    268         m = g_list_append( m, GAIM_AWAY_CUSTOM );
     256        static GList *m = NULL;
     257
     258        if( m == NULL )
     259        {
     260                m = g_list_append( m, "Available" );
     261                m = g_list_append( m, "Be Right Back" );
     262                m = g_list_append( m, "Busy" );
     263                m = g_list_append( m, "Not At Home" );
     264                m = g_list_append( m, "Not At Desk" );
     265                m = g_list_append( m, "Not In Office" );
     266                m = g_list_append( m, "On Phone" );
     267                m = g_list_append( m, "On Vacation" );
     268                m = g_list_append( m, "Out To Lunch" );
     269                m = g_list_append( m, "Stepped Out" );
     270                m = g_list_append( m, "Invisible" );
     271                m = g_list_append( m, GAIM_AWAY_CUSTOM );
     272        }
    269273       
    270274        return m;
     
    345349       
    346350        return c;
     351}
     352
     353static void byahoo_auth_allow( struct im_connection *ic, const char *who )
     354{
     355        struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data;
     356       
     357        yahoo_accept_buddy_ymsg13( yd->y2_id, NULL, who );
     358}
     359
     360static void byahoo_auth_deny( struct im_connection *ic, const char *who )
     361{
     362        struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data;
     363       
     364        yahoo_reject_buddy_ymsg13( yd->y2_id, NULL, who, NULL );
    347365}
    348366
     
    372390        ret->handle_cmp = g_strcasecmp;
    373391       
     392        ret->auth_allow = byahoo_auth_allow;
     393        ret->auth_deny = byahoo_auth_deny;
     394       
    374395        register_protocol(ret);
    375396}
     
    451472        struct byahoo_write_ready_data *d = data;
    452473       
    453         yahoo_write_ready( d->id, d->fd, d->data );
    454        
    455         return FALSE;
     474        return yahoo_write_ready( d->id, d->fd, d->data );
    456475}
    457476
     
    790809{
    791810        struct byahoo_conf_invitation *inv = data;
    792        
    793         yahoo_conference_logon( inv->yid, NULL, inv->members, inv->name );
    794         imcb_chat_add_buddy( inv->c, inv->ic->acc->user );
     811        struct groupchat *b;
     812       
     813        for( b = inv->ic->groupchats; b; b = b->next )
     814                if( b == inv->c )
     815                        break;
     816       
     817        if( b != NULL )
     818        {
     819                yahoo_conference_logon( inv->yid, NULL, inv->members, inv->name );
     820                imcb_chat_add_buddy( inv->c, inv->ic->acc->user );
     821        }
     822        else
     823        {
     824                imcb_log( inv->ic, "Duplicate/corrupted invitation to `%s'.", inv->name );
     825        }
     826       
    795827        g_free( inv->name );
    796828        g_free( inv );
     
    908940}
    909941
     942void ext_yahoo_contact_auth_request( int id, const char *myid, const char *who, const char *msg )
     943{
     944        struct im_connection *ic = byahoo_get_ic_by_id( id );
     945       
     946        imcb_ask_auth( ic, who, NULL );
     947}
     948
    910949void ext_yahoo_contact_added( int id, const char *myid, const char *who, const char *msg )
    911950{
    912         /* Groups schmoups. If I want to handle groups properly I can get the
    913            buddy data from some internal libyahoo2 structure. */
    914         imcb_add_buddy( byahoo_get_ic_by_id( id ), (char*) who, NULL );
     951        struct im_connection *ic = byahoo_get_ic_by_id( id );
     952       
     953        imcb_add_buddy( ic, (char*) who, NULL );
    915954}
    916955
  • protocols/yahoo/yahoo2.h

    r0c41177 rc5bc47b  
    217217void yahoo_buddyicon_request(int id, const char *who);
    218218
     219void yahoo_accept_buddy_ymsg13(int,const char*,const char*);
     220void yahoo_reject_buddy_ymsg13(int,const char*,const char*,const char*);
     221
    219222#include "yahoo_httplib.h"
    220223
  • protocols/yahoo/yahoo2_callbacks.h

    r0c41177 rc5bc47b  
    361361
    362362/*
     363 * Name: ext_yahoo_contact_auth_request
     364 *      Called when a contact wants to add you to his/her contact list
     365 * Params:
     366 *      id   - the id that identifies the server connection
     367 *      myid - the identity s/he added
     368 *      who  - who did it
     369 *      msg  - any message sent
     370 */
     371void YAHOO_CALLBACK_TYPE(ext_yahoo_contact_auth_request)(int id, const char *myid, const char *who, const char *msg);
     372
     373
     374/*
    363375 * Name: ext_yahoo_contact_added
    364376 *      Called when a contact is added to your list
  • protocols/yahoo/yahoo2_types.h

    r0c41177 rc5bc47b  
    5757        YAHOO_LOGIN_LOCK = 14,
    5858        YAHOO_LOGIN_DUPL = 99,
    59         YAHOO_LOGIN_SOCK = -1
     59        YAHOO_LOGIN_SOCK = -1,
     60};
     61
     62enum ypacket_status {
     63        YPACKET_STATUS_DISCONNECTED = -1,
     64        YPACKET_STATUS_DEFAULT = 0,
     65        YPACKET_STATUS_SERVERACK = 1,
     66        YPACKET_STATUS_GAME     = 0x2,
     67        YPACKET_STATUS_AWAY     = 0x4,
     68        YPACKET_STATUS_CONTINUED = 0x5,
     69        YPACKET_STATUS_INVISIBLE = 12,
     70        YPACKET_STATUS_NOTIFY = 0x16, /* TYPING */
     71        YPACKET_STATUS_WEBLOGIN = 0x5a55aa55,
     72        YPACKET_STATUS_OFFLINE = 0x5a55aa56
    6073};
    6174
     
    8598};
    8699
    87 #define YAHOO_PROTO_VER 0x000b
     100#define YAHOO_PROTO_VER 0x0010
    88101
    89102/* Yahoo style/color directives */
     
    115128        YAHOO_CONNECTION_WEBCAM,
    116129        YAHOO_CONNECTION_CHATCAT,
    117         YAHOO_CONNECTION_SEARCH
     130        YAHOO_CONNECTION_SEARCH,
     131        YAHOO_CONNECTION_AUTH,
    118132};
    119133
     
    131145/* chat member attribs */
    132146#define YAHOO_CHAT_MALE 0x8000
    133 #define YAHOO_CHAT_FEMALE 0x10000
    134147#define YAHOO_CHAT_FEMALE 0x10000
    135148#define YAHOO_CHAT_DUNNO 0x400
  • root_commands.c

    r0c41177 rc5bc47b  
    7878}
    7979
     80#define MIN_ARGS( x, y... )                                                    \
     81        do                                                                     \
     82        {                                                                      \
     83                int blaat;                                                     \
     84                for( blaat = 0; blaat <= x; blaat ++ )                         \
     85                        if( cmd[blaat] == NULL )                               \
     86                        {                                                      \
     87                                irc_usermsg( irc, "Not enough parameters given (need %d).", x ); \
     88                                return y;                                      \
     89                        }                                                      \
     90        } while( 0 )
     91
    8092void root_command( irc_t *irc, char *cmd[] )
    8193{       
     
    88100                if( g_strcasecmp( commands[i].command, cmd[0] ) == 0 )
    89101                {
    90                         if( !cmd[commands[i].required_parameters] )
    91                         {
    92                                 irc_usermsg( irc, "Not enough parameters given (need %d)", commands[i].required_parameters );
    93                                 return;
    94                         }
     102                        MIN_ARGS( commands[i].required_parameters );
     103                       
    95104                        commands[i].execute( irc, cmd );
    96105                        return;
     
    250259}
    251260
     261typedef set_t** (*cmd_set_findhead)( irc_t*, char* );
     262typedef int (*cmd_set_checkflags)( irc_t*, set_t *set );
     263
     264static int cmd_set_real( irc_t *irc, char **cmd, cmd_set_findhead findhead, cmd_set_checkflags checkflags )
     265{
     266        char *set_full = NULL, *set_name = NULL, *tmp;
     267        set_t **head;
     268       
     269        if( cmd[1] && g_strncasecmp( cmd[1], "-del", 4 ) == 0 )
     270        {
     271                MIN_ARGS( 2, 0 );
     272                set_full = cmd[2];
     273        }
     274        else
     275                set_full = cmd[1];
     276       
     277        if( findhead == NULL )
     278        {
     279                set_name = set_full;
     280               
     281                head = &irc->set;
     282        }
     283        else
     284        {
     285                char *id;
     286               
     287                if( ( tmp = strchr( set_full, '/' ) ) )
     288                {
     289                        id = g_strndup( set_full, ( tmp - set_full ) );
     290                        set_name = tmp + 1;
     291                }
     292                else
     293                {
     294                        id = g_strdup( set_full );
     295                }
     296               
     297                if( ( head = findhead( irc, id ) ) == NULL )
     298                {
     299                        g_free( id );
     300                        irc_usermsg( irc, "Could not find setting." );
     301                        return 0;
     302                }
     303                g_free( id );
     304        }
     305       
     306        if( cmd[1] && cmd[2] && set_name )
     307        {
     308                set_t *s = set_find( head, set_name );
     309                int st;
     310               
     311                if( s && checkflags && checkflags( irc, s ) == 0 )
     312                        return 0;
     313               
     314                if( g_strncasecmp( cmd[1], "-del", 4 ) == 0 )
     315                        st = set_reset( head, set_name );
     316                else
     317                        st = set_setstr( head, set_name, cmd[2] );
     318               
     319                if( set_getstr( head, set_name ) == NULL )
     320                {
     321                        if( st )
     322                                irc_usermsg( irc, "Setting changed successfully" );
     323                        else
     324                                irc_usermsg( irc, "Failed to change setting" );
     325                }
     326                else
     327                {
     328                        cmd_showset( irc, head, set_name );
     329                }
     330        }
     331        else if( set_name )
     332        {
     333                cmd_showset( irc, head, set_name );
     334        }
     335        else
     336        {
     337                set_t *s = *head;
     338                while( s )
     339                {
     340                        cmd_showset( irc, &s, s->key );
     341                        s = s->next;
     342                }
     343        }
     344       
     345        return 1;
     346}
     347
     348static set_t **cmd_account_set_findhead( irc_t *irc, char *id )
     349{
     350        account_t *a;
     351       
     352        if( ( a = account_get( irc, id ) ) )
     353                return &a->set;
     354        else
     355                return NULL;
     356}
     357
     358static int cmd_account_set_checkflags( irc_t *irc, set_t *s )
     359{
     360        account_t *a = s->data;
     361       
     362        if( a->ic && s && s->flags & ACC_SET_OFFLINE_ONLY )
     363        {
     364                irc_usermsg( irc, "This setting can only be changed when the account is %s-line", "off" );
     365                return 0;
     366        }
     367        else if( !a->ic && s && s->flags & ACC_SET_ONLINE_ONLY )
     368        {
     369                irc_usermsg( irc, "This setting can only be changed when the account is %s-line", "on" );
     370                return 0;
     371        }
     372       
     373        return 1;
     374}
     375
    252376static void cmd_account( irc_t *irc, char **cmd )
    253377{
     
    264388                struct prpl *prpl;
    265389               
    266                 if( cmd[2] == NULL || cmd[3] == NULL || cmd[4] == NULL )
    267                 {
    268                         irc_usermsg( irc, "Not enough parameters" );
    269                         return;
    270                 }
    271                
    272                 prpl = find_protocol(cmd[2]);
     390                MIN_ARGS( 4 );
     391               
     392                prpl = find_protocol( cmd[2] );
    273393               
    274394                if( prpl == NULL )
     
    290410        else if( g_strcasecmp( cmd[1], "del" ) == 0 )
    291411        {
    292                 if( !cmd[2] )
    293                 {
    294                         irc_usermsg( irc, "Not enough parameters given (need %d)", 2 );
    295                 }
    296                 else if( !( a = account_get( irc, cmd[2] ) ) )
     412                MIN_ARGS( 2 );
     413
     414                if( !( a = account_get( irc, cmd[2] ) ) )
    297415                {
    298416                        irc_usermsg( irc, "Invalid account" );
     
    422540        else if( g_strcasecmp( cmd[1], "set" ) == 0 )
    423541        {
    424                 char *acc_handle, *set_name = NULL, *tmp;
    425                
    426                 if( !cmd[2] )
    427                 {
    428                         irc_usermsg( irc, "Not enough parameters given (need %d)", 2 );
    429                         return;
    430                 }
    431                
    432                 if( g_strncasecmp( cmd[2], "-del", 4 ) == 0 )
    433                         acc_handle = g_strdup( cmd[3] );
    434                 else
    435                         acc_handle = g_strdup( cmd[2] );
    436                
    437                 if( !acc_handle )
    438                 {
    439                         irc_usermsg( irc, "Not enough parameters given (need %d)", 3 );
    440                         return;
    441                 }
    442                
    443                 if( ( tmp = strchr( acc_handle, '/' ) ) )
    444                 {
    445                         *tmp = 0;
    446                         set_name = tmp + 1;
    447                 }
    448                
    449                 if( ( a = account_get( irc, acc_handle ) ) == NULL )
    450                 {
    451                         g_free( acc_handle );
    452                         irc_usermsg( irc, "Invalid account" );
    453                         return;
    454                 }
    455                
    456                 if( cmd[3] && set_name )
    457                 {
    458                         set_t *s = set_find( &a->set, set_name );
    459                         int st;
    460                        
    461                         if( a->ic && s && s->flags & ACC_SET_OFFLINE_ONLY )
    462                         {
    463                                 g_free( acc_handle );
    464                                 irc_usermsg( irc, "This setting can only be changed when the account is %s-line", "off" );
    465                                 return;
    466                         }
    467                         else if( !a->ic && s && s->flags & ACC_SET_ONLINE_ONLY )
    468                         {
    469                                 g_free( acc_handle );
    470                                 irc_usermsg( irc, "This setting can only be changed when the account is %s-line", "on" );
    471                                 return;
    472                         }
    473                        
    474                         if( g_strncasecmp( cmd[2], "-del", 4 ) == 0 )
    475                                 st = set_reset( &a->set, set_name );
    476                         else
    477                                 st = set_setstr( &a->set, set_name, cmd[3] );
    478                        
    479                         if( set_getstr( &a->set, set_name ) == NULL )
    480                         {
    481                                 if( st )
    482                                         irc_usermsg( irc, "Setting changed successfully" );
    483                                 else
    484                                         irc_usermsg( irc, "Failed to change setting" );
    485                         }
    486                         else
    487                         {
    488                                 cmd_showset( irc, &a->set, set_name );
    489                         }
    490                 }
    491                 else if( set_name )
    492                 {
    493                         cmd_showset( irc, &a->set, set_name );
    494                 }
    495                 else
    496                 {
    497                         set_t *s = a->set;
    498                         while( s )
    499                         {
    500                                 cmd_showset( irc, &s, s->key );
    501                                 s = s->next;
    502                         }
    503                 }
    504                
    505                 g_free( acc_handle );
    506         }
    507         else
    508         {
    509                 irc_usermsg( irc, "Unknown command: account %s. Please use \x02help commands\x02 to get a list of available commands.", cmd[1] );
     542                MIN_ARGS( 2 );
     543               
     544                cmd_set_real( irc, cmd + 1, cmd_account_set_findhead, cmd_account_set_checkflags );
     545        }
     546        else
     547        {
     548                irc_usermsg( irc, "Unknown command: %s %s. Please use \x02help commands\x02 to get a list of available commands.", "account", cmd[1] );
    510549        }
    511550}
     
    518557        if( g_strcasecmp( cmd[1], "-tmp" ) == 0 )
    519558        {
     559                MIN_ARGS( 3 );
    520560                add_on_server = 0;
    521561                cmd ++;
     
    837877static void cmd_set( irc_t *irc, char **cmd )
    838878{
    839         char *set_name = cmd[1];
    840        
    841         if( cmd[1] && cmd[2] )
    842         {
    843                 int st;
    844                
    845                 if( g_strncasecmp( cmd[1], "-del", 4 ) == 0 )
    846                 {
    847                         st = set_reset( &irc->set, cmd[2] );
    848                         set_name = cmd[2];
    849                 }
    850                 else
    851                 {
    852                         st = set_setstr( &irc->set, cmd[1], cmd[2] );
    853                 }
    854                
    855                 /* Normally we just show the variable's new/unchanged
    856                    value as feedback to the user, but this has always
    857                    caused confusion when changing the password. Give
    858                    other feedback instead: */
    859                 if( set_getstr( &irc->set, set_name ) == NULL )
    860                 {
    861                         if( st )
    862                                 irc_usermsg( irc, "Setting changed successfully" );
    863                         else
    864                                 irc_usermsg( irc, "Failed to change setting" );
    865                 }
    866                 else
    867                 {
    868                         cmd_showset( irc, &irc->set, set_name );
    869                 }
    870         }
    871         else if( set_name )
    872         {
    873                 cmd_showset( irc, &irc->set, set_name );
    874 
    875                 if( strchr( set_name, '/' ) )
    876                         irc_usermsg( irc, "Warning: / found in setting name, you're probably looking for the `account set' command." );
    877         }
    878         else
    879         {
    880                 set_t *s = irc->set;
    881                 while( s )
    882                 {
    883                         cmd_showset( irc, &s, s->key );
    884                         s = s->next;
    885                 }
    886         }
     879        cmd_set_real( irc, cmd, NULL, NULL );
    887880}
    888881
     
    10071000static void cmd_join_chat( irc_t *irc, char **cmd )
    10081001{
     1002        irc_usermsg( irc, "This command is now obsolete. "
     1003                          "Please try the `chat' command instead." );
     1004}
     1005
     1006static set_t **cmd_chat_set_findhead( irc_t *irc, char *id )
     1007{
     1008        struct chat *c;
     1009       
     1010        if( ( c = chat_get( irc, id ) ) )
     1011                return &c->set;
     1012        else
     1013                return NULL;
     1014}
     1015
     1016static void cmd_chat( irc_t *irc, char **cmd )
     1017{
     1018        account_t *acc;
     1019        struct chat *c;
     1020       
     1021        if( g_strcasecmp( cmd[1], "add" ) == 0 )
     1022        {
     1023                char *channel, *s;
     1024               
     1025                MIN_ARGS( 3 );
     1026               
     1027                if( !( acc = account_get( irc, cmd[2] ) ) )
     1028                {
     1029                        irc_usermsg( irc, "Invalid account" );
     1030                        return;
     1031                }
     1032               
     1033                if( cmd[4] == NULL )
     1034                {
     1035                        channel = g_strdup( cmd[3] );
     1036                        if( ( s = strchr( channel, '@' ) ) )
     1037                                *s = 0;
     1038                }
     1039                else
     1040                {
     1041                        channel = g_strdup( cmd[4] );
     1042                }
     1043               
     1044                if( strchr( CTYPES, channel[0] ) == NULL )
     1045                {
     1046                        s = g_strdup_printf( "%c%s", CTYPES[0], channel );
     1047                        g_free( channel );
     1048                        channel = s;
     1049                }
     1050               
     1051                if( ( c = chat_add( irc, acc, cmd[3], channel ) ) )
     1052                        irc_usermsg( irc, "Chatroom added successfully." );
     1053                else
     1054                        irc_usermsg( irc, "Could not add chatroom." );
     1055               
     1056                g_free( channel );
     1057        }
     1058        else if( g_strcasecmp( cmd[1], "list" ) == 0 )
     1059        {
     1060                int i = 0;
     1061               
     1062                if( strchr( irc->umode, 'b' ) )
     1063                        irc_usermsg( irc, "Chatroom list:" );
     1064               
     1065                for( c = irc->chatrooms; c; c = c->next )
     1066                {
     1067                        irc_usermsg( irc, "%2d. %s(%s) %s, %s", i, c->acc->prpl->name,
     1068                                          c->acc->user, c->handle, c->channel );
     1069                       
     1070                        i ++;
     1071                }
     1072                irc_usermsg( irc, "End of chatroom list" );
     1073        }
     1074        else if( g_strcasecmp( cmd[1], "set" ) == 0 )
     1075        {
     1076                MIN_ARGS( 2 );
     1077               
     1078                cmd_set_real( irc, cmd + 1, cmd_chat_set_findhead, NULL );
     1079        }
     1080        else if( g_strcasecmp( cmd[1], "del" ) == 0 )
     1081        {
     1082                MIN_ARGS( 2 );
     1083               
     1084                if( ( c = chat_get( irc, cmd[2] ) ) )
     1085                {
     1086                        chat_del( irc, c );
     1087                }
     1088                else
     1089                {
     1090                        irc_usermsg( irc, "Could not remove chat." );
     1091                }
     1092        }
     1093        else if( g_strcasecmp( cmd[1], "with" ) == 0 )
     1094        {
     1095                user_t *u;
     1096               
     1097                MIN_ARGS( 2 );
     1098               
     1099                if( ( u = user_find( irc, cmd[2] ) ) && u->ic && u->ic->acc->prpl->chat_with )
     1100                {
     1101                        if( !u->ic->acc->prpl->chat_with( u->ic, u->handle ) )
     1102                        {
     1103                                irc_usermsg( irc, "(Possible) failure while trying to open "
     1104                                                  "a groupchat with %s.", u->nick );
     1105                        }
     1106                }
     1107                else
     1108                {
     1109                        irc_usermsg( irc, "Can't open a groupchat with %s.", cmd[2] );
     1110                }
     1111        }
     1112        else
     1113        {
     1114                irc_usermsg( irc, "Unknown command: %s %s. Please use \x02help commands\x02 to get a list of available commands.", "chat", cmd[1] );
     1115        }
     1116
     1117
     1118
     1119#if 0
    10091120        account_t *a;
    10101121        struct im_connection *ic;
     
    10321143        if( cmd[3] )
    10331144        {
    1034                 if( cmd[3][0] != '#' && cmd[3][0] != '&' )
     1145                if( strchr( CTYPES, cmd[3][0] ) == NULL )
    10351146                        channel = g_strdup_printf( "&%s", cmd[3] );
    10361147                else
     
    10751186                g_free( channel );
    10761187        }
     1188#endif
    10771189}
    10781190
     
    10971209        { "qlist",          0, cmd_qlist,          0 },
    10981210        { "join_chat",      2, cmd_join_chat,      0 },
     1211        { "chat",           1, cmd_chat,           0 },
    10991212        { NULL }
    11001213};
  • storage_xml.c

    r0c41177 rc5bc47b  
    5454        char *current_setting;
    5555        account_t *current_account;
     56        struct chat *current_chat;
     57        set_t **current_set_head;
    5658        char *given_nick;
    5759        char *given_pass;
     
    172174               
    173175                if( ( setting = xml_attr( attr_names, attr_values, "name" ) ) )
     176                {
     177                        if( xd->current_chat != NULL )
     178                                xd->current_set_head = &xd->current_chat->set;
     179                        else if( xd->current_account != NULL )
     180                                xd->current_set_head = &xd->current_account->set;
     181                        else
     182                                xd->current_set_head = &xd->irc->set;
     183                       
    174184                        xd->current_setting = g_strdup( setting );
     185                }
    175186                else
    176187                        g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
     
    194205                }
    195206        }
     207        else if( g_strcasecmp( element_name, "chat" ) == 0 )
     208        {
     209                char *handle, *channel;
     210               
     211                handle = xml_attr( attr_names, attr_values, "handle" );
     212                channel = xml_attr( attr_names, attr_values, "channel" );
     213               
     214                if( xd->current_account && handle && channel )
     215                {
     216                        xd->current_chat = chat_add( xd->irc, xd->current_account, handle, channel );
     217                }
     218                else
     219                {
     220                        g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
     221                                     "Missing attributes for %s element", element_name );
     222                }
     223        }
    196224        else
    197225        {
     
    214242                xd->current_account = NULL;
    215243        }
     244        else if( g_strcasecmp( element_name, "chat" ) == 0 )
     245        {
     246                xd->current_chat = NULL;
     247        }
    216248}
    217249
     
    220252        char text[text_len+1];
    221253        struct xml_parsedata *xd = data;
    222         irc_t *irc = xd->irc;
    223254       
    224255        strncpy( text, text_orig, text_len );
     
    233264        else if( g_strcasecmp( g_markup_parse_context_get_element( ctx ), "setting" ) == 0 && xd->current_setting )
    234265        {
    235                 set_setstr( xd->current_account ? &xd->current_account->set : &irc->set,
    236                             xd->current_setting, (char*) text );
     266                set_setstr( xd->current_set_head, xd->current_setting, (char*) text );
    237267                g_free( xd->current_setting );
    238268                xd->current_setting = NULL;
     
    397427       
    398428        for( set = irc->set; set; set = set->next )
    399                 if( set->value && set->def )
     429                if( set->value )
    400430                        if( !xml_printf( fd, 1, "<setting name=\"%s\">%s</setting>\n", set->key, set->value ) )
    401431                                goto write_error;
     
    406436                char *pass_b64;
    407437                int pass_len;
     438                struct chat *c;
    408439               
    409440                pass_len = arc_encode( acc->pass, strlen( acc->pass ), (unsigned char**) &pass_cr, irc->password, 12 );
     
    424455               
    425456                for( set = acc->set; set; set = set->next )
    426                         if( set->value && set->def && !( set->flags & ACC_SET_NOSAVE ) )
     457                        if( set->value && !( set->flags & ACC_SET_NOSAVE ) )
    427458                                if( !xml_printf( fd, 2, "<setting name=\"%s\">%s</setting>\n", set->key, set->value ) )
    428459                                        goto write_error;
     
    438469                        goto write_error;
    439470               
     471                for( c = irc->chatrooms; c; c = c->next )
     472                {
     473                        if( c->acc != acc )
     474                                continue;
     475                       
     476                        if( !xml_printf( fd, 2, "<chat handle=\"%s\" channel=\"%s\" type=\"%s\">\n",
     477                                                c->handle, c->channel, "room" ) )
     478                                goto write_error;
     479                       
     480                        for( set = c->set; set; set = set->next )
     481                                if( set->value && !( set->flags & ACC_SET_NOSAVE ) )
     482                                        if( !xml_printf( fd, 3, "<setting name=\"%s\">%s</setting>\n",
     483                                                                set->key, set->value ) )
     484                                                goto write_error;
     485
     486                        if( !xml_printf( fd, 2, "</chat>\n" ) )
     487                                goto write_error;
     488                }
     489               
    440490                if( !xml_printf( fd, 1, "</account>\n" ) )
    441491                        goto write_error;
  • tests/Makefile

    r0c41177 rc5bc47b  
    1111distclean: clean
    1212
    13 main_objs = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o storage_text.o user.o
     13main_objs = account.o bitlbee.o chat.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o storage_text.o user.o
    1414
    1515test_objs = check.o check_util.o check_nick.o check_md5.o check_arc.o check_irc.o check_help.o check_user.o check_crypting.o check_set.o check_jabber_sasl.o check_jabber_util.o
  • tests/check_set.c

    r0c41177 rc5bc47b  
    9696END_TEST
    9797
    98 START_TEST(test_setstr_implicit)
    99         void *data = "data";
    100         set_t *s = NULL, *t;
    101         set_setstr(&s, "name", "bloe");
    102         fail_unless(set_find(&s, "name") != NULL);
    103 END_TEST
    104 
    10598START_TEST(test_set_get_int_unknown)
    10699        set_t *s = NULL;
     
    126119        tcase_add_test (tc_core, test_setint);
    127120        tcase_add_test (tc_core, test_setstr);
    128         tcase_add_test (tc_core, test_setstr_implicit);
    129121        return s;
    130122}
  • user.c

    r0c41177 rc5bc47b  
    141141}
    142142
    143 user_t *user_findhandle( struct im_connection *ic, char *handle )
     143user_t *user_findhandle( struct im_connection *ic, const char *handle )
    144144{
    145145        user_t *u;
  • user.h

    r0c41177 rc5bc47b  
    5656int user_del( irc_t *irc, char *nick );
    5757G_MODULE_EXPORT user_t *user_find( irc_t *irc, char *nick );
    58 G_MODULE_EXPORT user_t *user_findhandle( struct im_connection *ic, char *handle );
     58G_MODULE_EXPORT user_t *user_findhandle( struct im_connection *ic, const char *handle );
    5959void user_rename( irc_t *irc, char *oldnick, char *newnick );
    6060
Note: See TracChangeset for help on using the changeset viewer.