aboutsummaryrefslogtreecommitdiffstats
path: root/protocols/account.c
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/account.c')
-rw-r--r--protocols/account.c538
1 files changed, 267 insertions, 271 deletions
diff --git a/protocols/account.c b/protocols/account.c
index 234b9de2..e1025a53 100644
--- a/protocols/account.c
+++ b/protocols/account.c
@@ -1,4 +1,4 @@
- /********************************************************************\
+/********************************************************************\
* BitlBee -- An IRC to other IM-networks gateway *
* *
* Copyright 2002-2013 Wilmer van der Gaast and others *
@@ -31,450 +31,446 @@ static const char* account_protocols_local[] = {
"gg", "whatsapp", NULL
};
-static char *set_eval_nick_source( set_t *set, char *value );
+static char *set_eval_nick_source(set_t *set, char *value);
-account_t *account_add( bee_t *bee, struct prpl *prpl, char *user, char *pass )
+account_t *account_add(bee_t *bee, struct prpl *prpl, char *user, char *pass)
{
account_t *a;
set_t *s;
- char tag[strlen(prpl->name)+10];
-
- if( bee->accounts )
- {
- for( a = bee->accounts; a->next; a = a->next );
- a = a->next = g_new0( account_t, 1 );
- }
- else
- {
- bee->accounts = a = g_new0 ( account_t, 1 );
+ char tag[strlen(prpl->name) + 10];
+
+ if (bee->accounts) {
+ for (a = bee->accounts; a->next; a = a->next) {
+ ;
+ }
+ a = a->next = g_new0(account_t, 1);
+ } else {
+ bee->accounts = a = g_new0(account_t, 1);
}
-
+
a->prpl = prpl;
- a->user = g_strdup( user );
- a->pass = g_strdup( pass );
+ a->user = g_strdup(user);
+ a->pass = g_strdup(pass);
a->auto_connect = 1;
a->bee = bee;
-
- s = set_add( &a->set, "auto_connect", "true", set_eval_account, a );
+
+ s = set_add(&a->set, "auto_connect", "true", set_eval_account, a);
s->flags |= SET_NOSAVE;
-
- s = set_add( &a->set, "auto_reconnect", "true", set_eval_bool, a );
-
- s = set_add( &a->set, "nick_format", NULL, NULL, a );
+
+ s = set_add(&a->set, "auto_reconnect", "true", set_eval_bool, a);
+
+ s = set_add(&a->set, "nick_format", NULL, NULL, a);
s->flags |= SET_NULL_OK;
-
- s = set_add( &a->set, "nick_source", "handle", set_eval_nick_source, a );
+
+ s = set_add(&a->set, "nick_source", "handle", set_eval_nick_source, a);
s->flags |= SET_NOSAVE; /* Just for bw compatibility! */
-
- s = set_add( &a->set, "password", NULL, set_eval_account, a );
+
+ s = set_add(&a->set, "password", NULL, set_eval_account, a);
s->flags |= SET_NOSAVE | SET_NULL_OK | SET_PASSWORD;
-
- s = set_add( &a->set, "tag", NULL, set_eval_account, a );
+
+ s = set_add(&a->set, "tag", NULL, set_eval_account, a);
s->flags |= SET_NOSAVE;
-
- s = set_add( &a->set, "username", NULL, set_eval_account, a );
+
+ s = set_add(&a->set, "username", NULL, set_eval_account, a);
s->flags |= SET_NOSAVE | ACC_SET_OFFLINE_ONLY;
- set_setstr( &a->set, "username", user );
-
+ set_setstr(&a->set, "username", user);
+
/* Hardcode some more clever tag guesses. */
- strcpy( tag, prpl->name );
- if( strcmp( prpl->name, "oscar" ) == 0 )
- {
- if( g_ascii_isdigit( a->user[0] ) )
- strcpy( tag, "icq" );
- else
- strcpy( tag, "aim" );
- }
- else if( strcmp( prpl->name, "jabber" ) == 0 )
- {
- if( strstr( a->user, "@gmail.com" ) ||
- strstr( a->user, "@googlemail.com" ) )
- strcpy( tag, "gtalk" );
- else if( strstr( a->user, "@chat.facebook.com" ) )
- strcpy( tag, "fb" );
+ strcpy(tag, prpl->name);
+ if (strcmp(prpl->name, "oscar") == 0) {
+ if (g_ascii_isdigit(a->user[0])) {
+ strcpy(tag, "icq");
+ } else {
+ strcpy(tag, "aim");
+ }
+ } else if (strcmp(prpl->name, "jabber") == 0) {
+ if (strstr(a->user, "@gmail.com") ||
+ strstr(a->user, "@googlemail.com")) {
+ strcpy(tag, "gtalk");
+ } else if (strstr(a->user, "@chat.facebook.com")) {
+ strcpy(tag, "fb");
+ }
}
-
- if( account_by_tag( bee, tag ) )
- {
- char *numpos = tag + strlen( tag );
+
+ if (account_by_tag(bee, tag)) {
+ char *numpos = tag + strlen(tag);
int i;
- for( i = 2; i < 10000; i ++ )
- {
- sprintf( numpos, "%d", i );
- if( !account_by_tag( bee, tag ) )
+ for (i = 2; i < 10000; i++) {
+ sprintf(numpos, "%d", i);
+ if (!account_by_tag(bee, tag)) {
break;
+ }
}
}
- set_setstr( &a->set, "tag", tag );
-
- a->nicks = g_hash_table_new_full( g_str_hash, g_str_equal, g_free, g_free );
-
+ set_setstr(&a->set, "tag", tag);
+
+ a->nicks = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+
/* This function adds some more settings (and might want to do more
things that have to be done now, although I can't think of anything. */
- if( prpl->init )
- prpl->init( a );
-
- s = set_add( &a->set, "away", NULL, set_eval_account, a );
+ if (prpl->init) {
+ prpl->init(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 );
+
+ 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 )
+char *set_eval_account(set_t *set, char *value)
{
account_t *acc = set->data;
-
+
/* Double-check: We refuse to edit on-line accounts. */
- if( set->flags & ACC_SET_OFFLINE_ONLY && acc->ic )
+ if (set->flags & ACC_SET_OFFLINE_ONLY && acc->ic) {
return SET_INVALID;
-
- if( strcmp( set->key, "server" ) == 0 )
- {
- g_free( acc->server );
- if( value && *value )
- {
- acc->server = g_strdup( value );
+ }
+
+ 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
- {
- 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 );
+ } else if (strcmp(set->key, "username") == 0) {
+ g_free(acc->user);
+ acc->user = g_strdup(value);
return value;
- }
- else if( strcmp( set->key, "password" ) == 0 )
- {
+ } else if (strcmp(set->key, "password") == 0) {
/* set -del allows /oper to be used to change the password or,
iff oauth is enabled, reset the oauth credential magic.
*/
- if( !value ) {
- if ( set_getbool( &(acc->set), "oauth" ) ) {
+ if (!value) {
+ if (set_getbool(&(acc->set), "oauth")) {
value = "";
} else {
value = PASSWORD_PENDING;
- ((irc_t *)acc->bee->ui_data)->status |= OPER_HACK_ACCOUNT_PASSWORD;
- irc_rootmsg((irc_t *)acc->bee->ui_data, "You may now use /OPER to set the password");
+ ((irc_t *) acc->bee->ui_data)->status |= OPER_HACK_ACCOUNT_PASSWORD;
+ irc_rootmsg((irc_t *) acc->bee->ui_data, "You may now use /OPER to set the password");
}
}
-
- g_free( acc->pass );
- acc->pass = g_strdup( value );
- return NULL; /* password shouldn't be visible in plaintext! */
- }
- else if( strcmp( set->key, "tag" ) == 0 )
- {
+
+ g_free(acc->pass);
+ acc->pass = g_strdup(value);
+ return NULL; /* password shouldn't be visible in plaintext! */
+ } else if (strcmp(set->key, "tag") == 0) {
account_t *oa;
-
+
/* Enforce uniqueness. */
- if( ( oa = account_by_tag( acc->bee, value ) ) && oa != acc )
+ if ((oa = account_by_tag(acc->bee, value)) && oa != acc) {
return SET_INVALID;
-
- g_free( acc->tag );
- acc->tag = g_strdup( value );
+ }
+
+ g_free(acc->tag);
+ acc->tag = g_strdup(value);
return value;
- }
- else if( strcmp( set->key, "auto_connect" ) == 0 )
- {
- if( !is_bool( value ) )
+ } else if (strcmp(set->key, "auto_connect") == 0) {
+ if (!is_bool(value)) {
return SET_INVALID;
-
- acc->auto_connect = bool2int( value );
+ }
+
+ 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 )
- {
+ } 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 );
+ g_free(set->value);
+ set->value = g_strdup(value);
+
+ imc_away_send_update(acc->ic);
}
-
+
return value;
}
-
+
return SET_INVALID;
}
/* For bw compatibility, have this write-only setting. */
-static char *set_eval_nick_source( set_t *set, char *value )
+static char *set_eval_nick_source(set_t *set, char *value)
{
account_t *a = set->data;
-
- if( strcmp( value, "full_name" ) == 0 )
- set_setstr( &a->set, "nick_format", "%full_name" );
- else if( strcmp( value, "first_name" ) == 0 )
- set_setstr( &a->set, "nick_format", "%first_name" );
- else
- set_setstr( &a->set, "nick_format", "%-@nick" );
-
+
+ if (strcmp(value, "full_name") == 0) {
+ set_setstr(&a->set, "nick_format", "%full_name");
+ } else if (strcmp(value, "first_name") == 0) {
+ set_setstr(&a->set, "nick_format", "%first_name");
+ } else {
+ set_setstr(&a->set, "nick_format", "%-@nick");
+ }
+
return value;
}
-account_t *account_get( bee_t *bee, const char *id )
+account_t *account_get(bee_t *bee, const char *id)
{
account_t *a, *ret = NULL;
char *handle, *s;
int nr;
-
+
/* Tags get priority above anything else. */
- if( ( a = account_by_tag( bee, id ) ) )
+ if ((a = account_by_tag(bee, id))) {
return a;
-
+ }
+
/* This checks if the id string ends with (...) */
- if( ( handle = strchr( id, '(' ) ) && ( s = strchr( handle, ')' ) ) && s[1] == 0 )
- {
+ if ((handle = strchr(id, '(')) && (s = strchr(handle, ')')) && s[1] == 0) {
struct prpl *proto;
-
+
*s = *handle = 0;
- handle ++;
-
- if( ( proto = find_protocol( id ) ) )
- {
- for( a = bee->accounts; a; a = a->next )
- if( a->prpl == proto &&
- a->prpl->handle_cmp( handle, a->user ) == 0 )
+ handle++;
+
+ if ((proto = find_protocol(id))) {
+ for (a = bee->accounts; a; a = a->next) {
+ if (a->prpl == proto &&
+ a->prpl->handle_cmp(handle, a->user) == 0) {
ret = a;
+ }
+ }
}
-
+
/* Restore the string. */
- handle --;
+ handle--;
*handle = '(';
*s = ')';
-
- if( ret )
+
+ if (ret) {
return ret;
+ }
}
-
- if( sscanf( id, "%d", &nr ) == 1 && nr < 1000 )
- {
- for( a = bee->accounts; a; a = a->next )
- if( ( nr-- ) == 0 )
- return( a );
-
- return( NULL );
+
+ if (sscanf(id, "%d", &nr) == 1 && nr < 1000) {
+ for (a = bee->accounts; a; a = a->next) {
+ if ((nr--) == 0) {
+ return(a);
+ }
+ }
+
+ return(NULL);
}
-
- for( a = bee->accounts; a; a = a->next )
- {
- if( g_strcasecmp( id, a->prpl->name ) == 0 )
- {
- if( !ret )
+
+ for (a = bee->accounts; a; a = a->next) {
+ if (g_strcasecmp(id, a->prpl->name) == 0) {
+ if (!ret) {
ret = a;
- else
- return( NULL ); /* We don't want to match more than one... */
- }
- else if( strstr( a->user, id ) )
- {
- if( !ret )
+ } else {
+ return(NULL); /* We don't want to match more than one... */
+ }
+ } else if (strstr(a->user, id)) {
+ if (!ret) {
ret = a;
- else
- return( NULL );
+ } else {
+ return(NULL);
+ }
}
}
-
- return( ret );
+
+ return(ret);
}
-account_t *account_by_tag( bee_t *bee, const char *tag )
+account_t *account_by_tag(bee_t *bee, const char *tag)
{
account_t *a;
-
- for( a = bee->accounts; a; a = a->next )
- if( a->tag && g_strcasecmp( tag, a->tag ) == 0 )
+
+ for (a = bee->accounts; a; a = a->next) {
+ if (a->tag && g_strcasecmp(tag, a->tag) == 0) {
return a;
-
+ }
+ }
+
return NULL;
}
-void account_del( bee_t *bee, account_t *acc )
+void account_del(bee_t *bee, account_t *acc)
{
account_t *a, *l = NULL;
-
- if( acc->ic )
+
+ if (acc->ic) {
/* Caller should have checked, accounts still in use can't be deleted. */
return;
-
- for( a = bee->accounts; a; a = (l=a)->next )
- if( a == acc )
- {
- if( l )
+ }
+
+ for (a = bee->accounts; a; a = (l = a)->next) {
+ if (a == acc) {
+ if (l) {
l->next = a->next;
- else
+ } else {
bee->accounts = a->next;
-
+ }
+
/** FIXME
for( c = bee->chatrooms; c; c = nc )
{
- nc = c->next;
- if( acc == c->acc )
- chat_del( bee, c );
+ nc = c->next;
+ if( acc == c->acc )
+ chat_del( bee, c );
}
*/
-
- while( a->set )
- set_del( &a->set, a->set->key );
-
- g_hash_table_destroy( a->nicks );
-
- g_free( a->tag );
- g_free( a->user );
- g_free( a->pass );
- g_free( a->server );
- if( a->reconnect ) /* This prevents any reconnect still queued to happen */
- cancel_auto_reconnect( a );
- g_free( a );
-
+
+ while (a->set) {
+ set_del(&a->set, a->set->key);
+ }
+
+ g_hash_table_destroy(a->nicks);
+
+ g_free(a->tag);
+ g_free(a->user);
+ g_free(a->pass);
+ g_free(a->server);
+ if (a->reconnect) { /* This prevents any reconnect still queued to happen */
+ cancel_auto_reconnect(a);
+ }
+ g_free(a);
+
break;
}
+ }
}
-static gboolean account_on_timeout( gpointer d, gint fd, b_input_condition cond );
+static gboolean account_on_timeout(gpointer d, gint fd, b_input_condition cond);
-void account_on( bee_t *bee, account_t *a )
+void account_on(bee_t *bee, account_t *a)
{
- if( a->ic )
- {
+ if (a->ic) {
/* Trying to enable an already-enabled account */
return;
}
-
- cancel_auto_reconnect( a );
-
+
+ cancel_auto_reconnect(a);
+
a->reconnect = 0;
- a->prpl->login( a );
-
- if( a->ic && !( a->ic->flags & ( OPT_SLOW_LOGIN | OPT_LOGGED_IN ) ) )
- a->ic->keepalive = b_timeout_add( 120000, account_on_timeout, a->ic );
+ a->prpl->login(a);
+
+ if (a->ic && !(a->ic->flags & (OPT_SLOW_LOGIN | OPT_LOGGED_IN))) {
+ a->ic->keepalive = b_timeout_add(120000, account_on_timeout, a->ic);
+ }
}
-void account_off( bee_t *bee, account_t *a )
+void account_off(bee_t *bee, account_t *a)
{
- imc_logout( a->ic, FALSE );
+ imc_logout(a->ic, FALSE);
a->ic = NULL;
- if( a->reconnect )
- {
+ if (a->reconnect) {
/* Shouldn't happen */
- cancel_auto_reconnect( a );
+ cancel_auto_reconnect(a);
}
}
-static gboolean account_on_timeout( gpointer d, gint fd, b_input_condition cond )
+static gboolean account_on_timeout(gpointer d, gint fd, b_input_condition cond)
{
struct im_connection *ic = d;
-
- if( !( ic->flags & ( OPT_SLOW_LOGIN | OPT_LOGGED_IN ) ) )
- {
- imcb_error( ic, "Connection timeout" );
- imc_logout( ic, TRUE );
+
+ if (!(ic->flags & (OPT_SLOW_LOGIN | OPT_LOGGED_IN))) {
+ imcb_error(ic, "Connection timeout");
+ imc_logout(ic, TRUE);
}
-
+
return FALSE;
}
-struct account_reconnect_delay
-{
+struct account_reconnect_delay {
int start;
char op;
int step;
int max;
};
-int account_reconnect_delay_parse( char *value, struct account_reconnect_delay *p )
+int account_reconnect_delay_parse(char *value, struct account_reconnect_delay *p)
{
- memset( p, 0, sizeof( *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 && g_ascii_isdigit( *value ) )
+ while (*value && g_ascii_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 (*value == 0) {
/* If the string ends now, the delay is constant. */
return 1;
- else if( *value != '+' && *value != '*' )
+ } 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 && g_ascii_isdigit( *value ) )
+ while (*value && g_ascii_isdigit(*value)) {
p->step = p->step * 10 + *value++ - '0';
-
- if( *value == 0 )
+ }
+
+ if (*value == 0) {
/* Use the default maximum (one day). */
return 1;
- else if( *value != '<' )
+ } else if (*value != '<') {
return 0;
-
+ }
+
p->max = 0;
- value ++;
- while( *value && g_ascii_isdigit( *value ) )
+ value++;
+ while (*value && g_ascii_isdigit(*value)) {
p->max = p->max * 10 + *value++ - '0';
-
+ }
+
return p->max > 0;
}
-char *set_eval_account_reconnect_delay( set_t *set, char *value )
+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;
+
+ return account_reconnect_delay_parse(value, &p) ? value : SET_INVALID;
}
-int account_reconnect_delay( account_t *a )
+int account_reconnect_delay(account_t *a)
{
- char *setting = set_getstr( &a->bee->set, "auto_reconnect_delay" );
+ char *setting = set_getstr(&a->bee->set, "auto_reconnect_delay");
struct account_reconnect_delay p;
-
- if( account_reconnect_delay_parse( setting, &p ) )
- {
- if( a->auto_reconnect_delay == 0 )
+
+ if (account_reconnect_delay_parse(setting, &p)) {
+ if (a->auto_reconnect_delay == 0) {
a->auto_reconnect_delay = p.start;
- else if( p.op == '+' )
+ } else if (p.op == '+') {
a->auto_reconnect_delay += p.step;
- else if( p.op == '*' )
+ } else if (p.op == '*') {
a->auto_reconnect_delay *= p.step;
-
- if( a->auto_reconnect_delay > p.max )
+ }
+
+ if (a->auto_reconnect_delay > p.max) {
a->auto_reconnect_delay = p.max;
- }
- else
- {
+ }
+ } else {
a->auto_reconnect_delay = 0;
}
-
+
return a->auto_reconnect_delay;
}
-int protocol_account_islocal( const char* protocol )
+int protocol_account_islocal(const char* protocol)
{
const char** p = account_protocols_local;
+
do {
- if( strcmp( *p, protocol ) == 0 )
+ if (strcmp(*p, protocol) == 0) {
return 1;
- } while( *( ++p ) );
+ }
+ } while (*(++p));
return 0;
}