diff options
Diffstat (limited to 'account.c')
-rw-r--r-- | account.c | 162 |
1 files changed, 143 insertions, 19 deletions
@@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2004 Wilmer van der Gaast and others * + * Copyright 2002-2010 Wilmer van der Gaast and others * \********************************************************************/ /* Account management functions */ @@ -26,6 +26,7 @@ #define BITLBEE_CORE #include "bitlbee.h" #include "account.h" +#include "chat.h" account_t *account_add( irc_t *irc, struct prpl *prpl, char *user, char *pass ) { @@ -53,8 +54,10 @@ account_t *account_add( irc_t *irc, struct prpl *prpl, char *user, char *pass ) s = set_add( &a->set, "auto_reconnect", "true", set_eval_bool, a ); + s = set_add( &a->set, "nick_source", "handle", NULL, a ); + s = set_add( &a->set, "password", NULL, set_eval_account, a ); - s->flags |= ACC_SET_NOSAVE; + s->flags |= ACC_SET_NOSAVE | SET_NULL_OK; s = set_add( &a->set, "username", NULL, set_eval_account, a ); s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY; @@ -67,7 +70,16 @@ account_t *account_add( irc_t *irc, struct prpl *prpl, char *user, char *pass ) if( prpl->init ) prpl->init( a ); - return( a ); + s = set_add( &a->set, "away", NULL, set_eval_account, a ); + s->flags |= SET_NULL_OK; + + if( a->flags & ACC_FLAG_STATUS_MESSAGE ) + { + s = set_add( &a->set, "status", NULL, set_eval_account, a ); + s->flags |= SET_NULL_OK; + } + + return a; } char *set_eval_account( set_t *set, char *value ) @@ -76,9 +88,23 @@ char *set_eval_account( set_t *set, char *value ) /* Double-check: We refuse to edit on-line accounts. */ if( set->flags & ACC_SET_OFFLINE_ONLY && acc->ic ) - return NULL; + return SET_INVALID; - if( strcmp( set->key, "username" ) == 0 ) + if( strcmp( set->key, "server" ) == 0 ) + { + g_free( acc->server ); + if( value && *value ) + { + acc->server = g_strdup( value ); + return value; + } + else + { + acc->server = g_strdup( set->def ); + return g_strdup( set->def ); + } + } + else if( strcmp( set->key, "username" ) == 0 ) { g_free( acc->user ); acc->user = g_strdup( value ); @@ -86,34 +112,44 @@ char *set_eval_account( set_t *set, char *value ) } else if( strcmp( set->key, "password" ) == 0 ) { - g_free( acc->pass ); - acc->pass = g_strdup( value ); - return NULL; /* password shouldn't be visible in plaintext! */ - } - else if( strcmp( set->key, "server" ) == 0 ) - { - g_free( acc->server ); - if( *value ) + if( value ) { - acc->server = g_strdup( value ); - return value; + g_free( acc->pass ); + acc->pass = g_strdup( value ); + return NULL; /* password shouldn't be visible in plaintext! */ } else { - acc->server = NULL; - return g_strdup( set->def ); + /* NULL can (should) be stored in the set_t + variable, but is otherwise not correct. */ + return SET_INVALID; } } else if( strcmp( set->key, "auto_connect" ) == 0 ) { if( !is_bool( value ) ) - return NULL; + return SET_INVALID; acc->auto_connect = bool2int( value ); return value; } + else if( strcmp( set->key, "away" ) == 0 || + strcmp( set->key, "status" ) == 0 ) + { + if( acc->ic && acc->ic->flags & OPT_LOGGED_IN ) + { + /* If we're currently on-line, set the var now already + (bit of a hack) and send an update. */ + g_free( set->value ); + set->value = g_strdup( value ); + + imc_away_send_update( acc->ic ); + } + + return value; + } - return NULL; + return SET_INVALID; } account_t *account_get( irc_t *irc, char *id ) @@ -180,6 +216,7 @@ account_t *account_get( irc_t *irc, char *id ) void account_del( irc_t *irc, account_t *acc ) { account_t *a, *l = NULL; + struct chat *c, *nc; if( acc->ic ) /* Caller should have checked, accounts still in use can't be deleted. */ @@ -193,6 +230,13 @@ void account_del( irc_t *irc, account_t *acc ) else irc->accounts = a->next; + for( c = irc->chatrooms; c; c = nc ) + { + nc = c->next; + if( acc == c->acc ) + chat_del( irc, c ); + } + while( a->set ) set_del( &a->set, a->set->key ); @@ -233,3 +277,83 @@ void account_off( irc_t *irc, account_t *a ) cancel_auto_reconnect( a ); } } + +struct account_reconnect_delay +{ + int start; + char op; + int step; + int max; +}; + +int account_reconnect_delay_parse( char *value, struct account_reconnect_delay *p ) +{ + memset( p, 0, sizeof( *p ) ); + /* A whole day seems like a sane "maximum maximum". */ + p->max = 86400; + + /* Format: /[0-9]+([*+][0-9]+(<[0-9+])?)?/ */ + while( *value && isdigit( *value ) ) + p->start = p->start * 10 + *value++ - '0'; + + /* Sure, call me evil for implementing my own fscanf here, but it's + dead simple and I immediately know where to continue parsing. */ + + if( *value == 0 ) + /* If the string ends now, the delay is constant. */ + return 1; + else if( *value != '+' && *value != '*' ) + /* Otherwise allow either a + or a * */ + return 0; + + p->op = *value++; + + /* + or * the delay by this number every time. */ + while( *value && isdigit( *value ) ) + p->step = p->step * 10 + *value++ - '0'; + + if( *value == 0 ) + /* Use the default maximum (one day). */ + return 1; + else if( *value != '<' ) + return 0; + + p->max = 0; + value ++; + while( *value && isdigit( *value ) ) + p->max = p->max * 10 + *value++ - '0'; + + return p->max > 0; +} + +char *set_eval_account_reconnect_delay( set_t *set, char *value ) +{ + struct account_reconnect_delay p; + + return account_reconnect_delay_parse( value, &p ) ? value : SET_INVALID; +} + +int account_reconnect_delay( account_t *a ) +{ + char *setting = set_getstr( &a->irc->set, "auto_reconnect_delay" ); + struct account_reconnect_delay p; + + if( account_reconnect_delay_parse( setting, &p ) ) + { + if( a->auto_reconnect_delay == 0 ) + a->auto_reconnect_delay = p.start; + else if( p.op == '+' ) + a->auto_reconnect_delay += p.step; + else if( p.op == '*' ) + a->auto_reconnect_delay *= p.step; + + if( a->auto_reconnect_delay > p.max ) + a->auto_reconnect_delay = p.max; + } + else + { + a->auto_reconnect_delay = 0; + } + + return a->auto_reconnect_delay; +} |