source: account.c @ 36cf9fd

Last change on this file since 36cf9fd was b75acf6, checked in by Wilmer van der Gaast <wilmer@…>, at 2009-10-22T21:55:23Z

Don't include chat.h from bitlbee.h. make install-dev doesn't install
chat.h and it shouldn't ... but things broke because bitlbee.h includes
it. Fixes #534.

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