source: protocols/account.c @ b1f818b

Last change on this file since b1f818b was 84c3a72, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-06-27T12:39:07Z

Import chatrooms configured in older BitlBee versions. Settings are currently
ignored though. Also removing the old chat.[ch] files since they're really not
important anymore.

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