source: protocols/account.c @ 27e2c66

Last change on this file since 27e2c66 was fb117aee, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-04-02T02:29:45Z

Cleaned lots of compiler warnings so I can get some signal again.

  • Property mode set to 100644
File size: 8.1 KB
RevLine 
[b7d3cc34]1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
[58adb7e]4  * Copyright 2002-2010 Wilmer van der Gaast and others                *
[b7d3cc34]5  \********************************************************************/
6
7/* Account management functions                                         */
8
9/*
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU General Public License for more details.
19
20  You should have received a copy of the GNU General Public License with
21  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
22  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
23  Suite 330, Boston, MA  02111-1307  USA
24*/
25
26#define BITLBEE_CORE
27#include "bitlbee.h"
28#include "account.h"
[b75acf6]29#include "chat.h"
[b7d3cc34]30
[81e04e1]31account_t *account_add( bee_t *bee, struct prpl *prpl, char *user, char *pass )
[b7d3cc34]32{
33        account_t *a;
[5100caa]34        set_t *s;
[b7d3cc34]35       
[81e04e1]36        if( bee->accounts )
[b7d3cc34]37        {
[81e04e1]38                for( a = bee->accounts; a->next; a = a->next );
[a312b6b]39                a = a->next = g_new0( account_t, 1 );
[b7d3cc34]40        }
41        else
42        {
[81e04e1]43                bee->accounts = a = g_new0 ( account_t, 1 );
[b7d3cc34]44        }
45       
[7b23afd]46        a->prpl = prpl;
[b7d3cc34]47        a->user = g_strdup( user );
48        a->pass = g_strdup( pass );
[2b14eef]49        a->auto_connect = 1;
[81e04e1]50        a->bee = bee;
[b7d3cc34]51       
[96863f6]52        s = set_add( &a->set, "auto_connect", "true", set_eval_account, a );
[5100caa]53        s->flags |= ACC_SET_NOSAVE;
54       
[04026d4]55        s = set_add( &a->set, "auto_reconnect", "true", set_eval_bool, a );
[00a5270]56       
[286b28e]57        s = set_add( &a->set, "nick_source", "handle", NULL, a );
58       
[5100caa]59        s = set_add( &a->set, "password", NULL, set_eval_account, a );
[f3579fd]60        s->flags |= ACC_SET_NOSAVE | SET_NULL_OK;
[5100caa]61       
62        s = set_add( &a->set, "username", NULL, set_eval_account, a );
63        s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY;
64        set_setstr( &a->set, "username", user );
65       
[5b52a48]66        a->nicks = g_hash_table_new_full( g_str_hash, g_str_equal, g_free, g_free );
67       
[96863f6]68        /* This function adds some more settings (and might want to do more
69           things that have to be done now, although I can't think of anything. */
[0da65d5]70        if( prpl->init )
71                prpl->init( a );
[96863f6]72       
[58adb7e]73        s = set_add( &a->set, "away", NULL, set_eval_account, a );
74        s->flags |= SET_NULL_OK;
75       
76        if( a->flags & ACC_FLAG_STATUS_MESSAGE )
77        {
78                s = set_add( &a->set, "status", NULL, set_eval_account, a );
79                s->flags |= SET_NULL_OK;
80        }
81       
82        return a;
[b7d3cc34]83}
84
[5100caa]85char *set_eval_account( set_t *set, char *value )
86{
87        account_t *acc = set->data;
88       
89        /* Double-check: We refuse to edit on-line accounts. */
[0da65d5]90        if( set->flags & ACC_SET_OFFLINE_ONLY && acc->ic )
[7125cb3]91                return SET_INVALID;
[5100caa]92       
[3b32017]93        if( strcmp( set->key, "server" ) == 0 )
[5100caa]94        {
95                g_free( acc->server );
[3b32017]96                if( value && *value )
[30ce1ce]97                {
[5100caa]98                        acc->server = g_strdup( value );
[30ce1ce]99                        return value;
100                }
[5100caa]101                else
[30ce1ce]102                {
[7125cb3]103                        acc->server = g_strdup( set->def );
[30ce1ce]104                        return g_strdup( set->def );
105                }
[5100caa]106        }
[3b32017]107        else if( strcmp( set->key, "username" ) == 0 )
108        {
109                g_free( acc->user );
110                acc->user = g_strdup( value );
111                return value;
112        }
113        else if( strcmp( set->key, "password" ) == 0 )
114        {
[7125cb3]115                if( value )
116                {
117                        g_free( acc->pass );
118                        acc->pass = g_strdup( value );
119                        return NULL;    /* password shouldn't be visible in plaintext! */
120                }
121                else
122                {
123                        /* NULL can (should) be stored in the set_t
124                           variable, but is otherwise not correct. */
125                        return SET_INVALID;
126                }
[3b32017]127        }
[5100caa]128        else if( strcmp( set->key, "auto_connect" ) == 0 )
129        {
130                if( !is_bool( value ) )
[7125cb3]131                        return SET_INVALID;
[5100caa]132               
133                acc->auto_connect = bool2int( value );
134                return value;
135        }
[58adb7e]136        else if( strcmp( set->key, "away" ) == 0 ||
137                 strcmp( set->key, "status" ) == 0 )
138        {
139                if( acc->ic && acc->ic->flags & OPT_LOGGED_IN )
140                {
141                        /* If we're currently on-line, set the var now already
142                           (bit of a hack) and send an update. */
143                        g_free( set->value );
144                        set->value = g_strdup( value );
145                       
146                        imc_away_send_update( acc->ic );
147                }
148               
149                return value;
150        }
[5100caa]151       
[7125cb3]152        return SET_INVALID;
[5100caa]153}
154
[81e04e1]155account_t *account_get( bee_t *bee, char *id )
[b7d3cc34]156{
157        account_t *a, *ret = NULL;
[85616c3]158        char *handle, *s;
[b7d3cc34]159        int nr;
160       
[85616c3]161        /* This checks if the id string ends with (...) */
162        if( ( handle = strchr( id, '(' ) ) && ( s = strchr( handle, ')' ) ) && s[1] == 0 )
163        {
164                struct prpl *proto;
165               
166                *s = *handle = 0;
167                handle ++;
168               
169                if( ( proto = find_protocol( id ) ) )
170                {
[81e04e1]171                        for( a = bee->accounts; a; a = a->next )
[85616c3]172                                if( a->prpl == proto &&
[5b52a48]173                                    a->prpl->handle_cmp( handle, a->user ) == 0 )
[85616c3]174                                        ret = a;
175                }
176               
177                /* Restore the string. */
178                handle --;
179                *handle = '(';
180                *s = ')';
181               
182                if( ret )
183                        return ret;
184        }
185       
[b7d3cc34]186        if( sscanf( id, "%d", &nr ) == 1 && nr < 1000 )
187        {
[81e04e1]188                for( a = bee->accounts; a; a = a->next )
[b7d3cc34]189                        if( ( nr-- ) == 0 )
190                                return( a );
191               
192                return( NULL );
193        }
194       
[81e04e1]195        for( a = bee->accounts; a; a = a->next )
[b7d3cc34]196        {
[7b23afd]197                if( g_strcasecmp( id, a->prpl->name ) == 0 )
[b7d3cc34]198                {
199                        if( !ret )
200                                ret = a;
201                        else
202                                return( NULL ); /* We don't want to match more than one... */
203                }
204                else if( strstr( a->user, id ) )
205                {
206                        if( !ret )
207                                ret = a;
208                        else
209                                return( NULL );
210                }
211        }
212       
213        return( ret );
214}
215
[81e04e1]216void account_del( bee_t *bee, account_t *acc )
[b7d3cc34]217{
218        account_t *a, *l = NULL;
219       
[fa75134]220        if( acc->ic )
221                /* Caller should have checked, accounts still in use can't be deleted. */
222                return;
223       
[81e04e1]224        for( a = bee->accounts; a; a = (l=a)->next )
[b7d3cc34]225                if( a == acc )
226                {
227                        if( l )
228                                l->next = a->next;
229                        else
[81e04e1]230                                bee->accounts = a->next;
[b7d3cc34]231                       
[81e04e1]232                        /** FIXME
233                        for( c = bee->chatrooms; c; c = nc )
[f86a3d5]234                        {
235                                nc = c->next;
[d995c9b]236                                if( acc == c->acc )
[81e04e1]237                                        chat_del( bee, c );
[f86a3d5]238                        }
[81e04e1]239                        */
[d995c9b]240                       
[5100caa]241                        while( a->set )
242                                set_del( &a->set, a->set->key );
243                       
[5b52a48]244                        g_hash_table_destroy( a->nicks );
245                       
[b7d3cc34]246                        g_free( a->user );
247                        g_free( a->pass );
[fa75134]248                        g_free( a->server );
[b7d3cc34]249                        if( a->reconnect )      /* This prevents any reconnect still queued to happen */
250                                cancel_auto_reconnect( a );
251                        g_free( a );
252                       
253                        break;
254                }
255}
256
[81e04e1]257void account_on( bee_t *bee, account_t *a )
[b7d3cc34]258{
[0da65d5]259        if( a->ic )
[b7d3cc34]260        {
261                /* Trying to enable an already-enabled account */
262                return;
263        }
264       
265        cancel_auto_reconnect( a );
266       
267        a->reconnect = 0;
[0a3c243]268        a->prpl->login( a );
[b7d3cc34]269}
270
[81e04e1]271void account_off( bee_t *bee, account_t *a )
[b7d3cc34]272{
[b0eaa5b]273        imc_logout( a->ic, FALSE );
[0da65d5]274        a->ic = NULL;
[b7d3cc34]275        if( a->reconnect )
276        {
277                /* Shouldn't happen */
278                cancel_auto_reconnect( a );
279        }
280}
[280e655]281
[4230221]282struct account_reconnect_delay
[280e655]283{
284        int start;
285        char op;
286        int step;
[4230221]287        int max;
288};
289
290int account_reconnect_delay_parse( char *value, struct account_reconnect_delay *p )
291{
292        memset( p, 0, sizeof( *p ) );
293        /* A whole day seems like a sane "maximum maximum". */
294        p->max = 86400;
[280e655]295       
[58adb7e]296        /* Format: /[0-9]+([*+][0-9]+(<[0-9+])?)?/ */
[4230221]297        while( *value && isdigit( *value ) )
298                p->start = p->start * 10 + *value++ - '0';
299       
300        /* Sure, call me evil for implementing my own fscanf here, but it's
[7125cb3]301           dead simple and I immediately know where to continue parsing. */
[4230221]302       
303        if( *value == 0 )
304                /* If the string ends now, the delay is constant. */
305                return 1;
306        else if( *value != '+' && *value != '*' )
307                /* Otherwise allow either a + or a * */
308                return 0;
309       
310        p->op = *value++;
311       
312        /* + or * the delay by this number every time. */
313        while( *value && isdigit( *value ) )
314                p->step = p->step * 10 + *value++ - '0';
315       
316        if( *value == 0 )
317                /* Use the default maximum (one day). */
318                return 1;
319        else if( *value != '<' )
320                return 0;
321       
322        p->max = 0;
323        value ++;
324        while( *value && isdigit( *value ) )
325                p->max = p->max * 10 + *value++ - '0';
326       
327        return p->max > 0;
328}
329
330char *set_eval_account_reconnect_delay( set_t *set, char *value )
331{
332        struct account_reconnect_delay p;
333       
[7125cb3]334        return account_reconnect_delay_parse( value, &p ) ? value : SET_INVALID;
[280e655]335}
336
337int account_reconnect_delay( account_t *a )
338{
[81e04e1]339        char *setting = set_getstr( &a->bee->set, "auto_reconnect_delay" );
[4230221]340        struct account_reconnect_delay p;
[280e655]341       
[4230221]342        if( account_reconnect_delay_parse( setting, &p ) )
[280e655]343        {
344                if( a->auto_reconnect_delay == 0 )
[4230221]345                        a->auto_reconnect_delay = p.start;
346                else if( p.op == '+' )
347                        a->auto_reconnect_delay += p.step;
348                else if( p.op == '*' )
349                        a->auto_reconnect_delay *= p.step;
350               
351                if( a->auto_reconnect_delay > p.max )
352                        a->auto_reconnect_delay = p.max;
[280e655]353        }
[4230221]354        else
[280e655]355        {
[4230221]356                a->auto_reconnect_delay = 0;
[280e655]357        }
358       
[4230221]359        return a->auto_reconnect_delay;
[280e655]360}
Note: See TracBrowser for help on using the repository browser.