source: irc.c @ 4be8239

Last change on this file since 4be8239 was 4be8239, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-03-27T02:39:08Z

Simple IRC channel interface, use it to represent the control channel.

  • Property mode set to 100644
File size: 16.9 KB
RevLine 
[b7d3cc34]1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
4  * Copyright 2002-2004 Wilmer van der Gaast and others                *
5  \********************************************************************/
6
[3ddb7477]7/* The IRC-based UI (for now the only one)                              */
[b7d3cc34]8
9/*
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU General Public License for more details.
19
20  You should have received a copy of the GNU General Public License with
21  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
22  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
23  Suite 330, Boston, MA  02111-1307  USA
24*/
25
26#include "bitlbee.h"
27
[3ddb7477]28GSList *irc_connection_list;
[b7d3cc34]29
[3ddb7477]30static char *set_eval_charset( set_t *set, char *value );
[58adb7e]31
[b7d3cc34]32irc_t *irc_new( int fd )
33{
[e4d6271]34        irc_t *irc;
[e9b755e]35        struct sockaddr_storage sock;
[7435ccf]36        socklen_t socklen = sizeof( sock );
[3ddb7477]37        char *host = NULL, *myhost = NULL;
38        irc_user_t *iu;
[7125cb3]39        set_t *s;
[3ddb7477]40        bee_t *b;
[e4d6271]41       
42        irc = g_new0( irc_t, 1 );
[b7d3cc34]43       
44        irc->fd = fd;
[a0d04d6]45        sock_make_nonblocking( irc->fd );
46       
[ba9edaa]47        irc->r_watch_source_id = b_input_add( irc->fd, GAIM_INPUT_READ, bitlbee_io_current_client_read, irc );
[b7d3cc34]48       
49        irc->status = USTATUS_OFFLINE;
50        irc->last_pong = gettime();
51       
[3ddb7477]52        irc->nick_user_hash = g_hash_table_new( g_str_hash, g_str_equal );
[b7d3cc34]53        irc->watches = g_hash_table_new( g_str_hash, g_str_equal );
54       
55        strcpy( irc->umode, UMODE );
56       
[f9756bd]57        irc->iconv = (GIConv) -1;
58        irc->oconv = (GIConv) -1;
59       
[b7d3cc34]60        if( global.conf->hostname )
61        {
[3ddb7477]62                myhost = g_strdup( global.conf->hostname );
[b7d3cc34]63        }
[7435ccf]64        else if( getsockname( irc->fd, (struct sockaddr*) &sock, &socklen ) == 0 ) 
[b7d3cc34]65        {
[2231302]66                char buf[NI_MAXHOST+1];
[e9b755e]67
[2231302]68                if( getnameinfo( (struct sockaddr *) &sock, socklen, buf,
[c84e31a]69                                 NI_MAXHOST, NULL, 0, 0 ) == 0 )
[2231302]70                {
[3ddb7477]71                        myhost = g_strdup( ipv6_unwrap( buf ) );
[2231302]72                }
[b7d3cc34]73        }
74       
[7435ccf]75        if( getpeername( irc->fd, (struct sockaddr*) &sock, &socklen ) == 0 )
[b7d3cc34]76        {
[2231302]77                char buf[NI_MAXHOST+1];
[e9b755e]78
[2231302]79                if( getnameinfo( (struct sockaddr *)&sock, socklen, buf,
[c84e31a]80                                 NI_MAXHOST, NULL, 0, 0 ) == 0 )
[2231302]81                {
[3ddb7477]82                        host = g_strdup( ipv6_unwrap( buf ) );
[2231302]83                }
[b7d3cc34]84        }
85       
[3ddb7477]86        if( host == NULL )
87                host = g_strdup( "localhost.localdomain" );
88        if( myhost == NULL )
89                myhost = g_strdup( "localhost.localdomain" );
[3e1e11af]90       
[3ddb7477]91        //if( global.conf->ping_interval > 0 && global.conf->ping_timeout > 0 )
92        //      irc->ping_source_id = b_timeout_add( global.conf->ping_interval * 1000, irc_userping, irc );
[b7d3cc34]93
94        irc_connection_list = g_slist_append( irc_connection_list, irc );
95       
[3ddb7477]96        b = irc->b = bee_new();
97       
98        s = set_add( &b->set, "away_devoice", "true", NULL/*set_eval_away_devoice*/, irc );
99        s = set_add( &b->set, "buddy_sendbuffer", "false", set_eval_bool, irc );
100        s = set_add( &b->set, "buddy_sendbuffer_delay", "200", set_eval_int, irc );
101        s = set_add( &b->set, "charset", "utf-8", set_eval_charset, irc );
102        //s = set_add( &b->set, "control_channel", irc->channel, NULL/*set_eval_control_channel*/, irc );
103        s = set_add( &b->set, "default_target", "root", NULL, irc );
104        s = set_add( &b->set, "display_namechanges", "false", set_eval_bool, irc );
105        s = set_add( &b->set, "handle_unknown", "root", NULL, irc );
106        s = set_add( &b->set, "lcnicks", "true", set_eval_bool, irc );
107        s = set_add( &b->set, "ops", "both", NULL/*set_eval_ops*/, irc );
108        s = set_add( &b->set, "private", "true", set_eval_bool, irc );
109        s = set_add( &b->set, "query_order", "lifo", NULL, irc );
110        s = set_add( &b->set, "root_nick", ROOT_NICK, NULL/*set_eval_root_nick*/, irc );
111        s = set_add( &b->set, "simulate_netsplit", "true", set_eval_bool, irc );
112        s = set_add( &b->set, "to_char", ": ", set_eval_to_char, irc );
113        s = set_add( &b->set, "typing_notice", "false", set_eval_bool, irc );
114
115        irc->root = iu = irc_user_new( irc, ROOT_NICK );
116        iu->host = g_strdup( myhost );
117        iu->fullname = g_strdup( ROOT_FN );
118       
119        iu = irc_user_new( irc, NS_NICK );
120        iu->host = g_strdup( myhost );
121        iu->fullname = g_strdup( ROOT_FN );
122       
123        irc->user = g_new0( irc_user_t, 1 );
124        irc->user->host = g_strdup( host );
125       
[ebaebfe]126        conf_loaddefaults( irc );
[b7d3cc34]127       
[f9756bd]128        /* Evaluator sets the iconv/oconv structures. */
[3ddb7477]129        set_eval_charset( set_find( &b->set, "charset" ), set_getstr( &b->set, "charset" ) );
[f9756bd]130       
[3ddb7477]131        irc_write( irc, ":%s NOTICE AUTH :%s", irc->root->host, "BitlBee-IRCd initialized, please go on" );
132       
[ebaebfe]133        g_free( myhost );
134        g_free( host );
135       
[3ddb7477]136        return irc;
[b7d3cc34]137}
138
[f73b969]139/* immed=1 makes this function pretty much equal to irc_free(), except that
140   this one will "log". In case the connection is already broken and we
141   shouldn't try to write to it. */
[fc50d48]142void irc_abort( irc_t *irc, int immed, char *format, ... )
[c1826c6]143{
[fc50d48]144        if( format != NULL )
145        {
[f73b969]146                va_list params;
[fc50d48]147                char *reason;
148               
149                va_start( params, format );
[f73b969]150                reason = g_strdup_vprintf( format, params );
[fc50d48]151                va_end( params );
152               
153                if( !immed )
154                        irc_write( irc, "ERROR :Closing link: %s", reason );
155               
156                ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n",
[3ddb7477]157                                   irc->user->nick ? irc->user->nick : "(NONE)", irc->root->host, reason );
[fc50d48]158               
159                g_free( reason );
160        }
161        else
162        {
163                if( !immed )
164                        irc_write( irc, "ERROR :Closing link" );
165               
166                ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n",
[3ddb7477]167                                   irc->user->nick ? irc->user->nick : "(NONE)", irc->root->host, "No reason given" );
[fc50d48]168        }
169       
[79e826a]170        irc->status |= USTATUS_SHUTDOWN;
[fc50d48]171        if( irc->sendbuffer && !immed )
[c1826c6]172        {
[883a398]173                /* Set up a timeout event that should shut down the connection
174                   in a second, just in case ..._write doesn't do it first. */
[fc50d48]175               
[ba9edaa]176                b_event_remove( irc->r_watch_source_id );
[883a398]177                irc->r_watch_source_id = 0;
178               
179                b_event_remove( irc->ping_source_id );
180                irc->ping_source_id = b_timeout_add( 1000, (b_event_handler) irc_free, irc );
[c1826c6]181        }
182        else
183        {
184                irc_free( irc );
185        }
186}
187
[3ddb7477]188static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data );
[b7d3cc34]189
[fa75134]190void irc_free( irc_t * irc )
[b7d3cc34]191{
192        log_message( LOGLVL_INFO, "Destroying connection with fd %d", irc->fd );
193       
[3ddb7477]194        /*
195        if( irc->status & USTATUS_IDENTIFIED && set_getbool( &irc->b->set, "save_on_quit" ) )
[3183c21]196                if( storage_save( irc, NULL, TRUE ) != STORAGE_OK )
[b7d3cc34]197                        irc_usermsg( irc, "Error while saving settings!" );
[3ddb7477]198        */
[b7d3cc34]199       
200        irc_connection_list = g_slist_remove( irc_connection_list, irc );
201       
[3ddb7477]202        /*
[fa75134]203        while( irc->queries != NULL )
204                query_del( irc, irc->queries );
[3ddb7477]205        */
[5b52a48]206       
[3ddb7477]207        while( irc->users )
[ebaebfe]208        {
209                irc_user_t *iu = irc->users->data;
210                irc_user_free( irc, iu->nick );
211        }
[b7d3cc34]212       
[fa75134]213        if( irc->ping_source_id > 0 )
214                b_event_remove( irc->ping_source_id );
[883a398]215        if( irc->r_watch_source_id > 0 )
216                b_event_remove( irc->r_watch_source_id );
[fa75134]217        if( irc->w_watch_source_id > 0 )
218                b_event_remove( irc->w_watch_source_id );
219       
220        closesocket( irc->fd );
221        irc->fd = -1;
222       
[3ddb7477]223        g_hash_table_foreach_remove( irc->nick_user_hash, irc_free_hashkey, NULL );
224        g_hash_table_destroy( irc->nick_user_hash );
[b7d3cc34]225       
[fa75134]226        g_hash_table_foreach_remove( irc->watches, irc_free_hashkey, NULL );
227        g_hash_table_destroy( irc->watches );
[b7d3cc34]228       
[f9756bd]229        if( irc->iconv != (GIConv) -1 )
230                g_iconv_close( irc->iconv );
231        if( irc->oconv != (GIConv) -1 )
232                g_iconv_close( irc->oconv );
233       
[fa75134]234        g_free( irc->sendbuffer );
235        g_free( irc->readbuffer );
236       
237        g_free( irc->password );
238       
239        g_free( irc );
[b7d3cc34]240       
[565a1ea]241        if( global.conf->runmode == RUNMODE_INETD ||
242            global.conf->runmode == RUNMODE_FORKDAEMON ||
243            ( global.conf->runmode == RUNMODE_DAEMON &&
244              global.listen_socket == -1 &&
245              irc_connection_list == NULL ) )
[ba9edaa]246                b_main_quit();
[b7d3cc34]247}
248
[3ddb7477]249static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data )
[7cad7b4]250{
[3ddb7477]251        g_free( key );
[7cad7b4]252       
[3ddb7477]253        return( TRUE );
[7cad7b4]254}
255
[3ddb7477]256static char **irc_splitlines( char *buffer );
257
[f73b969]258void irc_process( irc_t *irc )
[b7d3cc34]259{
[f9756bd]260        char **lines, *temp, **cmd;
[b7d3cc34]261        int i;
262
[de3e100]263        if( irc->readbuffer != NULL )
264        {
[3ddb7477]265                lines = irc_splitlines( irc->readbuffer );
[de3e100]266               
267                for( i = 0; *lines[i] != '\0'; i ++ )
268                {
[f9756bd]269                        char *conv = NULL;
[7d31002]270                       
[18ff38f]271                        /* [WvG] If the last line isn't empty, it's an incomplete line and we
272                           should wait for the rest to come in before processing it. */
[de3e100]273                        if( lines[i+1] == NULL )
274                        {
[b7d3cc34]275                                temp = g_strdup( lines[i] );
276                                g_free( irc->readbuffer );
277                                irc->readbuffer = temp;
[de3e100]278                                i ++;
[b7d3cc34]279                                break;
[e27661d]280                        }
281                       
[f9756bd]282                        if( irc->iconv != (GIConv) -1 )
[e27661d]283                        {
[f9756bd]284                                gsize bytes_read, bytes_written;
285                               
286                                conv = g_convert_with_iconv( lines[i], -1, irc->iconv,
287                                                             &bytes_read, &bytes_written, NULL );
288                               
289                                if( conv == NULL || bytes_read != strlen( lines[i] ) )
[94d52d64]290                                {
[fc0cf92]291                                        /* GLib can do strange things if things are not in the expected charset,
292                                           so let's be a little bit paranoid here: */
[94d52d64]293                                        if( irc->status & USTATUS_LOGGED_IN )
[fc0cf92]294                                        {
[43462708]295                                                irc_usermsg( irc, "Error: Charset mismatch detected. The charset "
[94d52d64]296                                                                  "setting is currently set to %s, so please make "
297                                                                  "sure your IRC client will send and accept text in "
298                                                                  "that charset, or tell BitlBee which charset to "
299                                                                  "expect by changing the charset setting. See "
300                                                                  "`help set charset' for more information. Your "
[f9756bd]301                                                                  "message was ignored.",
[3ddb7477]302                                                                  set_getstr( &irc->b->set, "charset" ) );
[f9756bd]303                                               
304                                                g_free( conv );
305                                                conv = NULL;
[fc0cf92]306                                        }
307                                        else
308                                        {
[3ddb7477]309                                                irc_write( irc, ":%s NOTICE AUTH :%s", irc->root->host,
[a83442a]310                                                           "Warning: invalid characters received at login time." );
[fc0cf92]311                                               
[f9756bd]312                                                conv = g_strdup( lines[i] );
[fc0cf92]313                                                for( temp = conv; *temp; temp ++ )
314                                                        if( *temp & 0x80 )
315                                                                *temp = '?';
316                                        }
[94d52d64]317                                }
318                                lines[i] = conv;
[e27661d]319                        }
[de3e100]320                       
[e1720ce]321                        if( lines[i] && ( cmd = irc_parse_line( lines[i] ) ) )
[f9756bd]322                        {
323                                irc_exec( irc, cmd );
324                                g_free( cmd );
325                        }
[f73b969]326                       
[f9756bd]327                        g_free( conv );
[f73b969]328                       
329                        /* Shouldn't really happen, but just in case... */
330                        if( !g_slist_find( irc_connection_list, irc ) )
[de3e100]331                        {
[b7d3cc34]332                                g_free( lines );
[f73b969]333                                return;
[b7d3cc34]334                        }
335                }
[de3e100]336               
337                if( lines[i] != NULL )
338                {
339                        g_free( irc->readbuffer );
[0431ea1]340                        irc->readbuffer = NULL;
[b7d3cc34]341                }
[de3e100]342               
[b7d3cc34]343                g_free( lines );
344        }
345}
346
[3ddb7477]347/* Splits a long string into separate lines. The array is NULL-terminated
348   and, unless the string contains an incomplete line at the end, ends with
349   an empty string. Could use g_strsplit() but this one does it in-place.
350   (So yes, it's destructive.) */
351static char **irc_splitlines( char *buffer )
[b7d3cc34]352{
[18ff38f]353        int i, j, n = 3;
[b7d3cc34]354        char **lines;
355
[18ff38f]356        /* Allocate n+1 elements. */
357        lines = g_new( char *, n + 1 );
[b7d3cc34]358       
[de3e100]359        lines[0] = buffer;
[b7d3cc34]360       
[18ff38f]361        /* Split the buffer in several strings, and accept any kind of line endings,
362         * knowing that ERC on Windows may send something interesting like \r\r\n,
363         * and surely there must be clients that think just \n is enough... */
364        for( i = 0, j = 0; buffer[i] != '\0'; i ++ )
[de3e100]365        {
[18ff38f]366                if( buffer[i] == '\r' || buffer[i] == '\n' )
[de3e100]367                {
[18ff38f]368                        while( buffer[i] == '\r' || buffer[i] == '\n' )
369                                buffer[i++] = '\0';
370                       
371                        lines[++j] = buffer + i;
[de3e100]372                       
[18ff38f]373                        if( j >= n )
374                        {
375                                n *= 2;
376                                lines = g_renew( char *, lines, n + 1 );
377                        }
378
379                        if( buffer[i] == '\0' )
380                                break;
[b7d3cc34]381                }
382        }
[de3e100]383       
[18ff38f]384        /* NULL terminate our list. */ 
385        lines[++j] = NULL;
386       
387        return lines;
[b7d3cc34]388}
389
[e27661d]390/* Split an IRC-style line into little parts/arguments. */
[0431ea1]391char **irc_parse_line( char *line )
[b7d3cc34]392{
393        int i, j;
394        char **cmd;
395       
396        /* Move the line pointer to the start of the command, skipping spaces and the optional prefix. */
[de3e100]397        if( line[0] == ':' )
398        {
[e1720ce]399                for( i = 0; line[i] && line[i] != ' '; i ++ );
[de3e100]400                line = line + i;
[b7d3cc34]401        }
[de3e100]402        for( i = 0; line[i] == ' '; i ++ );
403        line = line + i;
404       
[b7d3cc34]405        /* If we're already at the end of the line, return. If not, we're going to need at least one element. */
[de3e100]406        if( line[0] == '\0')
407                return NULL;
408       
409        /* Count the number of char **cmd elements we're going to need. */
410        j = 1;
411        for( i = 0; line[i] != '\0'; i ++ )
412        {
413                if( line[i] == ' ' )
414                {
415                        j ++;
[b7d3cc34]416                       
[de3e100]417                        if( line[i+1] == ':' )
418                                break;
419                }
[b7d3cc34]420        }       
421
422        /* Allocate the space we need. */
[de3e100]423        cmd = g_new( char *, j + 1 );
424        cmd[j] = NULL;
[b7d3cc34]425       
426        /* Do the actual line splitting, format is:
427         * Input: "PRIVMSG #bitlbee :foo bar"
428         * Output: cmd[0]=="PRIVMSG", cmd[1]=="#bitlbee", cmd[2]=="foo bar", cmd[3]==NULL
429         */
430
[de3e100]431        cmd[0] = line;
432        for( i = 0, j = 0; line[i] != '\0'; i ++ )
[b7d3cc34]433        {
[de3e100]434                if( line[i] == ' ' )
[b7d3cc34]435                {
[de3e100]436                        line[i] = '\0';
437                        cmd[++j] = line + i + 1;
[b7d3cc34]438                       
[de3e100]439                        if( line[i+1] == ':' )
[b7d3cc34]440                        {
[de3e100]441                                cmd[j] ++;
[b7d3cc34]442                                break;
443                        }
444                }
445        }
446       
[de3e100]447        return cmd;
[b7d3cc34]448}
449
[e27661d]450/* Converts such an array back into a command string. Mainly used for the IPC code right now. */
[74c119d]451char *irc_build_line( char **cmd )
452{
453        int i, len;
454        char *s;
[b7d3cc34]455       
[74c119d]456        if( cmd[0] == NULL )
457                return NULL;
[b7d3cc34]458       
[74c119d]459        len = 1;
460        for( i = 0; cmd[i]; i ++ )
461                len += strlen( cmd[i] ) + 1;
462       
463        if( strchr( cmd[i-1], ' ' ) != NULL )
464                len ++;
465       
466        s = g_new0( char, len + 1 );
467        for( i = 0; cmd[i]; i ++ )
[b7d3cc34]468        {
[74c119d]469                if( cmd[i+1] == NULL && strchr( cmd[i], ' ' ) != NULL )
470                        strcat( s, ":" );
[b7d3cc34]471               
[74c119d]472                strcat( s, cmd[i] );
[b7d3cc34]473               
[74c119d]474                if( cmd[i+1] )
475                        strcat( s, " " );
[b7d3cc34]476        }
[74c119d]477        strcat( s, "\r\n" );
[b7d3cc34]478       
[74c119d]479        return s;
[b7d3cc34]480}
481
[3ddb7477]482void irc_write( irc_t *irc, char *format, ... ) 
[b7d3cc34]483{
484        va_list params;
[3ddb7477]485
[b7d3cc34]486        va_start( params, format );
[3ddb7477]487        irc_vawrite( irc, format, params );     
[b7d3cc34]488        va_end( params );
[3ddb7477]489
[b7d3cc34]490        return;
491}
492
[3ddb7477]493void irc_write_all( int now, char *format, ... )
[b7d3cc34]494{
495        va_list params;
[3ddb7477]496        GSList *temp;   
[b7d3cc34]497       
498        va_start( params, format );
499       
[3ddb7477]500        temp = irc_connection_list;
501        while( temp != NULL )
502        {
503                irc_t *irc = temp->data;
504               
505                if( now )
506                {
507                        g_free( irc->sendbuffer );
508                        irc->sendbuffer = g_strdup( "\r\n" );
509                }
510                irc_vawrite( temp->data, format, params );
511                if( now )
512                {
513                        bitlbee_io_current_client_write( irc, irc->fd, GAIM_INPUT_WRITE );
514                }
515                temp = temp->next;
516        }
517       
[b7d3cc34]518        va_end( params );
519        return;
[3ddb7477]520} 
[b7d3cc34]521
522void irc_vawrite( irc_t *irc, char *format, va_list params )
523{
524        int size;
[f9756bd]525        char line[IRC_MAX_LINE+1];
[d783e48]526               
[0356ae3]527        /* Don't try to write anything new anymore when shutting down. */
[5898ef8]528        if( irc->status & USTATUS_SHUTDOWN )
[b7d3cc34]529                return;
[d783e48]530       
[f9756bd]531        memset( line, 0, sizeof( line ) );
[d783e48]532        g_vsnprintf( line, IRC_MAX_LINE - 2, format, params );
[b7d3cc34]533        strip_newlines( line );
[f9756bd]534       
535        if( irc->oconv != (GIConv) -1 )
[d783e48]536        {
[f9756bd]537                gsize bytes_read, bytes_written;
538                char *conv;
539               
540                conv = g_convert_with_iconv( line, -1, irc->oconv,
541                                             &bytes_read, &bytes_written, NULL );
542
543                if( bytes_read == strlen( line ) )
544                        strncpy( line, conv, IRC_MAX_LINE - 2 );
[d783e48]545               
[f9756bd]546                g_free( conv );
[d783e48]547        }
[f9756bd]548        g_strlcat( line, "\r\n", IRC_MAX_LINE + 1 );
[d783e48]549       
[a0d04d6]550        if( irc->sendbuffer != NULL )
551        {
[b7d3cc34]552                size = strlen( irc->sendbuffer ) + strlen( line );
553                irc->sendbuffer = g_renew ( char, irc->sendbuffer, size + 1 );
554                strcpy( ( irc->sendbuffer + strlen( irc->sendbuffer ) ), line );
555        }
[a0d04d6]556        else
[b7d3cc34]557        {
[a0d04d6]558                irc->sendbuffer = g_strdup(line);
[b7d3cc34]559        }
560       
[a0d04d6]561        if( irc->w_watch_source_id == 0 )
[0356ae3]562        {
563                /* If the buffer is empty we can probably write, so call the write event handler
564                   immediately. If it returns TRUE, it should be called again, so add the event to
565                   the queue. If it's FALSE, we emptied the buffer and saved ourselves some work
566                   in the event queue. */
[bbb6ffb]567                /* Really can't be done as long as the code doesn't do error checking very well:
568                if( bitlbee_io_current_client_write( irc, irc->fd, GAIM_INPUT_WRITE ) ) */
569               
570                /* So just always do it via the event handler. */
571                irc->w_watch_source_id = b_input_add( irc->fd, GAIM_INPUT_WRITE, bitlbee_io_current_client_write, irc );
[0356ae3]572        }
[a0d04d6]573       
[b7d3cc34]574        return;
575}
576
[edf9657]577int irc_check_login( irc_t *irc )
[b7d3cc34]578{
[3ddb7477]579        if( irc->user->user && irc->user->nick )
[edf9657]580        {
[3af70b0]581                if( global.conf->authmode == AUTHMODE_CLOSED && !( irc->status & USTATUS_AUTHORIZED ) )
[b7d3cc34]582                {
[3ddb7477]583                        irc_send_num( irc, 464, ":This server is password-protected." );
[edf9657]584                        return 0;
[b7d3cc34]585                }
[edf9657]586                else
[b7d3cc34]587                {
[4be8239]588                        irc_channel_t *ic;
589                        irc_user_t *iu = irc->user;
590                       
591                        irc->user = irc_user_new( irc, iu->nick );
592                        irc->user->user = iu->user;
593                        irc->user->fullname = iu->fullname;
594                        g_free( iu->nick );
595                        g_free( iu );
596                       
597                        irc->umode[0] = '\0';
598                        /*irc_umode_set( irc, "+" UMODE, 1 );*/
599                       
600                        if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON )
601                                ipc_to_master_str( "CLIENT %s %s :%s\r\n", irc->user->host, irc->user->nick, irc->user->fullname );
602                       
603                        irc->status |= USTATUS_LOGGED_IN;
604                       
605                        /* This is for bug #209 (use PASS to identify to NickServ). */
606                        if( irc->password != NULL )
607                        {
608                                char *send_cmd[] = { "identify", g_strdup( irc->password ), NULL };
609                               
610                                /*irc_setpass( irc, NULL );*/
611                                /*root_command( irc, send_cmd );*/
612                                g_free( send_cmd[1] );
613                        }
614                       
[3ddb7477]615                        irc_send_login( irc );
[4be8239]616                       
617                        ic = irc_channel_new( irc, ROOT_CHAN );
618                        irc_channel_set_topic( ic, CONTROL_TOPIC );
619                        irc_channel_add_user( ic, irc->user );
620                       
[edf9657]621                        return 1;
[b7d3cc34]622                }
[edf9657]623        }
624        else
625        {
626                /* More information needed. */
627                return 0;
628        }
[b7d3cc34]629}
630
631
632
[3ddb7477]633static char *set_eval_charset( set_t *set, char *value )
[b7d3cc34]634{
[3ddb7477]635        irc_t *irc = set->data;
636        GIConv ic, oc;
[b7d3cc34]637
[3ddb7477]638        if( g_strcasecmp( value, "none" ) == 0 )
639                value = g_strdup( "utf-8" );
[b7d3cc34]640
[3ddb7477]641        if( ( ic = g_iconv_open( "utf-8", value ) ) == (GIConv) -1 )
[b7d3cc34]642        {
[3ddb7477]643                return NULL;
[b7d3cc34]644        }
[3ddb7477]645        if( ( oc = g_iconv_open( value, "utf-8" ) ) == (GIConv) -1 )
[b7d3cc34]646        {
[3ddb7477]647                g_iconv_close( ic );
648                return NULL;
[b7d3cc34]649        }
650       
[3ddb7477]651        if( irc->iconv != (GIConv) -1 )
652                g_iconv_close( irc->iconv );
653        if( irc->oconv != (GIConv) -1 )
654                g_iconv_close( irc->oconv );
[b7d3cc34]655       
[3ddb7477]656        irc->iconv = ic;
657        irc->oconv = oc;
[0e7ab64]658
[3ddb7477]659        return value;
[0e7ab64]660}
Note: See TracBrowser for help on using the repository browser.