Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • protocols/nogaim.c

    r3663bb3 r839189b  
    3838#include "chat.h"
    3939
     40static int remove_chat_buddy_silent( struct groupchat *b, const char *handle );
     41static char *format_timestamp( irc_t *irc, time_t msg_ts );
     42
    4043GSList *connections;
    4144
     
    8992}
    9093#endif
     94
     95/* nogaim.c */
    9196
    9297GList *protocols = NULL;
     
    121126}
    122127
     128/* nogaim.c */
    123129void nogaim_init()
    124130{
     
    156162GSList *get_connections() { return connections; }
    157163
     164/* multi.c */
     165
    158166struct im_connection *imcb_new( account_t *acc )
    159167{
     
    162170        ic = g_new0( struct im_connection, 1 );
    163171       
    164         ic->bee = acc->bee;
     172        ic->irc = acc->irc;
    165173        ic->acc = acc;
    166174        acc->ic = ic;
     
    176184       
    177185        /* Destroy the pointer to this connection from the account list */
    178         for( a = ic->bee->accounts; a; a = a->next )
     186        for( a = ic->irc->accounts; a; a = a->next )
    179187                if( a->ic == ic )
    180188                {
     
    197205        va_end( params );
    198206
    199         if( ( g_strcasecmp( set_getstr( &ic->bee->set, "strip_html" ), "always" ) == 0 ) ||
    200             ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->bee->set, "strip_html" ) ) )
     207        if( ( g_strcasecmp( set_getstr( &ic->irc->set, "strip_html" ), "always" ) == 0 ) ||
     208            ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) )
    201209                strip_html( text );
    202210       
    203211        /* Try to find a different connection on the same protocol. */
    204         for( a = ic->bee->accounts; a; a = a->next )
     212        for( a = ic->irc->accounts; a; a = a->next )
    205213                if( a->prpl == ic->acc->prpl && a->ic != ic )
    206214                        break;
     
    208216        /* If we found one, include the screenname in the message. */
    209217        if( a )
    210                 /* FIXME(wilmer): ui_log callback or so */
    211                 irc_usermsg( ic->bee->ui_data, "%s(%s) - %s", ic->acc->prpl->name, ic->acc->user, text );
     218                irc_usermsg( ic->irc, "%s(%s) - %s", ic->acc->prpl->name, ic->acc->user, text );
    212219        else
    213                 irc_usermsg( ic->bee->ui_data, "%s - %s", ic->acc->prpl->name, text );
     220                irc_usermsg( ic->irc, "%s - %s", ic->acc->prpl->name, text );
    214221       
    215222        g_free( text );
     
    262269void imcb_connected( struct im_connection *ic )
    263270{
     271        irc_t *irc = ic->irc;
     272        struct chat *c;
     273        user_t *u;
     274       
    264275        /* MSN servers sometimes redirect you to a different server and do
    265276           the whole login sequence again, so these "late" calls to this
     
    268279                return;
    269280       
     281        u = user_find( ic->irc, ic->irc->nick );
     282       
    270283        imcb_log( ic, "Logged in" );
    271284       
     
    280293        ic->acc->auto_reconnect_delay = 0;
    281294       
    282         /*
    283295        for( c = irc->chatrooms; c; c = c->next )
    284296        {
     
    289301                        chat_join( irc, c, NULL );
    290302        }
    291         */
    292303}
    293304
     
    297308       
    298309        a->reconnect = 0;
    299         account_on( a->bee, a );
     310        account_on( a->irc, a );
    300311       
    301312        return( FALSE );        /* Only have to run the timeout once */
     
    310321void imc_logout( struct im_connection *ic, int allow_reconnect )
    311322{
    312         bee_t *bee = ic->bee;
     323        irc_t *irc = ic->irc;
     324        user_t *t, *u;
    313325        account_t *a;
    314         GSList *l;
    315326        int delay;
    316327       
     
    332343        ic->away = NULL;
    333344       
    334         for( l = bee->users; l; )
    335         {
    336                 bee_user_t *bu = l->data;
    337                 GSList *next = l->next;
    338                
    339                 if( bu->ic == ic )
    340                         bee_user_free( bee, bu );
    341                
    342                 l = next;
    343         }
    344        
    345         query_del_by_conn( (irc_t*) ic->bee->ui_data, ic );
    346        
    347         for( a = bee->accounts; a; a = a->next )
     345        u = irc->users;
     346        while( u )
     347        {
     348                if( u->ic == ic )
     349                {
     350                        t = u->next;
     351                        user_del( irc, u->nick );
     352                        u = t;
     353                }
     354                else
     355                        u = u->next;
     356        }
     357       
     358        query_del_by_conn( ic->irc, ic );
     359       
     360        for( a = irc->accounts; a; a = a->next )
    348361                if( a->ic == ic )
    349362                        break;
     
    353366                /* Uhm... This is very sick. */
    354367        }
    355         else if( allow_reconnect && set_getbool( &bee->set, "auto_reconnect" ) &&
     368        else if( allow_reconnect && set_getbool( &irc->set, "auto_reconnect" ) &&
    356369                 set_getbool( &a->set, "auto_reconnect" ) &&
    357370                 ( delay = account_reconnect_delay( a ) ) > 0 )
     
    364377}
    365378
     379
     380/* dialogs.c */
     381
    366382void imcb_ask( struct im_connection *ic, char *msg, void *data,
    367383               query_callback doit, query_callback dont )
    368384{
    369         query_add( (irc_t *) ic->bee->ui_data, ic, msg, doit, dont, data );
    370 }
     385        query_add( ic->irc, ic, msg, doit, dont, data );
     386}
     387
     388
     389/* list.c */
    371390
    372391void imcb_add_buddy( struct im_connection *ic, const char *handle, const char *group )
    373392{
    374         bee_user_t *bu;
    375         bee_t *bee = ic->bee;
    376        
    377         if( !( bu = bee_user_by_handle( bee, ic, handle ) ) )
    378                 bu = bee_user_new( bee, ic, handle );
    379        
    380         bu->group = bee_group_by_name( bee, group, TRUE );
    381 }
    382 
    383 void imcb_rename_buddy( struct im_connection *ic, const char *handle, const char *fullname )
    384 {
    385         bee_t *bee = ic->bee;
    386         bee_user_t *bu = bee_user_by_handle( bee, ic, handle );
    387        
    388         if( !bu || !fullname ) return;
    389        
    390         if( !bu->fullname || strcmp( bu->fullname, fullname ) != 0 )
    391         {
    392                 g_free( bu->fullname );
    393                 bu->fullname = g_strdup( fullname );
    394                
    395                 if( bee->ui->user_fullname )
    396                         bee->ui->user_fullname( bee, bu );
     393        user_t *u;
     394        char nick[MAX_NICK_LENGTH+1], *s;
     395        irc_t *irc = ic->irc;
     396       
     397        if( user_findhandle( ic, handle ) )
     398        {
     399                if( set_getbool( &irc->set, "debug" ) )
     400                        imcb_log( ic, "User already exists, ignoring add request: %s", handle );
     401               
     402                return;
     403               
     404                /* Buddy seems to exist already. Let's ignore this request then...
     405                   Eventually subsequent calls to this function *should* be possible
     406                   when a buddy is in multiple groups. But for now BitlBee doesn't
     407                   even support groups so let's silently ignore this for now. */
     408        }
     409       
     410        memset( nick, 0, MAX_NICK_LENGTH + 1 );
     411        strcpy( nick, nick_get( ic->acc, handle ) );
     412       
     413        u = user_add( ic->irc, nick );
     414       
     415//      if( !realname || !*realname ) realname = nick;
     416//      u->realname = g_strdup( realname );
     417       
     418        if( ( s = strchr( handle, '@' ) ) )
     419        {
     420                u->host = g_strdup( s + 1 );
     421                u->user = g_strndup( handle, s - handle );
     422        }
     423        else if( ic->acc->server )
     424        {
     425                u->host = g_strdup( ic->acc->server );
     426                u->user = g_strdup( handle );
     427               
     428                /* s/ /_/ ... important for AOL screennames */
     429                for( s = u->user; *s; s ++ )
     430                        if( *s == ' ' )
     431                                *s = '_';
     432        }
     433        else
     434        {
     435                u->host = g_strdup( ic->acc->prpl->name );
     436                u->user = g_strdup( handle );
     437        }
     438       
     439        u->ic = ic;
     440        u->handle = g_strdup( handle );
     441        if( group ) u->group = g_strdup( group );
     442        u->send_handler = buddy_send_handler;
     443        u->last_typing_notice = 0;
     444}
     445
     446struct buddy *imcb_find_buddy( struct im_connection *ic, char *handle )
     447{
     448        static struct buddy b[1];
     449        user_t *u;
     450       
     451        u = user_findhandle( ic, handle );
     452       
     453        if( !u )
     454                return( NULL );
     455       
     456        memset( b, 0, sizeof( b ) );
     457        strncpy( b->name, handle, 80 );
     458        strncpy( b->show, u->realname, BUDDY_ALIAS_MAXLEN );
     459        b->present = u->online;
     460        b->ic = u->ic;
     461       
     462        return( b );
     463}
     464
     465void imcb_rename_buddy( struct im_connection *ic, const char *handle, const char *realname )
     466{
     467        user_t *u = user_findhandle( ic, handle );
     468        char *set;
     469       
     470        if( !u || !realname ) return;
     471       
     472        if( g_strcasecmp( u->realname, realname ) != 0 )
     473        {
     474                if( u->realname != u->nick ) g_free( u->realname );
     475               
     476                u->realname = g_strdup( realname );
     477               
     478                if( ( ic->flags & OPT_LOGGED_IN ) && set_getbool( &ic->irc->set, "display_namechanges" ) )
     479                        imcb_log( ic, "User `%s' changed name to `%s'", u->nick, u->realname );
     480        }
     481       
     482        set = set_getstr( &ic->acc->set, "nick_source" );
     483        if( strcmp( set, "handle" ) != 0 )
     484        {
     485                char *name = g_strdup( realname );
     486               
     487                if( strcmp( set, "first_name" ) == 0 )
     488                {
     489                        int i;
     490                        for( i = 0; name[i] && !isspace( name[i] ); i ++ ) {}
     491                        name[i] = '\0';
     492                }
     493               
     494                imcb_buddy_nick_hint( ic, handle, name );
     495               
     496                g_free( name );
    397497        }
    398498}
     
    400500void imcb_remove_buddy( struct im_connection *ic, const char *handle, char *group )
    401501{
    402         bee_user_free( ic->bee, bee_user_by_handle( ic->bee, ic, handle ) );
     502        user_t *u;
     503       
     504        if( ( u = user_findhandle( ic, handle ) ) )
     505                user_del( ic->irc, u->nick );
    403506}
    404507
     
    407510void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick )
    408511{
    409 #if 0
    410512        user_t *u = user_findhandle( ic, handle );
    411513        char newnick[MAX_NICK_LENGTH+1], *orig_nick;
     
    422524                /* Some processing to make sure this string is a valid IRC nickname. */
    423525                nick_strip( newnick );
    424                 if( set_getbool( &ic->bee->set, "lcnicks" ) )
     526                if( set_getbool( &ic->irc->set, "lcnicks" ) )
    425527                        nick_lc( newnick );
    426528               
     
    439541                }
    440542        }
    441 #endif
    442543}
    443544
     
    484585        data->ic = ic;
    485586        data->handle = g_strdup( handle );
    486         query_add( (irc_t *) ic->bee->ui_data, ic, s,
    487                    imcb_ask_auth_cb_yes, imcb_ask_auth_cb_no, data );
     587        query_add( ic->irc, ic, s, imcb_ask_auth_cb_yes, imcb_ask_auth_cb_no, data );
    488588}
    489589
     
    510610       
    511611        /* TODO: Make a setting for this! */
    512         if( bee_user_by_handle( ic->bee, ic, handle ) != NULL )
     612        if( user_findhandle( ic, handle ) != NULL )
    513613                return;
    514614       
     
    517617        data->ic = ic;
    518618        data->handle = g_strdup( handle );
    519         query_add( (irc_t *) ic->bee->ui_data, ic, s,
    520                    imcb_ask_add_cb_yes, imcb_ask_add_cb_no, data );
    521 }
    522 
    523 struct bee_user *imcb_buddy_by_handle( struct im_connection *ic, const char *handle )
    524 {
    525         return bee_user_by_handle( ic->bee, ic, handle );
     619        query_add( ic->irc, ic, s, imcb_ask_add_cb_yes, imcb_ask_add_cb_no, data );
     620}
     621
     622
     623/* server.c */                   
     624
     625void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, const char *state, const char *message )
     626{
     627        user_t *u;
     628        int oa, oo;
     629       
     630        u = user_findhandle( ic, (char*) handle );
     631       
     632        if( !u )
     633        {
     634                if( g_strcasecmp( set_getstr( &ic->irc->set, "handle_unknown" ), "add" ) == 0 )
     635                {
     636                        imcb_add_buddy( ic, (char*) handle, NULL );
     637                        u = user_findhandle( ic, (char*) handle );
     638                }
     639                else
     640                {
     641                        if( set_getbool( &ic->irc->set, "debug" ) || g_strcasecmp( set_getstr( &ic->irc->set, "handle_unknown" ), "ignore" ) != 0 )
     642                        {
     643                                imcb_log( ic, "imcb_buddy_status() for unknown handle %s:", handle );
     644                                imcb_log( ic, "flags = %d, state = %s, message = %s", flags,
     645                                          state ? state : "NULL", message ? message : "NULL" );
     646                        }
     647                       
     648                        return;
     649                }
     650        }
     651       
     652        oa = u->away != NULL;
     653        oo = u->online;
     654       
     655        g_free( u->away );
     656        g_free( u->status_msg );
     657        u->away = u->status_msg = NULL;
     658       
     659        if( set_getbool( &ic->irc->set, "show_offline" ) && !u->online )
     660        {
     661                /* always set users as online */
     662                irc_spawn( ic->irc, u );
     663                u->online = 1;
     664                if( !( flags & OPT_LOGGED_IN ) )
     665                {
     666                        /* set away message if user isn't really online */
     667                        u->away = g_strdup( "User is offline" );
     668                }
     669        }
     670        else if( ( flags & OPT_LOGGED_IN ) && !u->online )
     671        {
     672                irc_spawn( ic->irc, u );
     673                u->online = 1;
     674        }
     675        else if( !( flags & OPT_LOGGED_IN ) && u->online )
     676        {
     677                struct groupchat *c;
     678               
     679                if( set_getbool( &ic->irc->set, "show_offline" ) )
     680                {
     681                        /* keep offline users in channel and set away message to "offline" */
     682                        u->away = g_strdup( "User is offline" );
     683
     684                        /* Keep showing him/her in the control channel but not in groupchats. */
     685                        for( c = ic->groupchats; c; c = c->next )
     686                        {
     687                                if( remove_chat_buddy_silent( c, handle ) && c->joined )
     688                                        irc_part( c->ic->irc, u, c->channel );
     689                        }
     690                }
     691                else
     692                {
     693                        /* kill offline users */
     694                        irc_kill( ic->irc, u );
     695                        u->online = 0;
     696
     697                        /* Remove him/her from the groupchats to prevent PART messages after he/she QUIT already */
     698                        for( c = ic->groupchats; c; c = c->next )
     699                                remove_chat_buddy_silent( c, handle );
     700                }
     701        }
     702
     703        if( flags & OPT_AWAY )
     704        {
     705                if( state && message )
     706                {
     707                        u->away = g_strdup_printf( "%s (%s)", state, message );
     708                }
     709                else if( state )
     710                {
     711                        u->away = g_strdup( state );
     712                }
     713                else if( message )
     714                {
     715                        u->away = g_strdup( message );
     716                }
     717                else
     718                {
     719                        u->away = g_strdup( "Away" );
     720                }
     721        }
     722        else
     723        {
     724                u->status_msg = g_strdup( message );
     725        }
     726       
     727        /* early if-clause for show_offline even if there is some redundant code here because this isn't LISP but C ;) */
     728        if( set_getbool( &ic->irc->set, "show_offline" ) && set_getbool( &ic->irc->set, "away_devoice" ) )
     729        {
     730                char *from;
     731               
     732                if( set_getbool( &ic->irc->set, "simulate_netsplit" ) )
     733                {
     734                        from = g_strdup( ic->irc->myhost );
     735                }
     736                else
     737                {
     738                        from = g_strdup_printf( "%s!%s@%s", ic->irc->mynick, ic->irc->mynick,
     739                                                            ic->irc->myhost );
     740                }
     741
     742                /* if we use show_offline, we op online users, voice away users, and devoice/deop offline users */
     743                if( flags & OPT_LOGGED_IN )
     744                {
     745                        /* user is "online" (either really online or away) */
     746                        irc_write( ic->irc, ":%s MODE %s %cv%co %s %s", from, ic->irc->channel,
     747                                                                  u->away?'+':'-', u->away?'-':'+', u->nick, u->nick );
     748                }
     749                else
     750                {
     751                        /* user is offline */
     752                        irc_write( ic->irc, ":%s MODE %s -vo %s %s", from, ic->irc->channel, u->nick, u->nick );
     753                }
     754        }
     755        else
     756        {
     757                /* LISPy... */
     758                if( ( set_getbool( &ic->irc->set, "away_devoice" ) ) &&         /* Don't do a thing when user doesn't want it */
     759                    ( u->online ) &&                                            /* Don't touch offline people */
     760                    ( ( ( u->online != oo ) && !u->away ) ||                    /* Voice joining people */
     761                      ( ( u->online == oo ) && ( oa == !u->away ) ) ) )         /* (De)voice people changing state */
     762                {
     763                        char *from;
     764
     765                        if( set_getbool( &ic->irc->set, "simulate_netsplit" ) )
     766                        {
     767                                from = g_strdup( ic->irc->myhost );
     768                        }
     769                        else
     770                        {
     771                                from = g_strdup_printf( "%s!%s@%s", ic->irc->mynick, ic->irc->mynick,
     772                                                                    ic->irc->myhost );
     773                        }
     774                        irc_write( ic->irc, ":%s MODE %s %cv %s", from, ic->irc->channel,
     775                                                                  u->away?'-':'+', u->nick );
     776                        g_free( from );
     777                }
     778        }
     779}
     780
     781void imcb_buddy_msg( struct im_connection *ic, const char *handle, char *msg, uint32_t flags, time_t sent_at )
     782{
     783        irc_t *irc = ic->irc;
     784        char *wrapped, *ts = NULL;
     785        user_t *u;
     786       
     787        u = user_findhandle( ic, handle );
     788       
     789        if( !u )
     790        {
     791                char *h = set_getstr( &irc->set, "handle_unknown" );
     792               
     793                if( g_strcasecmp( h, "ignore" ) == 0 )
     794                {
     795                        if( set_getbool( &irc->set, "debug" ) )
     796                                imcb_log( ic, "Ignoring message from unknown handle %s", handle );
     797                       
     798                        return;
     799                }
     800                else if( g_strncasecmp( h, "add", 3 ) == 0 )
     801                {
     802                        int private = set_getbool( &irc->set, "private" );
     803                       
     804                        if( h[3] )
     805                        {
     806                                if( g_strcasecmp( h + 3, "_private" ) == 0 )
     807                                        private = 1;
     808                                else if( g_strcasecmp( h + 3, "_channel" ) == 0 )
     809                                        private = 0;
     810                        }
     811                       
     812                        imcb_add_buddy( ic, handle, NULL );
     813                        u = user_findhandle( ic, handle );
     814                        u->is_private = private;
     815                }
     816                else
     817                {
     818                        imcb_log( ic, "Message from unknown handle %s:", handle );
     819                        u = user_find( irc, irc->mynick );
     820                }
     821        }
     822       
     823        if( ( g_strcasecmp( set_getstr( &ic->irc->set, "strip_html" ), "always" ) == 0 ) ||
     824            ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) )
     825                strip_html( msg );
     826       
     827        if( set_getbool( &ic->irc->set, "display_timestamps" ) &&
     828            ( ts = format_timestamp( irc, sent_at ) ) )
     829        {
     830                char *new = g_strconcat( ts, msg, NULL );
     831                g_free( ts );
     832                ts = msg = new;
     833        }
     834       
     835        wrapped = word_wrap( msg, 425 );
     836        irc_msgfrom( irc, u->nick, wrapped );
     837        g_free( wrapped );
     838        g_free( ts );
     839}
     840
     841void imcb_buddy_typing( struct im_connection *ic, char *handle, uint32_t flags )
     842{
     843        user_t *u;
     844       
     845        if( !set_getbool( &ic->irc->set, "typing_notice" ) )
     846                return;
     847       
     848        if( ( u = user_findhandle( ic, handle ) ) )
     849        {
     850                char buf[256];
     851               
     852                g_snprintf( buf, 256, "\1TYPING %d\1", ( flags >> 8 ) & 3 );
     853                irc_privmsg( ic->irc, u, "PRIVMSG", ic->irc->nick, NULL, buf );
     854        }
     855}
     856
     857struct groupchat *imcb_chat_new( struct im_connection *ic, const char *handle )
     858{
     859        struct groupchat *c;
     860       
     861        /* This one just creates the conversation structure, user won't see anything yet */
     862       
     863        if( ic->groupchats )
     864        {
     865                for( c = ic->groupchats; c->next; c = c->next );
     866                c = c->next = g_new0( struct groupchat, 1 );
     867        }
     868        else
     869                ic->groupchats = c = g_new0( struct groupchat, 1 );
     870       
     871        c->ic = ic;
     872        c->title = g_strdup( handle );
     873        c->channel = g_strdup_printf( "&chat_%03d", ic->irc->c_id++ );
     874        c->topic = g_strdup_printf( "BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", c->title );
     875       
     876        if( set_getbool( &ic->irc->set, "debug" ) )
     877                imcb_log( ic, "Creating new conversation: (id=%p,handle=%s)", c, handle );
     878       
     879        return c;
     880}
     881
     882void imcb_chat_name_hint( struct groupchat *c, const char *name )
     883{
     884        if( !c->joined )
     885        {
     886                struct im_connection *ic = c->ic;
     887                char stripped[MAX_NICK_LENGTH+1], *full_name;
     888               
     889                strncpy( stripped, name, MAX_NICK_LENGTH );
     890                stripped[MAX_NICK_LENGTH] = '\0';
     891                nick_strip( stripped );
     892                if( set_getbool( &ic->irc->set, "lcnicks" ) )
     893                        nick_lc( stripped );
     894               
     895                full_name = g_strdup_printf( "&%s", stripped );
     896               
     897                if( stripped[0] &&
     898                    nick_cmp( stripped, ic->irc->channel + 1 ) != 0 &&
     899                    irc_chat_by_channel( ic->irc, full_name ) == NULL )
     900                {
     901                        g_free( c->channel );
     902                        c->channel = full_name;
     903                }
     904                else
     905                {
     906                        g_free( full_name );
     907                }
     908        }
     909}
     910
     911void imcb_chat_free( struct groupchat *c )
     912{
     913        struct im_connection *ic = c->ic;
     914        struct groupchat *l;
     915        GList *ir;
     916       
     917        if( set_getbool( &ic->irc->set, "debug" ) )
     918                imcb_log( ic, "You were removed from conversation %p", c );
     919       
     920        if( c )
     921        {
     922                if( c->joined )
     923                {
     924                        user_t *u, *r;
     925                       
     926                        r = user_find( ic->irc, ic->irc->mynick );
     927                        irc_privmsg( ic->irc, r, "PRIVMSG", c->channel, "", "Cleaning up channel, bye!" );
     928                       
     929                        u = user_find( ic->irc, ic->irc->nick );
     930                        irc_kick( ic->irc, u, c->channel, r );
     931                        /* irc_part( ic->irc, u, c->channel ); */
     932                }
     933               
     934                /* Find the previous chat in the linked list. */
     935                for( l = ic->groupchats; l && l->next != c; l = l->next );
     936               
     937                if( l )
     938                        l->next = c->next;
     939                else
     940                        ic->groupchats = c->next;
     941               
     942                for( ir = c->in_room; ir; ir = ir->next )
     943                        g_free( ir->data );
     944                g_list_free( c->in_room );
     945                g_free( c->channel );
     946                g_free( c->title );
     947                g_free( c->topic );
     948                g_free( c );
     949        }
     950}
     951
     952void imcb_chat_msg( struct groupchat *c, const char *who, char *msg, uint32_t flags, time_t sent_at )
     953{
     954        struct im_connection *ic = c->ic;
     955        char *wrapped;
     956        user_t *u;
     957       
     958        /* Gaim sends own messages through this too. IRC doesn't want this, so kill them */
     959        if( g_strcasecmp( who, ic->acc->user ) == 0 )
     960                return;
     961       
     962        u = user_findhandle( ic, who );
     963       
     964        if( ( g_strcasecmp( set_getstr( &ic->irc->set, "strip_html" ), "always" ) == 0 ) ||
     965            ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) )
     966                strip_html( msg );
     967       
     968        wrapped = word_wrap( msg, 425 );
     969        if( c && u )
     970        {
     971                char *ts = NULL;
     972                if( set_getbool( &ic->irc->set, "display_timestamps" ) )
     973                        ts = format_timestamp( ic->irc, sent_at );
     974                irc_privmsg( ic->irc, u, "PRIVMSG", c->channel, ts ? : "", wrapped );
     975                g_free( ts );
     976        }
     977        else
     978        {
     979                imcb_log( ic, "Message from/to conversation %s@%p (unknown conv/user): %s", who, c, wrapped );
     980        }
     981        g_free( wrapped );
     982}
     983
     984void imcb_chat_log( struct groupchat *c, char *format, ... )
     985{
     986        irc_t *irc = c->ic->irc;
     987        va_list params;
     988        char *text;
     989        user_t *u;
     990       
     991        va_start( params, format );
     992        text = g_strdup_vprintf( format, params );
     993        va_end( params );
     994       
     995        u = user_find( irc, irc->mynick );
     996       
     997        irc_privmsg( irc, u, "PRIVMSG", c->channel, "System message: ", text );
     998       
     999        g_free( text );
     1000}
     1001
     1002void imcb_chat_topic( struct groupchat *c, char *who, char *topic, time_t set_at )
     1003{
     1004        struct im_connection *ic = c->ic;
     1005        user_t *u = NULL;
     1006       
     1007        if( who == NULL)
     1008                u = user_find( ic->irc, ic->irc->mynick );
     1009        else if( g_strcasecmp( who, ic->acc->user ) == 0 )
     1010                u = user_find( ic->irc, ic->irc->nick );
     1011        else
     1012                u = user_findhandle( ic, who );
     1013       
     1014        if( ( g_strcasecmp( set_getstr( &ic->irc->set, "strip_html" ), "always" ) == 0 ) ||
     1015            ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) )
     1016                strip_html( topic );
     1017       
     1018        g_free( c->topic );
     1019        c->topic = g_strdup( topic );
     1020       
     1021        if( c->joined && u )
     1022                irc_write( ic->irc, ":%s!%s@%s TOPIC %s :%s", u->nick, u->user, u->host, c->channel, topic );
     1023}
     1024
     1025
     1026/* buddy_chat.c */
     1027
     1028void imcb_chat_add_buddy( struct groupchat *b, const char *handle )
     1029{
     1030        user_t *u = user_findhandle( b->ic, handle );
     1031        int me = 0;
     1032       
     1033        if( set_getbool( &b->ic->irc->set, "debug" ) )
     1034                imcb_log( b->ic, "User %s added to conversation %p", handle, b );
     1035       
     1036        /* It might be yourself! */
     1037        if( b->ic->acc->prpl->handle_cmp( handle, b->ic->acc->user ) == 0 )
     1038        {
     1039                u = user_find( b->ic->irc, b->ic->irc->nick );
     1040                if( !b->joined )
     1041                        irc_join( b->ic->irc, u, b->channel );
     1042                b->joined = me = 1;
     1043        }
     1044       
     1045        /* Most protocols allow people to join, even when they're not in
     1046           your contact list. Try to handle that here */
     1047        if( !u )
     1048        {
     1049                imcb_add_buddy( b->ic, handle, NULL );
     1050                u = user_findhandle( b->ic, handle );
     1051        }
     1052       
     1053        /* Add the handle to the room userlist, if it's not 'me' */
     1054        if( !me )
     1055        {
     1056                if( b->joined )
     1057                        irc_join( b->ic->irc, u, b->channel );
     1058                b->in_room = g_list_append( b->in_room, g_strdup( handle ) );
     1059        }
     1060}
     1061
     1062/* This function is one BIG hack... :-( EREWRITE */
     1063void imcb_chat_remove_buddy( struct groupchat *b, const char *handle, const char *reason )
     1064{
     1065        user_t *u;
     1066        int me = 0;
     1067       
     1068        if( set_getbool( &b->ic->irc->set, "debug" ) )
     1069                imcb_log( b->ic, "User %s removed from conversation %p (%s)", handle, b, reason ? reason : "" );
     1070       
     1071        /* It might be yourself! */
     1072        if( g_strcasecmp( handle, b->ic->acc->user ) == 0 )
     1073        {
     1074                if( b->joined == 0 )
     1075                        return;
     1076               
     1077                u = user_find( b->ic->irc, b->ic->irc->nick );
     1078                b->joined = 0;
     1079                me = 1;
     1080        }
     1081        else
     1082        {
     1083                u = user_findhandle( b->ic, handle );
     1084        }
     1085       
     1086        if( me || ( remove_chat_buddy_silent( b, handle ) && b->joined && u ) )
     1087                irc_part( b->ic->irc, u, b->channel );
     1088}
     1089
     1090static int remove_chat_buddy_silent( struct groupchat *b, const char *handle )
     1091{
     1092        GList *i;
     1093       
     1094        /* Find the handle in the room userlist and shoot it */
     1095        i = b->in_room;
     1096        while( i )
     1097        {
     1098                if( g_strcasecmp( handle, i->data ) == 0 )
     1099                {
     1100                        g_free( i->data );
     1101                        b->in_room = g_list_remove( b->in_room, i->data );
     1102                        return( 1 );
     1103                }
     1104               
     1105                i = i->next;
     1106        }
     1107       
     1108        return( 0 );
    5261109}
    5271110
    5281111
    5291112/* Misc. BitlBee stuff which shouldn't really be here */
    530 #if 0
     1113
    5311114char *set_eval_away_devoice( set_t *set, char *value )
    5321115{
     
    5411124        /* Horror.... */
    5421125       
    543         if( st != set_getbool( &irc->b->set, "away_devoice" ) )
     1126        if( st != set_getbool( &irc->set, "away_devoice" ) )
    5441127        {
    5451128                char list[80] = "";
     
    5831166        return value;
    5841167}
    585 #endif
     1168
     1169char *set_eval_timezone( set_t *set, char *value )
     1170{
     1171        char *s;
     1172       
     1173        if( strcmp( value, "local" ) == 0 ||
     1174            strcmp( value, "gmt" ) == 0 || strcmp( value, "utc" ) == 0 )
     1175                return value;
     1176       
     1177        /* Otherwise: +/- at the beginning optional, then one or more numbers,
     1178           possibly followed by a colon and more numbers. Don't bother bound-
     1179           checking them since users are free to shoot themselves in the foot. */
     1180        s = value;
     1181        if( *s == '+' || *s == '-' )
     1182                s ++;
     1183       
     1184        /* \d+ */
     1185        if( !isdigit( *s ) )
     1186                return SET_INVALID;
     1187        while( *s && isdigit( *s ) ) s ++;
     1188       
     1189        /* EOS? */
     1190        if( *s == '\0' )
     1191                return value;
     1192       
     1193        /* Otherwise, colon */
     1194        if( *s != ':' )
     1195                return SET_INVALID;
     1196        s ++;
     1197       
     1198        /* \d+ */
     1199        if( !isdigit( *s ) )
     1200                return SET_INVALID;
     1201        while( *s && isdigit( *s ) ) s ++;
     1202       
     1203        /* EOS */
     1204        return *s == '\0' ? value : SET_INVALID;
     1205}
     1206
     1207static char *format_timestamp( irc_t *irc, time_t msg_ts )
     1208{
     1209        time_t now_ts = time( NULL );
     1210        struct tm now, msg;
     1211        char *set;
     1212       
     1213        /* If the timestamp is <= 0 or less than a minute ago, discard it as
     1214           it doesn't seem to add to much useful info and/or might be noise. */
     1215        if( msg_ts <= 0 || msg_ts > now_ts - 60 )
     1216                return NULL;
     1217       
     1218        set = set_getstr( &irc->set, "timezone" );
     1219        if( strcmp( set, "local" ) == 0 )
     1220        {
     1221                localtime_r( &now_ts, &now );
     1222                localtime_r( &msg_ts, &msg );
     1223        }
     1224        else
     1225        {
     1226                int hr, min = 0, sign = 60;
     1227               
     1228                if( set[0] == '-' )
     1229                {
     1230                        sign *= -1;
     1231                        set ++;
     1232                }
     1233                else if( set[0] == '+' )
     1234                {
     1235                        set ++;
     1236                }
     1237               
     1238                if( sscanf( set, "%d:%d", &hr, &min ) >= 1 )
     1239                {
     1240                        msg_ts += sign * ( hr * 60 + min );
     1241                        now_ts += sign * ( hr * 60 + min );
     1242                }
     1243               
     1244                gmtime_r( &now_ts, &now );
     1245                gmtime_r( &msg_ts, &msg );
     1246        }
     1247       
     1248        if( msg.tm_year == now.tm_year && msg.tm_yday == now.tm_yday )
     1249                return g_strdup_printf( "\x02[\x02\x02\x02%02d:%02d:%02d\x02]\x02 ",
     1250                                        msg.tm_hour, msg.tm_min, msg.tm_sec );
     1251        else
     1252                return g_strdup_printf( "\x02[\x02\x02\x02%04d-%02d-%02d "
     1253                                        "%02d:%02d:%02d\x02]\x02 ",
     1254                                        msg.tm_year + 1900, msg.tm_mon + 1, msg.tm_mday,
     1255                                        msg.tm_hour, msg.tm_min, msg.tm_sec );
     1256}
    5861257
    5871258/* The plan is to not allow straight calls to prpl functions anymore, but do
    5881259   them all from some wrappers. We'll start to define some down here: */
     1260
     1261int imc_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags )
     1262{
     1263        char *buf = NULL;
     1264        int st;
     1265       
     1266        if( ( ic->flags & OPT_DOES_HTML ) && ( g_strncasecmp( msg, "<html>", 6 ) != 0 ) )
     1267        {
     1268                buf = escape_html( msg );
     1269                msg = buf;
     1270        }
     1271       
     1272        st = ic->acc->prpl->buddy_msg( ic, handle, msg, flags );
     1273        g_free( buf );
     1274       
     1275        return st;
     1276}
    5891277
    5901278int imc_chat_msg( struct groupchat *c, char *msg, int flags )
     
    6151303       
    6161304        away = set_getstr( &ic->acc->set, "away" ) ?
    617              : set_getstr( &ic->bee->set, "away" );
     1305             : set_getstr( &ic->irc->set, "away" );
    6181306        if( away && *away )
    6191307        {
     
    6261314                away = NULL;
    6271315                msg = set_getstr( &ic->acc->set, "status" ) ?
    628                     : set_getstr( &ic->bee->set, "status" );
     1316                    : set_getstr( &ic->irc->set, "status" );
    6291317        }
    6301318       
Note: See TracChangeset for help on using the changeset viewer.