Changes in / [0431ea1:9d6b229]


Ignore:
Files:
3 deleted
6 edited

Legend:

Unmodified
Added
Removed
  • Makefile

    r0431ea1 r9d6b229  
    1010
    1111# Program variables
    12 objects = account.o bitlbee.o commands.o conf.o crypting.o help.o ini.o ipc.o irc.o irc_commands.o log.o nick.o query.o set.o storage.o storage_text.o unix.o url.o user.o util.o
     12objects = account.o bitlbee.o commands.o conf.o crypting.o help.o ini.o irc.o log.o nick.o query.o set.o storage.o storage_text.o unix.o url.o user.o util.o
    1313subdirs = protocols
    1414
  • bitlbee.c

    r0431ea1 r9d6b229  
    2929#include "protocols/nogaim.h"
    3030#include "help.h"
    31 #include "ipc.h"
    3231#include <signal.h>
    3332#include <stdio.h>
    3433#include <errno.h>
    3534
     35struct bitlbee_child
     36{
     37        pid_t pid;
     38        int ipc_fd;
     39        gint ipc_inpa;
     40};
     41
     42static GSList *child_list = NULL;
     43
    3644gboolean bitlbee_io_new_client( GIOChannel *source, GIOCondition condition, gpointer data );
    37 
     45 
    3846int bitlbee_daemon_init()
    3947{
     
    224232}
    225233
     234gboolean bitlbee_io_master_ipc_read( gpointer data, gint source, GaimInputCondition cond );
     235gboolean bitlbee_io_child_ipc_read( gpointer data, gint source, GaimInputCondition cond );
     236
    226237gboolean bitlbee_io_new_client( GIOChannel *source, GIOCondition condition, gpointer data )
    227238{
     
    253264                        child->pid = client_pid;
    254265                        child->ipc_fd = fds[0];
    255                         child->ipc_inpa = gaim_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child );
     266                        child->ipc_inpa = gaim_input_add( child->ipc_fd, GAIM_INPUT_READ, bitlbee_io_master_ipc_read, child );
    256267                        child_list = g_slist_append( child_list, child );
    257268                       
    258                         log_message( LOGLVL_INFO, "Creating new subprocess with pid %d.", client_pid );
    259                        
    260                         /* Close some things we don't need in the parent process. */
    261                         close( new_socket );
    262269                        close( fds[1] );
    263270                }
    264271                else if( client_pid == 0 )
    265272                {
    266                         irc_t *irc;
    267                        
    268273                        /* Close the listening socket, we're a client. */
    269274                        close( global.listen_socket );
    270275                        g_source_remove( global.listen_watch_source_id );
    271276                       
    272                         /* Make the connection. */
    273                         irc = irc_new( new_socket );
    274                        
    275277                        /* We can store the IPC fd there now. */
    276278                        global.listen_socket = fds[1];
    277                         global.listen_watch_source_id = gaim_input_add( fds[1], GAIM_INPUT_READ, ipc_child_read, irc );
     279                        global.listen_watch_source_id = gaim_input_add( fds[1], GAIM_INPUT_READ, bitlbee_io_child_ipc_read, NULL );
    278280                       
    279281                        close( fds[0] );
    280282                }
    281283        }
    282         else
     284       
     285        if( client_pid == 0 )
    283286        {
    284287                log_message( LOGLVL_INFO, "Creating new connection with fd %d.", new_socket );
    285288                irc_new( new_socket );
     289        }
     290        else
     291        {
     292                /* We don't need this one, only the client does. */
     293                close( new_socket );
    286294        }
    287295       
     
    298306        g_main_quit( global.loop );
    299307}
     308
     309gboolean bitlbee_io_master_ipc_read( gpointer data, gint source, GaimInputCondition cond )
     310{
     311        struct bitlbee_child *child = data;
     312        char buf[513], *eol;
     313        int size;
     314       
     315        size = recv( child->ipc_fd, buf, sizeof( buf ) - 1, MSG_PEEK );
     316       
     317        if( size < 0 || ( size < 0 && !sockerr_again() ) )
     318                goto error_abort;
     319        else
     320                buf[size] = 0;
     321       
     322        eol = strstr( buf, "\r\n" );
     323        if( eol == NULL )
     324                goto error_abort;
     325       
     326        size = recv( child->ipc_fd, buf, eol - buf + 2, 0 );
     327        buf[size] = 0;
     328       
     329        if( strcmp( buf, "DIE\r\n" ) == 0 )
     330        {
     331                printf( "Bye...\n" );
     332                exit( 0 );
     333        }
     334       
     335        return TRUE;
     336       
     337error_abort:
     338        {
     339                GSList *l;
     340                struct bitlbee_child *c;
     341               
     342                for( l = child_list; l; l = l->next )
     343                {
     344                        c = l->data;
     345                        if( c->ipc_fd == source )
     346                        {
     347                                close( c->ipc_fd );
     348                                gaim_input_remove( c->ipc_inpa );
     349                                g_free( c );
     350                               
     351                                child_list = g_slist_remove( child_list, l );
     352                               
     353                                break;
     354                        }
     355                }
     356               
     357                return FALSE;
     358        }
     359}
     360
     361gboolean bitlbee_io_child_ipc_read( gpointer data, gint source, GaimInputCondition cond )
     362{
     363        return TRUE;
     364}
  • commands.c

    r0431ea1 r9d6b229  
    3232#include <string.h>
    3333
     34const command_t commands[] = {
     35        { "help",           0, cmd_help },
     36        { "identify",       1, cmd_identify },
     37        { "register",       1, cmd_register },
     38        { "drop",           1, cmd_drop },
     39        { "account",        1, cmd_account },
     40        { "add",            2, cmd_add },
     41        { "info",           1, cmd_info },
     42        { "rename",         2, cmd_rename },
     43        { "remove",         1, cmd_remove },
     44        { "block",          1, cmd_block },
     45        { "allow",          1, cmd_allow },
     46        { "save",           0, cmd_save },
     47        { "set",            0, cmd_set },
     48        { "yes",            0, cmd_yesno },
     49        { "no",             0, cmd_yesno },
     50        { "blist",          0, cmd_blist },
     51        { "nick",           1, cmd_nick },
     52        { "import_buddies", 1, cmd_import_buddies },
     53        { "qlist",          0, cmd_qlist },
     54        { NULL }
     55};
     56
    3457int root_command_string( irc_t *irc, user_t *u, char *command, int flags )
    3558{
     
    91114}
    92115
    93 static int cmd_help( irc_t *irc, char **cmd )
     116int cmd_help( irc_t *irc, char **cmd )
    94117{
    95118        char param[80];
     
    120143}
    121144
    122 static int cmd_identify( irc_t *irc, char **cmd )
     145int cmd_identify( irc_t *irc, char **cmd )
    123146{
    124147        storage_status_t status = storage_load( irc->nick, cmd[1], irc );
     
    143166}
    144167
    145 static int cmd_register( irc_t *irc, char **cmd )
     168int cmd_register( irc_t *irc, char **cmd )
    146169{
    147170        if( global.conf->authmode == AUTHMODE_REGISTERED )
     
    170193}
    171194
    172 static int cmd_drop( irc_t *irc, char **cmd )
     195int cmd_drop( irc_t *irc, char **cmd )
    173196{
    174197        storage_status_t status;
     
    194217}
    195218
    196 static int cmd_account( irc_t *irc, char **cmd )
     219int cmd_account( irc_t *irc, char **cmd )
    197220{
    198221        account_t *a;
     
    354377}
    355378
    356 static int cmd_add( irc_t *irc, char **cmd )
     379int cmd_add( irc_t *irc, char **cmd )
    357380{
    358381        account_t *a;
     
    394417}
    395418
    396 static int cmd_info( irc_t *irc, char **cmd )
     419int cmd_info( irc_t *irc, char **cmd )
    397420{
    398421        struct gaim_connection *gc;
     
    431454}
    432455
    433 static int cmd_rename( irc_t *irc, char **cmd )
     456int cmd_rename( irc_t *irc, char **cmd )
    434457{
    435458        user_t *u;
     
    472495}
    473496
    474 static int cmd_remove( irc_t *irc, char **cmd )
     497int cmd_remove( irc_t *irc, char **cmd )
    475498{
    476499        user_t *u;
     
    494517}
    495518
    496 static int cmd_block( irc_t *irc, char **cmd )
     519int cmd_block( irc_t *irc, char **cmd )
    497520{
    498521        struct gaim_connection *gc;
     
    535558}
    536559
    537 static int cmd_allow( irc_t *irc, char **cmd )
     560int cmd_allow( irc_t *irc, char **cmd )
    538561{
    539562        struct gaim_connection *gc;
     
    577600}
    578601
    579 static int cmd_yesno( irc_t *irc, char **cmd )
     602int cmd_yesno( irc_t *irc, char **cmd )
    580603{
    581604        query_t *q = NULL;
     
    617640}
    618641
    619 static int cmd_set( irc_t *irc, char **cmd )
     642int cmd_set( irc_t *irc, char **cmd )
    620643{
    621644        if( cmd[1] && cmd[2] )
     
    643666}
    644667
    645 static int cmd_save( irc_t *irc, char **cmd )
     668int cmd_save( irc_t *irc, char **cmd )
    646669{
    647670        if( storage_save( irc, TRUE ) == STORAGE_OK )
     
    653676}
    654677
    655 static int cmd_blist( irc_t *irc, char **cmd )
     678int cmd_blist( irc_t *irc, char **cmd )
    656679{
    657680        int online = 0, away = 0, offline = 0;
     
    699722}
    700723
    701 static int cmd_nick( irc_t *irc, char **cmd )
     724int cmd_nick( irc_t *irc, char **cmd )
    702725{
    703726        account_t *a;
     
    735758}
    736759
    737 static int cmd_qlist( irc_t *irc, char **cmd )
     760int cmd_qlist( irc_t *irc, char **cmd )
    738761{
    739762        query_t *q = irc->queries;
     
    757780}
    758781
    759 static int cmd_import_buddies( irc_t *irc, char **cmd )
     782int cmd_import_buddies( irc_t *irc, char **cmd )
    760783{
    761784        struct gaim_connection *gc;
     
    809832        return( 0 );
    810833}
    811 
    812 const command_t commands[] = {
    813         { "help",           0, cmd_help,           0 },
    814         { "identify",       1, cmd_identify,       0 },
    815         { "register",       1, cmd_register,       0 },
    816         { "drop",           1, cmd_drop,           0 },
    817         { "account",        1, cmd_account,        0 },
    818         { "add",            2, cmd_add,            0 },
    819         { "info",           1, cmd_info,           0 },
    820         { "rename",         2, cmd_rename,         0 },
    821         { "remove",         1, cmd_remove,         0 },
    822         { "block",          1, cmd_block,          0 },
    823         { "allow",          1, cmd_allow,          0 },
    824         { "save",           0, cmd_save,           0 },
    825         { "set",            0, cmd_set,            0 },
    826         { "yes",            0, cmd_yesno,          0 },
    827         { "no",             0, cmd_yesno,          0 },
    828         { "blist",          0, cmd_blist,          0 },
    829         { "nick",           1, cmd_nick,           0 },
    830         { "import_buddies", 1, cmd_import_buddies, 0 },
    831         { "qlist",          0, cmd_qlist,          0 },
    832         { NULL }
    833 };
  • commands.h

    r0431ea1 r9d6b229  
    2929#include "bitlbee.h"
    3030
    31 typedef struct command
     31typedef struct command_t
    3232{
    3333        char *command;
    3434        int required_parameters;
    3535        int (*execute)(irc_t *, char **args);
    36         int flags;
    3736} command_t;
     37
     38int cmd_account( irc_t *irc, char **cmd );
     39int cmd_help( irc_t *irc, char **args);
     40int cmd_info( irc_t *irc, char **args);
     41int cmd_add( irc_t *irc, char **args) ;
     42int cmd_rename( irc_t *irc, char **args );
     43int cmd_remove( irc_t *irc, char **args );
     44int cmd_block( irc_t *irc, char **args );
     45int cmd_allow( irc_t *irc, char **args );
     46int cmd_save( irc_t *irc, char **args );
     47int cmd_set( irc_t *irc, char **args );
     48int cmd_yesno( irc_t *irc, char **args );
     49int cmd_identify( irc_t *irc, char **args );
     50int cmd_register( irc_t *irc, char **args );
     51int cmd_drop( irc_t *irc, char **args );
     52int cmd_blist( irc_t *irc, char **cmd );
     53int cmd_nick( irc_t *irc, char **cmd );
     54int cmd_qlist( irc_t *irc, char **cmd );
     55int cmd_import_buddies( irc_t *irc, char **cmd );
     56int cmd_dump( irc_t *irc, char **cmd );
    3857
    3958extern const command_t commands[];
    4059
    41 #define IRC_CMD_PRE_LOGIN       1
    42 #define IRC_CMD_LOGGED_IN       2
    43 #define IRC_CMD_OPER_ONLY       4
    44 #define IRC_CMD_TO_MASTER       8
    45 
    4660#endif
  • irc.c

    r0431ea1 r9d6b229  
    293293int irc_process( irc_t *irc )
    294294{
    295         char **lines, *temp, **cmd;
     295        char **lines, *temp;   
    296296        int i;
    297297
    298         if( irc->readbuffer != NULL )
    299         {
    300                 lines = irc_tokenize( irc->readbuffer );
    301                
    302                 for( i = 0; *lines[i] != '\0'; i ++ )
    303                 {
    304                         if( lines[i+1] == NULL )
    305                         {
     298        if( irc->readbuffer != NULL ) {
     299                lines = irc_tokenize(irc->readbuffer );
     300                for( i = 0; *lines[i] != '\0'; i++ ) {
     301                        if( lines[i+1] == NULL ) {
    306302                                temp = g_strdup( lines[i] );
    307303                                g_free( irc->readbuffer );
    308304                                irc->readbuffer = temp;
    309                                 i ++;
     305                                i++;
    310306                                break;
    311307                        }                       
    312                        
    313                         if( ( cmd = irc_parse_line( lines[i] ) ) == NULL )
    314                                 continue;
    315                         if( !irc_exec( irc, cmd ) )
    316                         {
    317                                 g_free( cmd );
     308                        if (!irc_process_line(irc, lines[i])) {
    318309                                g_free( lines );
    319310                                return 0;
    320311                        }
    321                        
    322                         g_free( cmd );
    323                 }
    324                
    325                 if( lines[i] != NULL )
    326                 {
    327                         g_free( irc->readbuffer );
    328                         irc->readbuffer = NULL;
    329                 }
    330                
     312                }
     313                if(lines[i]!=NULL) {
     314                        g_free(irc->readbuffer);
     315                        irc->readbuffer=NULL;   
     316                }
    331317                g_free( lines );
    332318        }
    333        
    334319        return 1;       
    335320}
     
    341326
    342327        /* Count the number of elements we're gonna need. */
    343         for( i = 0, j = 1; buffer[i] != '\0'; i ++ )
    344         {
    345                 if( buffer[i] == '\n' )
    346                         if( buffer[i+1] != '\r' && buffer[i+1] != '\n' )
    347                                 j ++;
     328        for(i=0, j=1; buffer[i]!='\0'; i++ ) {
     329                if(buffer[i]=='\n' )
     330                        if(buffer[i+1]!='\r' && buffer[i+1]!='\n')
     331                                j++;
    348332        }
    349333       
    350334        /* Allocate j+1 elements. */
    351         lines = g_new( char *, j + 1 );
     335        lines=g_new (char *, j+1);
    352336       
    353337        /* NULL terminate our list. */
    354         lines[j] = NULL;
    355        
    356         lines[0] = buffer;
     338        lines[j]=NULL;
     339       
     340        lines[0]=buffer;
    357341       
    358342        /* Split the buffer in several strings, using \r\n as our seperator, where \r is optional.
    359343         * Although this is not in the RFC, some braindead ircds (newnet's) use this, so some clients might too.
    360344         */
    361         for( i = 0, j = 0; buffer[i] != '\0'; i ++)
    362         {
    363                 if( buffer[i] == '\n' )
    364                 {
    365                         buffer[i] = '\0';
    366                        
    367                         if( i > 0 && buffer[i-1] == '\r' )
    368                                 buffer[i-1] = '\0';
    369                         if( buffer[i+1] != '\r' && buffer[i+1] != '\n' )
    370                                 lines[++j] = buffer + i + 1;
    371                 }
    372         }
    373        
    374         return( lines );
    375 }
    376 
    377 char **irc_parse_line( char *line )
     345        for( i=0, j=0; buffer[i]!='\0'; i++) {
     346                if(buffer[i]=='\n') {
     347                        buffer[i]='\0';
     348
     349                        /* We dont want to read 1 byte before our buffer
     350                         * and (in rare cases) generate a SIGSEGV.
     351                         */
     352                        if(i!=0)
     353                                if(buffer[i-1]=='\r')
     354                                        buffer[i-1]='\0';
     355                        if(buffer[i+1]!='\r'&&buffer[i+1]!='\n')
     356                                lines[++j]=buffer+i+1;
     357                }
     358        }
     359
     360        return(lines);
     361}
     362
     363int irc_process_line( irc_t *irc, char *line )
    378364{
    379365        int i, j;
     
    381367       
    382368        /* Move the line pointer to the start of the command, skipping spaces and the optional prefix. */
    383         if( line[0] == ':' )
    384         {
    385                 for( i = 0; line[i] != ' '; i ++ );
    386                 line = line + i;
    387         }
    388         for( i = 0; line[i] == ' '; i ++ );
    389         line = line + i;
    390        
     369        if(line[0]==':') {
     370                for(i=0; line[i]!=32; i++);
     371                line=line+i;
     372        }
     373        for(i=0; line[i]==32; i++);
     374        line=line+i;
     375
    391376        /* If we're already at the end of the line, return. If not, we're going to need at least one element. */
    392         if( line[0] == '\0')
    393                 return NULL;
    394        
    395         /* Count the number of char **cmd elements we're going to need. */
    396         j = 1;
    397         for( i = 0; line[i] != '\0'; i ++ )
    398         {
    399                 if( line[i] == ' ' )
    400                 {
    401                         j ++;
     377        if(line[0]=='\0')
     378                return 1;
     379        else
     380                j=1;   
     381       
     382        /* Count the number of char **cmd elements we're going to need. */     
     383        for(i=0; line[i]!='\0'; i++) {
     384                if((line[i]==32) && (line[i+1]!=32) && (line[i+1]!='\0') && (line[i+1]!=':'))           
     385                        j++;
     386                else if((line[i]==':') && (line[i+1]!='\0') && (line[i-1]==32)) {
     387                        j++;
     388                        break;
     389                }
    402390                       
    403                         if( line[i+1] == ':' )
    404                                 break;
    405                 }
    406391        }       
    407392
    408393        /* Allocate the space we need. */
    409         cmd = g_new( char *, j + 1 );
    410         cmd[j] = NULL;
     394        cmd=g_new(char *, j+1);
     395        cmd[j]=NULL;
    411396       
    412397        /* Do the actual line splitting, format is:
     
    415400         */
    416401
    417         cmd[0] = line;
    418         for( i = 0, j = 0; line[i] != '\0'; i ++ )
    419         {
    420                 if( line[i] == ' ' )
    421                 {
    422                         line[i] = '\0';
    423                         cmd[++j] = line + i + 1;
     402        cmd[0]=line;
     403        for(i=0, j=0; line[i]!='\0'; i++) {
     404                if((line[i]==32)) {
     405                        line[i]='\0';
     406                        if((line[i+1]!=32) && (line[i+1]!='\0') && (line[i+1]!=':'))           
     407                                cmd[++j]=line+i+1;
     408                }
     409                else if((line[i]==':') && (line[i+1]!='\0') && (line[i-1]=='\0')) {
     410                        cmd[++j]=line+i+1;
     411                        break;
     412                }
     413        }
     414       
     415        i=irc_exec(irc, cmd);
     416        g_free(cmd);
     417
     418        return(i);     
     419}
     420
     421int irc_exec( irc_t *irc, char **cmd )
     422{       
     423        int i;
     424
     425        if( (global.conf)->authmode == AUTHMODE_CLOSED && irc->status < USTATUS_AUTHORIZED )
     426        {
     427                if( g_strcasecmp( cmd[0], "PASS" ) == 0 )
     428                {
     429                        if( !cmd[1] )
     430                        {
     431                                irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
     432                        }
     433                        else if( strcmp( cmd[1], (global.conf)->auth_pass ) == 0 )
     434                        {
     435                                irc->status = USTATUS_AUTHORIZED;
     436                        }
     437                        else
     438                        {
     439                                irc_reply( irc, 464, ":Nope, maybe you should try it again..." );
     440                        }
     441                }
     442                else
     443                {
     444                        irc_reply( irc, 464, ":Uhh, fine, but I want the password first." );
     445                }
     446               
     447                return( 1 );
     448        }
     449       
     450        if( g_strcasecmp( cmd[0], "USER" ) == 0 )
     451        {
     452                if( !( cmd[1] && cmd[2] && cmd[3] && cmd[4] ) )
     453                {
     454                        irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
     455                }
     456                else if( irc->user )
     457                {
     458                        irc_reply( irc, 462, ":You can't change your nick/userinfo" );
     459                }
     460                else
     461                {
     462                        irc->user = g_strdup( cmd[1] );
     463                        irc->realname = g_strdup( cmd[4] );
     464                        if( irc->nick ) irc_login( irc );
     465                }
     466                return( 1 );
     467        }
     468        else if( g_strcasecmp( cmd[0], "NICK" ) == 0 )
     469        {
     470                if( !cmd[1] )
     471                {
     472                        irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
     473                }
     474                else if( irc->nick )
     475                {
     476                        irc_reply( irc, 438, ":The hand of the deity is upon thee, thy nick may not change" );
     477                }
     478                /* This is not clean, but for now it'll have to be like this... */
     479                else if( ( nick_cmp( cmd[1], irc->mynick ) == 0 ) || ( nick_cmp( cmd[1], NS_NICK ) == 0 ) )
     480                {
     481                        irc_reply( irc, 433, ":This nick is already in use" );
     482                }
     483                else if( !nick_ok( cmd[1] ) )
     484                {
     485                        /* [SH] Invalid characters. */
     486                        irc_reply( irc, 432, ":This nick contains invalid characters" );
     487                }
     488                else
     489                {
     490                        irc->nick = g_strdup( cmd[1] );
     491                        if( irc->user ) irc_login( irc );
     492                }
     493                return( 1 );
     494        }
     495        else if( g_strcasecmp( cmd[0], "QUIT" ) == 0 )
     496        {
     497                irc_write( irc, "ERROR :%s%s", cmd[1]?"Quit: ":"", cmd[1]?cmd[1]:"Client Quit" );
     498                g_io_channel_close( irc->io_channel );
     499                return( 0 );
     500        }
     501       
     502        if( !irc->user || !irc->nick )
     503        {
     504                irc_reply( irc, 451, ":Register first" );
     505                return( 1 );
     506        }
     507       
     508        if( g_strcasecmp( cmd[0], "PING" ) == 0 )
     509        {
     510                irc_write( irc, ":%s PONG %s :%s", irc->myhost, irc->myhost, cmd[1]?cmd[1]:irc->myhost );
     511        }
     512        else if( g_strcasecmp( cmd[0], "OPER" ) == 0 )
     513        {
     514                if( !cmd[2] )
     515                        irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
     516                else if( strcmp( cmd[2], global.conf->oper_pass ) == 0 )
     517                        irc_umode_set( irc, "+o", 1 );
     518                // else
     519                        /* FIXME/TODO: Find out which reply to send now. */
     520        }
     521        else if( g_strcasecmp( cmd[0], "MODE" ) == 0 )
     522        {
     523                if( !cmd[1] )
     524                {
     525                        irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
     526                }
     527                else if( *cmd[1] == '#' || *cmd[1] == '&' )
     528                {
     529                        if( cmd[2] )
     530                        {
     531                                if( *cmd[2] == '+' || *cmd[2] == '-' )
     532                                        irc_reply( irc, 477, "%s :Can't change channel modes", cmd[1] );
     533                                else if( *cmd[2] == 'b' )
     534                                        irc_reply( irc, 368, "%s :No bans possible", cmd[1] );
     535                        }
     536                        else
     537                                irc_reply( irc, 324, "%s +%s", cmd[1], CMODE );
     538                }
     539                else
     540                {
     541                        if( nick_cmp( cmd[1], irc->nick ) == 0 )
     542                        {
     543                                if( cmd[2] )
     544                                        irc_umode_set( irc, cmd[2], 0 );
     545                        }
     546                        else
     547                                irc_reply( irc, 502, ":Don't touch their modes" );
     548                }
     549        }
     550        else if( g_strcasecmp( cmd[0], "NAMES" ) == 0 )
     551        {
     552                irc_names( irc, cmd[1]?cmd[1]:irc->channel );
     553        }
     554        else if( g_strcasecmp( cmd[0], "PART" ) == 0 )
     555        {
     556                struct conversation *c;
     557               
     558                if( !cmd[1] )
     559                {
     560                        irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
     561                }
     562                else if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
     563                {
     564                        user_t *u = user_find( irc, irc->nick );
    424565                       
    425                         if( line[i+1] == ':' )
    426                         {
    427                                 cmd[j] ++;
     566                        /* Not allowed to leave control channel */
     567                        irc_part( irc, u, irc->channel );
     568                        irc_join( irc, u, irc->channel );
     569                }
     570                else if( ( c = conv_findchannel( cmd[1] ) ) )
     571                {
     572                        user_t *u = user_find( irc, irc->nick );
     573                       
     574                        irc_part( irc, u, c->channel );
     575                       
     576                        if( c->gc && c->gc->prpl )
     577                        {
     578                                c->joined = 0;
     579                                c->gc->prpl->chat_leave( c->gc, c->id );
     580                        }
     581                }
     582                else
     583                {
     584                        irc_reply( irc, 403, "%s :No such channel", cmd[1] );
     585                }
     586        }
     587        else if( g_strcasecmp( cmd[0], "JOIN" ) == 0 )
     588        {
     589                if( !cmd[1] )
     590                {
     591                        irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
     592                }
     593                else if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
     594                        ; /* Dude, you're already there...
     595                             RFC doesn't have any reply for that though? */
     596                else if( cmd[1] )
     597                {
     598                        if( ( cmd[1][0] == '#' || cmd[1][0] == '&' ) && cmd[1][1] )
     599                        {
     600                                user_t *u = user_find( irc, cmd[1] + 1 );
     601                               
     602                                if( u && u->gc && u->gc->prpl && u->gc->prpl->chat_open )
     603                                {
     604                                        irc_reply( irc, 403, "%s :Initializing groupchat in a different channel", cmd[1] );
     605                                       
     606                                        if( !u->gc->prpl->chat_open( u->gc, u->handle ) )
     607                                        {
     608                                                irc_usermsg( irc, "Could not open a groupchat with %s, maybe you don't have a connection to him/her yet?", u->nick );
     609                                        }
     610                                }
     611                                else
     612                                {
     613                                        irc_reply( irc, 403, "%s :Groupchats are not possible with %s", cmd[1], cmd[1]+1 );
     614                                }
     615                        }
     616                        else
     617                        {
     618                                irc_reply( irc, 403, "%s :No such channel", cmd[1] );
     619                        }
     620                }
     621        }
     622        else if( g_strcasecmp( cmd[0], "INVITE" ) == 0 )
     623        {
     624                if( cmd[1] && cmd[2] )
     625                        irc_invite( irc, cmd[1], cmd[2] );
     626                else
     627                        irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
     628        }
     629        else if( g_strcasecmp( cmd[0], "PRIVMSG" ) == 0 || g_strcasecmp( cmd[0], "NOTICE" ) == 0 )
     630        {
     631                if( !cmd[1] )
     632                {
     633                        irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
     634                }
     635                else if ( !cmd[2] )
     636                {
     637                        irc_reply( irc, 412, ":No text to send" );
     638                }
     639                else if ( irc->nick && g_strcasecmp( cmd[1], irc->nick ) == 0 )
     640                {
     641                        irc_write( irc, ":%s!%s@%s %s %s :%s", irc->nick, irc->user, irc->host, cmd[0], cmd[1], cmd[2] );
     642                }
     643                else
     644                {
     645                        if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
     646                        {
     647                                unsigned int i;
     648                                char *t = set_getstr( irc, "default_target" );
     649                               
     650                                if( g_strcasecmp( t, "last" ) == 0 && irc->last_target )
     651                                        cmd[1] = irc->last_target;
     652                                else if( g_strcasecmp( t, "root" ) == 0 )
     653                                        cmd[1] = irc->mynick;
     654                               
     655                                for( i = 0; i < strlen( cmd[2] ); i ++ )
     656                                {
     657                                        if( cmd[2][i] == ' ' ) break;
     658                                        if( cmd[2][i] == ':' || cmd[2][i] == ',' )
     659                                        {
     660                                                cmd[1] = cmd[2];
     661                                                cmd[2] += i;
     662                                                *cmd[2] = 0;
     663                                                while( *(++cmd[2]) == ' ' );
     664                                                break;
     665                                        }
     666                                }
     667                               
     668                                irc->is_private = 0;
     669                               
     670                                if( cmd[1] != irc->last_target )
     671                                {
     672                                        if( irc->last_target )
     673                                                g_free( irc->last_target );
     674                                        irc->last_target = g_strdup( cmd[1] );
     675                                }
     676                        }
     677                        else
     678                        {
     679                                irc->is_private = 1;
     680                        }
     681                        irc_send( irc, cmd[1], cmd[2], ( g_strcasecmp( cmd[0], "NOTICE" ) == 0 ) ? IM_FLAG_AWAY : 0 );
     682                }
     683        }
     684        else if( g_strcasecmp( cmd[0], "WHO" ) == 0 )
     685        {
     686                irc_who( irc, cmd[1] );
     687        }
     688        else if( g_strcasecmp( cmd[0], "USERHOST" ) == 0 )
     689        {
     690                user_t *u;
     691               
     692                if( !cmd[1] )
     693                {
     694                        irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
     695                }
     696                /* [TV] Usable USERHOST-implementation according to
     697                        RFC1459. Without this, mIRC shows an error
     698                        while connecting, and the used way of rejecting
     699                        breaks standards.
     700                */
     701               
     702                for( i = 1; cmd[i]; i ++ )
     703                        if( ( u = user_find( irc, cmd[i] ) ) )
     704                        {
     705                                if( u->online && u->away )
     706                                        irc_reply( irc, 302, ":%s=-%s@%s", u->nick, u->user, u->host );
     707                                else
     708                                        irc_reply( irc, 302, ":%s=+%s@%s", u->nick, u->user, u->host );
     709                        }
     710        }
     711        else if( g_strcasecmp( cmd[0], "ISON" ) == 0 )
     712        {
     713                user_t *u;
     714                char buff[IRC_MAX_LINE];
     715                int lenleft;
     716               
     717                buff[0] = '\0';
     718               
     719                /* [SH] Leave room for : and \0 */
     720                lenleft = IRC_MAX_LINE - 2;
     721               
     722                for( i = 1; cmd[i]; i ++ )
     723                {
     724                        if( ( u = user_find( irc, cmd[i] ) ) && u->online )
     725                        {
     726                                /* [SH] Make sure we don't use too much buffer space. */
     727                                lenleft -= strlen( u->nick ) + 1;
     728                               
     729                                if( lenleft < 0 )
     730                                {
     731                                        break;
     732                                }
     733                               
     734                                /* [SH] Add the nick to the buffer. Note
     735                                 * that an extra space is always added. Even
     736                                 * if it's the last nick in the list. Who
     737                                 * cares?
     738                                 */
     739                               
     740                                strcat( buff, u->nick );
     741                                strcat( buff, " " );
     742                        }
     743                }
     744               
     745                /* [WvG] Well, maybe someone cares, so why not remove it? */
     746                if( strlen( buff ) > 0 )
     747                        buff[strlen(buff)-1] = '\0';
     748               
     749                /* [SH] By the way, that really *was* WvG talking. */
     750                /* [WvG] Really? */
     751                /* [SH] Yeah... But *this* is WvG talking too. ;-P */
     752                /* [WvG] *sigh* */
     753               
     754                irc_reply( irc, 303, ":%s", buff );
     755        }
     756        else if( g_strcasecmp( cmd[0], "WATCH" ) == 0 )
     757        {
     758                /* Obviously we could also mark a user structure as being
     759                   watched, but what if the WATCH command is sent right
     760                   after connecting? The user won't exist yet then... */
     761                for( i = 1; cmd[i]; i ++ )
     762                {
     763                        char *nick;
     764                        user_t *u;
     765                       
     766                        if( !cmd[i][0] || !cmd[i][1] )
    428767                                break;
    429                         }
    430                 }
    431         }
    432        
    433         return cmd;
     768                       
     769                        nick = g_strdup( cmd[i] + 1 );
     770                        nick_lc( nick );
     771                       
     772                        u = user_find( irc, nick );
     773                       
     774                        if( cmd[i][0] == '+' )
     775                        {
     776                                if( !g_hash_table_lookup( irc->watches, nick ) )
     777                                        g_hash_table_insert( irc->watches, nick, nick );
     778                               
     779                                if( u && u->online )
     780                                        irc_reply( irc, 604, "%s %s %s %d :%s", u->nick, u->user, u->host, time( NULL ), "is online" );
     781                                else
     782                                        irc_reply( irc, 605, "%s %s %s %d :%s", nick, "*", "*", time( NULL ), "is offline" );
     783                        }
     784                        else if( cmd[i][0] == '-' )
     785                        {
     786                                gpointer okey, ovalue;
     787                               
     788                                if( g_hash_table_lookup_extended( irc->watches, nick, &okey, &ovalue ) )
     789                                {
     790                                        g_free( okey );
     791                                        g_hash_table_remove( irc->watches, okey );
     792                                       
     793                                        irc_reply( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" );
     794                                }
     795                        }
     796                }
     797        }
     798        else if( g_strcasecmp( cmd[0], "TOPIC" ) == 0 )
     799        {
     800                if( cmd[1] && cmd[2] )
     801                        irc_reply( irc, 482, "%s :Cannot change topic", cmd[1] );
     802                else if( cmd[1] )
     803                        irc_topic( irc, cmd[1] );
     804                else
     805                        irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
     806        }
     807        else if( g_strcasecmp( cmd[0], "AWAY" ) == 0 )
     808        {
     809                irc_away( irc, cmd[1] );
     810        }
     811        else if( g_strcasecmp( cmd[0], "WHOIS" ) == 0 )
     812        {
     813                if( cmd[1] )
     814                {
     815                        irc_whois( irc, cmd[1] );
     816                }
     817                else
     818                {
     819                        irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
     820                }
     821        }
     822        else if( g_strcasecmp( cmd[0], "WHOWAS" ) == 0 )
     823        {
     824                /* For some reason irssi tries a whowas when whois fails. We can
     825                   ignore this, but then the user never gets a "user not found"
     826                   message from irssi which is a bit annoying. So just respond
     827                   with not-found and irssi users will get better error messages */
     828               
     829                if( cmd[1] )
     830                {
     831                        irc_reply( irc, 406, "%s :Nick does not exist", cmd[1] );
     832                        irc_reply( irc, 369, "%s :End of WHOWAS", cmd[1] );
     833                }
     834                else
     835                {
     836                        irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
     837                }
     838        }
     839        else if( ( g_strcasecmp( cmd[0], "NICKSERV" ) == 0 ) || ( g_strcasecmp( cmd[0], "NS" ) == 0 ) )
     840        {
     841                /* [SH] This aliases the NickServ command to PRIVMSG root */
     842                /* [TV] This aliases the NS command to PRIVMSG root as well */
     843                root_command( irc, cmd + 1 );
     844        }
     845        else if( g_strcasecmp( cmd[0], "MOTD" ) == 0 )
     846        {
     847                irc_motd( irc );
     848        }
     849        else if( g_strcasecmp( cmd[0], "PONG" ) == 0 )
     850        {
     851                /* We could check the value we get back from the user, but in
     852                   fact we don't care, we're just happy he's still alive. */
     853                irc->last_pong = gettime();
     854                irc->pinging = 0;
     855        }
     856        else if( g_strcasecmp( cmd[0], "COMPLETIONS" ) == 0 )
     857        {
     858                user_t *u = user_find( irc, irc->mynick );
     859                help_t *h;
     860                set_t *s;
     861                int i;
     862               
     863                irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", "OK" );
     864               
     865                for( i = 0; commands[i].command; i ++ )
     866                        irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", commands[i].command );
     867               
     868                for( h = global.help; h; h = h->next )
     869                        irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS help ", h->string );
     870               
     871                for( s = irc->set; s; s = s->next )
     872                        irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS set ", s->key );
     873               
     874                irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", "END" );
     875        }
     876        else if( g_strcasecmp( cmd[0], "DIE" ) == 0 )
     877        {
     878                printf( "%d %d\n", global.listen_socket, write( global.listen_socket, "DIE\r\n", 5 ) );
     879        }
     880        else if( set_getint( irc, "debug" ) )
     881        {
     882                irc_usermsg( irc, "\002--- Unknown command:" );
     883                for( i = 0; cmd[i]; i ++ ) irc_usermsg( irc, "%s", cmd[i] );
     884                irc_usermsg( irc, "\002--------------------" );
     885        }
     886       
     887        return( 1 );
    434888}
    435889
     
    5901044}
    5911045
    592 int irc_check_login( irc_t *irc )
    593 {
    594         if( irc->user && irc->nick )
    595         {
    596                 if( global.conf->authmode == AUTHMODE_CLOSED && irc->status < USTATUS_AUTHORIZED )
    597                 {
    598                         irc_reply( irc, 464, ":This server is password-protected." );
    599                         return 0;
    600                 }
    601                 else
    602                 {
    603                         irc_login( irc );
    604                         return 1;
    605                 }
    606         }
    607         else
    608         {
    609                 /* More information needed. */
    610                 return 0;
    611         }
     1046void irc_who( irc_t *irc, char *channel )
     1047{
     1048        user_t *u = irc->users;
     1049        struct conversation *c;
     1050        GList *l;
     1051       
     1052        if( !channel || *channel == '0' || *channel == '*' || !*channel )
     1053                while( u )
     1054                {
     1055                        irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", u->online ? irc->channel : "*", u->user, u->host, irc->myhost, u->nick, u->online ? ( u->away ? 'G' : 'H' ) : 'G', u->realname );
     1056                        u = u->next;
     1057                }
     1058        else if( g_strcasecmp( channel, irc->channel ) == 0 )
     1059                while( u )
     1060                {
     1061                        if( u->online )
     1062                                irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", channel, u->user, u->host, irc->myhost, u->nick, u->away ? 'G' : 'H', u->realname );
     1063                        u = u->next;
     1064                }
     1065        else if( ( c = conv_findchannel( channel ) ) )
     1066                for( l = c->in_room; l; l = l->next )
     1067                {
     1068                        if( ( u = user_findhandle( c->gc, l->data ) ) )
     1069                                irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", channel, u->user, u->host, irc->myhost, u->nick, u->away ? 'G' : 'H', u->realname );
     1070                }
     1071        else if( ( u = user_find( irc, channel ) ) )
     1072                irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", channel, u->user, u->host, irc->myhost, u->nick, u->online ? ( u->away ? 'G' : 'H' ) : 'G', u->realname );
     1073       
     1074        irc_reply( irc, 315, "%s :End of /WHO list.", channel?channel:"**" );
    6121075}
    6131076
     
    7211184}
    7221185
     1186void irc_whois( irc_t *irc, char *nick )
     1187{
     1188        user_t *u = user_find( irc, nick );
     1189       
     1190        if( u )
     1191        {
     1192                irc_reply( irc, 311, "%s %s %s * :%s", u->nick, u->user, u->host, u->realname );
     1193               
     1194                if( u->gc )
     1195                        irc_reply( irc, 312, "%s %s.%s :%s network", u->nick, u->gc->user->username,
     1196                                   *u->gc->user->proto_opt[0] ? u->gc->user->proto_opt[0] : "", u->gc->prpl->name );
     1197                else
     1198                        irc_reply( irc, 312, "%s %s :%s", u->nick, irc->myhost, IRCD_INFO );
     1199               
     1200                if( !u->online )
     1201                        irc_reply( irc, 301, "%s :%s", u->nick, "User is offline" );
     1202                else if( u->away )
     1203                        irc_reply( irc, 301, "%s :%s", u->nick, u->away );
     1204               
     1205                irc_reply( irc, 318, "%s :End of /WHOIS list", nick );
     1206        }
     1207        else
     1208        {
     1209                irc_reply( irc, 401, "%s :Nick does not exist", nick );
     1210        }
     1211}
     1212
     1213
    7231214void irc_umode_set( irc_t *irc, char *s, int allow_priv )
    7241215{
     
    7501241}
    7511242
     1243int irc_away( irc_t *irc, char *away )
     1244{
     1245        user_t *u = user_find( irc, irc->nick );
     1246        GSList *c = get_connections();
     1247       
     1248        if( !u ) return( 0 );
     1249       
     1250        if( away && *away )
     1251        {
     1252                int i, j;
     1253               
     1254                /* Copy away string, but skip control chars. Mainly because
     1255                   Jabber really doesn't like them. */
     1256                u->away = g_malloc( strlen( away ) + 1 );
     1257                for( i = j = 0; away[i]; i ++ )
     1258                        if( ( u->away[j] = away[i] ) >= ' ' )
     1259                                j ++;
     1260                u->away[j] = 0;
     1261               
     1262                irc_reply( irc, 306, ":You're now away: %s", u->away );
     1263                /* irc_umode_set( irc, irc->myhost, "+a" ); */
     1264        }
     1265        else
     1266        {
     1267                if( u->away ) g_free( u->away );
     1268                u->away = NULL;
     1269                /* irc_umode_set( irc, irc->myhost, "-a" ); */
     1270                irc_reply( irc, 305, ":Welcome back" );
     1271        }
     1272       
     1273        while( c )
     1274        {
     1275                if( ((struct gaim_connection *)c->data)->flags & OPT_LOGGED_IN )
     1276                        proto_away( c->data, u->away );
     1277               
     1278                c = c->next;
     1279        }
     1280       
     1281        return( 1 );
     1282}
     1283
    7521284void irc_spawn( irc_t *irc, user_t *u )
    7531285{
     
    8011333        }
    8021334        g_free( nick );
     1335}
     1336
     1337void irc_invite( irc_t *irc, char *nick, char *channel )
     1338{
     1339        struct conversation *c = conv_findchannel( channel );
     1340        user_t *u = user_find( irc, nick );
     1341       
     1342        if( u && c && ( u->gc == c->gc ) )
     1343                if( c->gc && c->gc->prpl && c->gc->prpl->chat_invite )
     1344                {
     1345                        c->gc->prpl->chat_invite( c->gc, c->id, "", u->handle );
     1346                        irc_reply( irc, 341, "%s %s", nick, channel );
     1347                        return;
     1348                }
     1349       
     1350        irc_reply( irc, 482, "%s :Invite impossible; User/Channel non-existent or incompatible", channel );
    8031351}
    8041352
  • irc.h

    r0431ea1 r9d6b229  
    3333#define IRC_PING_STRING "PinglBee"
    3434
    35 #define UMODES "iasw"
     35#define UMODES "ias"
    3636#define UMODES_PRIV "Ro"
    3737#define CMODES "nt"
     
    108108int irc_exec( irc_t *irc, char **cmd );
    109109int irc_process( irc_t *irc );
    110 char **irc_parse_line( char *line );
     110int irc_process_line( irc_t *irc, char *line );
    111111
    112112void irc_vawrite( irc_t *irc, char *format, va_list params );
     
    118118
    119119void irc_login( irc_t *irc );
    120 int irc_check_login( irc_t *irc );
    121120void irc_motd( irc_t *irc );
    122121void irc_names( irc_t *irc, char *channel );
Note: See TracChangeset for help on using the changeset viewer.