source: storage_text.c @ 1ee6c18

Last change on this file since 1ee6c18 was 1ee6c18, checked in by Jelmer Vernooij <jelmer@…>, at 2005-12-08T13:41:53Z

Add abstraction layer for storage

  • Property mode set to 100644
File size: 7.9 KB
RevLine 
[1ee6c18]1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
4  * Copyright 2002-2004 Wilmer van der Gaast and others                *
5  \********************************************************************/
6
7/* Storage backend that uses the same file format as <=1.0 */
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 "crypting.h"
29
30static void text_init (void)
31{
32        if( access( global.conf->configdir, F_OK ) != 0 )
33                log_message( LOGLVL_WARNING, "The configuration directory %s does not exist. Configuration won't be saved.", CONFIG );
34        else if( access( global.conf->configdir, R_OK ) != 0 || access( global.conf->configdir, W_OK ) != 0 )
35                log_message( LOGLVL_WARNING, "Permission problem: Can't read/write from/to %s.", global.conf->configdir );
36}
37
38static int text_load ( const char *my_nick, const char* password, irc_t *irc )
39{
40        char s[512];
41        char *line;
42        int proto;
43        char nick[MAX_NICK_LENGTH+1];
44        FILE *fp;
45        user_t *ru = user_find( irc, ROOT_NICK );
46       
47        if( irc->status == USTATUS_IDENTIFIED )
48                return( 1 );
49       
50        g_snprintf( s, 511, "%s%s%s", global.conf->configdir, my_nick, ".accounts" );
51        fp = fopen( s, "r" );
52        if( !fp ) return( 0 );
53       
54        fscanf( fp, "%32[^\n]s", s );
55        if( setpass( irc, password, s ) < 0 )
56        {
57                fclose( fp );
58                return( -1 );
59        }
60       
61        /* Do this now. If the user runs with AuthMode = Registered, the
62           account command will not work otherwise. */
63        irc->status = USTATUS_IDENTIFIED;
64       
65        while( fscanf( fp, "%511[^\n]s", s ) > 0 )
66        {
67                fgetc( fp );
68                line = deobfucrypt( irc, s );
69                root_command_string( irc, ru, line, 0 );
70                g_free( line );
71        }
72        fclose( fp );
73       
74        g_snprintf( s, 511, "%s%s%s", global.conf->configdir, my_nick, ".nicks" );
75        fp = fopen( s, "r" );
76        if( !fp ) return( 0 );
77        while( fscanf( fp, "%s %d %s", s, &proto, nick ) > 0 )
78        {
79                http_decode( s );
80                nick_set( irc, s, proto, nick );
81        }
82        fclose( fp );
83       
84        if( set_getint( irc, "auto_connect" ) )
85        {
86                strcpy( s, "account on" );      /* Can't do this directly because r_c_s alters the string */
87                root_command_string( irc, ru, s, 0 );
88        }
89       
90        return( 1 );
91}
92
93static int text_save( irc_t *irc )
94{
95        char s[512];
96        char path[512], new_path[512];
97        char *line;
98        nick_t *n;
99        set_t *set;
100        mode_t ou = umask( 0077 );
101        account_t *a;
102        FILE *fp;
103        char *hash;
104       
105        /*\
106         *  [SH] Nothing should be saved if no password is set, because the
107         *  password is not set if it was wrong, or if one is not identified
108         *  yet. This means that a malicious user could easily overwrite
109         *  files owned by someone else:
110         *  a Bad Thing, methinks
111        \*/
112
113        /* [WVG] No? Really? */
114
115        /*\
116         *  [SH] Okay, okay, it wasn't really Wilmer who said that, it was
117         *  me. I just thought it was funny.
118        \*/
119       
120        hash = hashpass( irc );
121        if( hash == NULL )
122        {
123                irc_usermsg( irc, "Please register yourself if you want to save your settings." );
124                return( 0 );
125        }
126       
127        g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".nicks~" );
128        fp = fopen( path, "w" );
129        if( !fp ) return( 0 );
130        for( n = irc->nicks; n; n = n->next )
131        {
132                strcpy( s, n->handle );
133                s[169] = 0; /* Prevent any overflow (169 ~ 512 / 3) */
134                http_encode( s );
135                g_snprintf( s + strlen( s ), 510 - strlen( s ), " %d %s", n->proto, n->nick );
136                if( fprintf( fp, "%s\n", s ) != strlen( s ) + 1 )
137                {
138                        irc_usermsg( irc, "fprintf() wrote too little. Disk full?" );
139                        fclose( fp );
140                        return( 0 );
141                }
142        }
143        if( fclose( fp ) != 0 )
144        {
145                irc_usermsg( irc, "fclose() reported an error. Disk full?" );
146                return( 0 );
147        }
148 
149        g_snprintf( new_path, 512, "%s%s%s", global.conf->configdir, irc->nick, ".nicks" );
150        if( unlink( new_path ) != 0 )
151        {
152                if( errno != ENOENT )
153                {
154                        irc_usermsg( irc, "Error while removing old .nicks file" );
155                        return( 0 );
156                }
157        }
158        if( rename( path, new_path ) != 0 )
159        {
160                irc_usermsg( irc, "Error while renaming new .nicks file" );
161                return( 0 );
162        }
163       
164        g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".accounts~" );
165        fp = fopen( path, "w" );
166        if( !fp ) return( 0 );
167        if( fprintf( fp, "%s", hash ) != strlen( hash ) )
168        {
169                irc_usermsg( irc, "fprintf() wrote too little. Disk full?" );
170                fclose( fp );
171                return( 0 );
172        }
173        g_free( hash );
174
175        for( a = irc->accounts; a; a = a->next )
176        {
177                if( a->protocol == PROTO_OSCAR || a->protocol == PROTO_ICQ || a->protocol == PROTO_TOC )
178                        g_snprintf( s, sizeof( s ), "account add oscar \"%s\" \"%s\" %s", a->user, a->pass, a->server );
179                else
180                        g_snprintf( s, sizeof( s ), "account add %s \"%s\" \"%s\" \"%s\"",
181                                    proto_name[a->protocol], a->user, a->pass, a->server ? a->server : "" );
182               
183                line = obfucrypt( irc, s );
184                if( *line )
185                {
186                        if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 )
187                        {
188                                irc_usermsg( irc, "fprintf() wrote too little. Disk full?" );
189                                fclose( fp );
190                                return( 0 );
191                        }
192                }
193                g_free( line );
194        }
195       
196        for( set = irc->set; set; set = set->next )
197        {
198                if( set->value && set->def )
199                {
200                        g_snprintf( s, sizeof( s ), "set %s \"%s\"", set->key, set->value );
201                        line = obfucrypt( irc, s );
202                        if( *line )
203                        {
204                                if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 )
205                                {
206                                        irc_usermsg( irc, "fprintf() wrote too little. Disk full?" );
207                                        fclose( fp );
208                                        return( 0 );
209                                }
210                        }
211                        g_free( line );
212                }
213        }
214       
215        if( strcmp( irc->mynick, ROOT_NICK ) != 0 )
216        {
217                g_snprintf( s, sizeof( s ), "rename %s %s", ROOT_NICK, irc->mynick );
218                line = obfucrypt( irc, s );
219                if( *line )
220                {
221                        if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 )
222                        {
223                                irc_usermsg( irc, "fprintf() wrote too little. Disk full?" );
224                                fclose( fp );
225                                return( 0 );
226                        }
227                }
228                g_free( line );
229        }
230        if( fclose( fp ) != 0 )
231        {
232                irc_usermsg( irc, "fclose() reported an error. Disk full?" );
233                return( 0 );
234        }
235       
236        g_snprintf( new_path, 512, "%s%s%s", global.conf->configdir, irc->nick, ".accounts" );
237        if( unlink( new_path ) != 0 )
238        {
239                if( errno != ENOENT )
240                {
241                        irc_usermsg( irc, "Error while removing old .accounts file" );
242                        return( 0 );
243                }
244        }
245        if( rename( path, new_path ) != 0 )
246        {
247                irc_usermsg( irc, "Error while renaming new .accounts file" );
248                return( 0 );
249        }
250       
251        umask( ou );
252       
253        return( 1 );
254}
255
256static int text_exists( const char *nick )
257{
258        char path[512];
259        int checkie;
260
261        g_snprintf( path, 511, "%s%s%s", global.conf->configdir, nick, ".accounts" );
262        checkie = access( path, F_OK );
263       
264        g_snprintf( path, 511, "%s%s%s", global.conf->configdir, nick, ".nicks" );
265        checkie += access( path, F_OK );
266       
267        return ( checkie != -2 );
268}
269
270static int text_remove( const char *nick )
271{
272        char s[512];
273
274        g_snprintf( s, 511, "%s%s%s", global.conf->configdir, nick, ".accounts" );
275        if (unlink( s ) == -1)
276                return( 1 );
277       
278        g_snprintf( s, 511, "%s%s%s", global.conf->configdir, nick, ".nicks" );
279        if (unlink( s ) == -1)
280                return( 1 );
281
282        return( 0 );
283}
284
285static int text_check_pass( const char *nick, const char *password )
286{
287        char s[512];
288        FILE *fp;
289       
290        g_snprintf( s, 511, "%s%s%s", global.conf->configdir, nick, ".nicks" );
291        fp = fopen( s, "r" );
292
293        fscanf( fp, "%32[^\n]s", s );
294        fclose( fp );
295
296        /* FIXME */
297        return( 0 );
298}
299
300storage_t storage_text = {
301        .name = "text",
302        .init = text_init,
303        .exists = text_exists,
304        .check_pass = text_check_pass,
305        .remove = text_remove,
306        .load = text_load,
307        .save = text_save
308};
Note: See TracBrowser for help on using the repository browser.