aboutsummaryrefslogtreecommitdiffstats
path: root/storage_text.c
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2005-12-08 14:41:53 +0100
committerJelmer Vernooij <jelmer@samba.org>2005-12-08 14:41:53 +0100
commit1ee6c18cfb5eb03f33a5938b37e357dd3fd2c164 (patch)
tree6b6806ac2c13634c7a7c5419e95a0c8bd1fe6884 /storage_text.c
parentd636233a518fbe46264230866d4b8ea463f1474e (diff)
Add abstraction layer for storage
Diffstat (limited to 'storage_text.c')
-rw-r--r--storage_text.c308
1 files changed, 308 insertions, 0 deletions
diff --git a/storage_text.c b/storage_text.c
new file mode 100644
index 00000000..7c8b794c
--- /dev/null
+++ b/storage_text.c
@@ -0,0 +1,308 @@
+ /********************************************************************\
+ * BitlBee -- An IRC to other IM-networks gateway *
+ * *
+ * Copyright 2002-2004 Wilmer van der Gaast and others *
+ \********************************************************************/
+
+/* Storage backend that uses the same file format as <=1.0 */
+
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License with
+ the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+ if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+ Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#define BITLBEE_CORE
+#include "bitlbee.h"
+#include "crypting.h"
+
+static void text_init (void)
+{
+ if( access( global.conf->configdir, F_OK ) != 0 )
+ log_message( LOGLVL_WARNING, "The configuration directory %s does not exist. Configuration won't be saved.", CONFIG );
+ else if( access( global.conf->configdir, R_OK ) != 0 || access( global.conf->configdir, W_OK ) != 0 )
+ log_message( LOGLVL_WARNING, "Permission problem: Can't read/write from/to %s.", global.conf->configdir );
+}
+
+static int text_load ( const char *my_nick, const char* password, irc_t *irc )
+{
+ char s[512];
+ char *line;
+ int proto;
+ char nick[MAX_NICK_LENGTH+1];
+ FILE *fp;
+ user_t *ru = user_find( irc, ROOT_NICK );
+
+ if( irc->status == USTATUS_IDENTIFIED )
+ return( 1 );
+
+ g_snprintf( s, 511, "%s%s%s", global.conf->configdir, my_nick, ".accounts" );
+ fp = fopen( s, "r" );
+ if( !fp ) return( 0 );
+
+ fscanf( fp, "%32[^\n]s", s );
+ if( setpass( irc, password, s ) < 0 )
+ {
+ fclose( fp );
+ return( -1 );
+ }
+
+ /* Do this now. If the user runs with AuthMode = Registered, the
+ account command will not work otherwise. */
+ irc->status = USTATUS_IDENTIFIED;
+
+ while( fscanf( fp, "%511[^\n]s", s ) > 0 )
+ {
+ fgetc( fp );
+ line = deobfucrypt( irc, s );
+ root_command_string( irc, ru, line, 0 );
+ g_free( line );
+ }
+ fclose( fp );
+
+ g_snprintf( s, 511, "%s%s%s", global.conf->configdir, my_nick, ".nicks" );
+ fp = fopen( s, "r" );
+ if( !fp ) return( 0 );
+ while( fscanf( fp, "%s %d %s", s, &proto, nick ) > 0 )
+ {
+ http_decode( s );
+ nick_set( irc, s, proto, nick );
+ }
+ fclose( fp );
+
+ if( set_getint( irc, "auto_connect" ) )
+ {
+ strcpy( s, "account on" ); /* Can't do this directly because r_c_s alters the string */
+ root_command_string( irc, ru, s, 0 );
+ }
+
+ return( 1 );
+}
+
+static int text_save( irc_t *irc )
+{
+ char s[512];
+ char path[512], new_path[512];
+ char *line;
+ nick_t *n;
+ set_t *set;
+ mode_t ou = umask( 0077 );
+ account_t *a;
+ FILE *fp;
+ char *hash;
+
+ /*\
+ * [SH] Nothing should be saved if no password is set, because the
+ * password is not set if it was wrong, or if one is not identified
+ * yet. This means that a malicious user could easily overwrite
+ * files owned by someone else:
+ * a Bad Thing, methinks
+ \*/
+
+ /* [WVG] No? Really? */
+
+ /*\
+ * [SH] Okay, okay, it wasn't really Wilmer who said that, it was
+ * me. I just thought it was funny.
+ \*/
+
+ hash = hashpass( irc );
+ if( hash == NULL )
+ {
+ irc_usermsg( irc, "Please register yourself if you want to save your settings." );
+ return( 0 );
+ }
+
+ g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".nicks~" );
+ fp = fopen( path, "w" );
+ if( !fp ) return( 0 );
+ for( n = irc->nicks; n; n = n->next )
+ {
+ strcpy( s, n->handle );
+ s[169] = 0; /* Prevent any overflow (169 ~ 512 / 3) */
+ http_encode( s );
+ g_snprintf( s + strlen( s ), 510 - strlen( s ), " %d %s", n->proto, n->nick );
+ if( fprintf( fp, "%s\n", s ) != strlen( s ) + 1 )
+ {
+ irc_usermsg( irc, "fprintf() wrote too little. Disk full?" );
+ fclose( fp );
+ return( 0 );
+ }
+ }
+ if( fclose( fp ) != 0 )
+ {
+ irc_usermsg( irc, "fclose() reported an error. Disk full?" );
+ return( 0 );
+ }
+
+ g_snprintf( new_path, 512, "%s%s%s", global.conf->configdir, irc->nick, ".nicks" );
+ if( unlink( new_path ) != 0 )
+ {
+ if( errno != ENOENT )
+ {
+ irc_usermsg( irc, "Error while removing old .nicks file" );
+ return( 0 );
+ }
+ }
+ if( rename( path, new_path ) != 0 )
+ {
+ irc_usermsg( irc, "Error while renaming new .nicks file" );
+ return( 0 );
+ }
+
+ g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".accounts~" );
+ fp = fopen( path, "w" );
+ if( !fp ) return( 0 );
+ if( fprintf( fp, "%s", hash ) != strlen( hash ) )
+ {
+ irc_usermsg( irc, "fprintf() wrote too little. Disk full?" );
+ fclose( fp );
+ return( 0 );
+ }
+ g_free( hash );
+
+ for( a = irc->accounts; a; a = a->next )
+ {
+ if( a->protocol == PROTO_OSCAR || a->protocol == PROTO_ICQ || a->protocol == PROTO_TOC )
+ g_snprintf( s, sizeof( s ), "account add oscar \"%s\" \"%s\" %s", a->user, a->pass, a->server );
+ else
+ g_snprintf( s, sizeof( s ), "account add %s \"%s\" \"%s\" \"%s\"",
+ proto_name[a->protocol], a->user, a->pass, a->server ? a->server : "" );
+
+ line = obfucrypt( irc, s );
+ if( *line )
+ {
+ if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 )
+ {
+ irc_usermsg( irc, "fprintf() wrote too little. Disk full?" );
+ fclose( fp );
+ return( 0 );
+ }
+ }
+ g_free( line );
+ }
+
+ for( set = irc->set; set; set = set->next )
+ {
+ if( set->value && set->def )
+ {
+ g_snprintf( s, sizeof( s ), "set %s \"%s\"", set->key, set->value );
+ line = obfucrypt( irc, s );
+ if( *line )
+ {
+ if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 )
+ {
+ irc_usermsg( irc, "fprintf() wrote too little. Disk full?" );
+ fclose( fp );
+ return( 0 );
+ }
+ }
+ g_free( line );
+ }
+ }
+
+ if( strcmp( irc->mynick, ROOT_NICK ) != 0 )
+ {
+ g_snprintf( s, sizeof( s ), "rename %s %s", ROOT_NICK, irc->mynick );
+ line = obfucrypt( irc, s );
+ if( *line )
+ {
+ if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 )
+ {
+ irc_usermsg( irc, "fprintf() wrote too little. Disk full?" );
+ fclose( fp );
+ return( 0 );
+ }
+ }
+ g_free( line );
+ }
+ if( fclose( fp ) != 0 )
+ {
+ irc_usermsg( irc, "fclose() reported an error. Disk full?" );
+ return( 0 );
+ }
+
+ g_snprintf( new_path, 512, "%s%s%s", global.conf->configdir, irc->nick, ".accounts" );
+ if( unlink( new_path ) != 0 )
+ {
+ if( errno != ENOENT )
+ {
+ irc_usermsg( irc, "Error while removing old .accounts file" );
+ return( 0 );
+ }
+ }
+ if( rename( path, new_path ) != 0 )
+ {
+ irc_usermsg( irc, "Error while renaming new .accounts file" );
+ return( 0 );
+ }
+
+ umask( ou );
+
+ return( 1 );
+}
+
+static int text_exists( const char *nick )
+{
+ char path[512];
+ int checkie;
+
+ g_snprintf( path, 511, "%s%s%s", global.conf->configdir, nick, ".accounts" );
+ checkie = access( path, F_OK );
+
+ g_snprintf( path, 511, "%s%s%s", global.conf->configdir, nick, ".nicks" );
+ checkie += access( path, F_OK );
+
+ return ( checkie != -2 );
+}
+
+static int text_remove( const char *nick )
+{
+ char s[512];
+
+ g_snprintf( s, 511, "%s%s%s", global.conf->configdir, nick, ".accounts" );
+ if (unlink( s ) == -1)
+ return( 1 );
+
+ g_snprintf( s, 511, "%s%s%s", global.conf->configdir, nick, ".nicks" );
+ if (unlink( s ) == -1)
+ return( 1 );
+
+ return( 0 );
+}
+
+static int text_check_pass( const char *nick, const char *password )
+{
+ char s[512];
+ FILE *fp;
+
+ g_snprintf( s, 511, "%s%s%s", global.conf->configdir, nick, ".nicks" );
+ fp = fopen( s, "r" );
+
+ fscanf( fp, "%32[^\n]s", s );
+ fclose( fp );
+
+ /* FIXME */
+ return( 0 );
+}
+
+storage_t storage_text = {
+ .name = "text",
+ .init = text_init,
+ .exists = text_exists,
+ .check_pass = text_check_pass,
+ .remove = text_remove,
+ .load = text_load,
+ .save = text_save
+};