diff options
author | Jelmer Vernooij <jelmer@samba.org> | 2005-12-14 00:05:27 +0100 |
---|---|---|
committer | Jelmer Vernooij <jelmer@samba.org> | 2005-12-14 00:05:27 +0100 |
commit | b73ac9c35fb53203b8d0668251dfb66096883863 (patch) | |
tree | b5e10b15e55ec9453bf902431a3b9dc24310378c | |
parent | a301379c2035d9d0dd86926c4bdeebf95db18fac (diff) |
Add support for 'primary' and 'migrate' account storages.
Fix two bugs in the text storage backend that were introduced by my previous
changes.
-rw-r--r-- | bitlbee.h | 2 | ||||
-rw-r--r-- | commands.c | 2 | ||||
-rw-r--r-- | conf.c | 13 | ||||
-rw-r--r-- | conf.h | 3 | ||||
-rw-r--r-- | irc.c | 2 | ||||
-rw-r--r-- | storage.c | 114 | ||||
-rw-r--r-- | storage.h | 2 | ||||
-rw-r--r-- | storage_text.c | 15 | ||||
-rw-r--r-- | unix.c | 5 |
9 files changed, 134 insertions, 24 deletions
@@ -115,7 +115,7 @@ typedef struct global_t { int listen_socket; help_t *help; conf_t *conf; - storage_t *storage; + GList *storage; /* The first backend in the list will be used for saving */ char *helpfile; GMainLoop *loop; } global_t; @@ -101,7 +101,7 @@ int cmd_identify( irc_t *irc, char **cmd ) irc_usermsg( irc, "Something very weird happened" ); break; } - + return( 0 ); } @@ -49,7 +49,7 @@ conf_t *conf_load( int argc, char *argv[] ) conf->port = 6667; conf->nofork = 0; conf->verbose = 0; - conf->storage = "text"; + conf->primary_storage = "text"; conf->runmode = RUNMODE_INETD; conf->authmode = AUTHMODE_OPEN; conf->password = NULL; @@ -198,10 +198,15 @@ static int conf_loadini( conf_t *conf, char *file ) g_free( conf->motdfile ); conf->motdfile = g_strdup( ini->value ); } - else if( g_strcasecmp( ini->key, "storage" ) == 0 ) + else if( g_strcasecmp( ini->key, "account_storage" ) == 0 ) { - g_free( conf->storage ); - conf->storage = g_strdup( ini->value ); + g_free( conf->primary_storage ); + conf->primary_storage = g_strdup( ini->value ); + } + else if( g_strcasecmp( ini->key, "account_storage_migrate" ) == 0 ) + { + g_strfreev( conf->migrate_storage ); + conf->migrate_storage = g_strsplit( ini->value, " \t,;", -1 ); } else if( g_strcasecmp( ini->key, "pinginterval" ) == 0 ) { @@ -41,7 +41,8 @@ typedef struct conf char *hostname; char *configdir; char *motdfile; - char *storage; + char *primary_storage; + char **migrate_storage; int ping_interval; int ping_timeout; } conf_t; @@ -160,7 +160,7 @@ void irc_free(irc_t * irc) log_message( LOGLVL_INFO, "Destroying connection with fd %d", irc->fd ); if( irc->status >= USTATUS_IDENTIFIED && set_getint( irc, "save_on_quit" ) ) - if( !storage_save( irc, TRUE ) ) + if( storage_save( irc, TRUE ) != STORAGE_OK ) irc_usermsg( irc, "Error while saving settings!" ); if( irc->ping_source_id > 0 ) @@ -37,7 +37,7 @@ void register_storage_backend(storage_t *backend) storage_backends = g_list_append(storage_backends, backend); } -storage_t *storage_init(const char *name) +static storage_t *storage_init_single(const char *name) { GList *gl; storage_t *st; @@ -57,27 +57,129 @@ storage_t *storage_init(const char *name) return st; } +GList *storage_init(const char *primary, char **migrate) +{ + GList *ret = NULL; + int i; + storage_t *storage; + + storage = storage_init_single(primary); + if (storage == NULL) + return NULL; + + ret = g_list_append(ret, storage); + + for (i = 0; migrate && migrate[i]; i++) { + storage = storage_init_single(migrate[i]); + + if (storage) + ret = g_list_append(ret, storage); + } + + return ret; +} + storage_status_t storage_check_pass (const char *nick, const char *password) { - return global.storage->check_pass(nick, password); + GList *gl; + + /* Loop until we don't get NO_SUCH_USER */ + + for (gl = global.storage; gl; gl = gl->next) { + storage_t *st = gl->data; + storage_status_t status; + + status = st->check_pass(nick, password); + if (status != STORAGE_NO_SUCH_USER) + return status; + } + + return STORAGE_NO_SUCH_USER; } storage_status_t storage_load (const char *nick, const char *password, irc_t * irc) { - return global.storage->load(nick, password, irc); + GList *gl; + + /* Loop until we don't get NO_SUCH_USER */ + for (gl = global.storage; gl; gl = gl->next) { + storage_t *st = gl->data; + storage_status_t status; + + status = st->load(nick, password, irc); + if (status == STORAGE_OK) { + irc_setpass(irc, password); + return status; + } + + if (status != STORAGE_NO_SUCH_USER) + return status; + } + + return STORAGE_NO_SUCH_USER; } storage_status_t storage_save (irc_t *irc, int overwrite) { - return global.storage->save(irc, overwrite); + return ((storage_t *)global.storage->data)->save(irc, overwrite); } storage_status_t storage_remove (const char *nick, const char *password) { - return global.storage->remove(nick, password); + GList *gl; + storage_status_t ret = STORAGE_OK; + + /* Remove this account from all storage backends. If this isn't + * done, the account will still be usable, it'd just be + * loaded from a different backend. */ + for (gl = global.storage; gl; gl = gl->next) { + storage_t *st = gl->data; + storage_status_t status; + + status = st->remove(nick, password); + if (status != STORAGE_NO_SUCH_USER && + status != STORAGE_OK) + ret = status; + } + + return ret; } storage_status_t storage_rename (const char *onick, const char *nnick, const char *password) { - return global.storage->rename(onick, nnick, password); + storage_status_t status; + GList *gl = global.storage; + storage_t *primary_storage = gl->data; + irc_t *irc; + + /* First, try to rename in the current write backend, assuming onick + * is stored there */ + status = primary_storage->rename(onick, nnick, password); + if (status != STORAGE_NO_SUCH_USER) + return status; + + /* Try to load from a migration backend and save to the current backend. + * Explicitly remove the account from the migration backend as otherwise + * it'd still be usable under the old name */ + + irc = g_new0(irc_t, 1); + status = storage_load(onick, password, irc); + if (status != STORAGE_OK) { + irc_free(irc); + return status; + } + + g_free(irc->nick); + irc->nick = g_strdup(nnick); + + status = storage_save(irc, FALSE); + if (status != STORAGE_OK) { + irc_free(irc); + return status; + } + irc_free(irc); + + storage_remove(onick, password); + + return STORAGE_OK; } @@ -61,6 +61,6 @@ storage_status_t storage_remove (const char *nick, const char *password); storage_status_t storage_rename (const char *onick, const char *nnick, const char *password); void register_storage_backend(storage_t *); -storage_t *storage_init(const char *name); +GList *storage_init(const char *primary, char **migrate); #endif /* __STORAGE_H__ */ diff --git a/storage_text.c b/storage_text.c index f3ca8a38..5909ff63 100644 --- a/storage_text.c +++ b/storage_text.c @@ -66,7 +66,8 @@ static storage_status_t text_load ( const char *my_nick, const char* password, i while( fscanf( fp, "%511[^\n]s", s ) > 0 ) { fgetc( fp ); - line = deobfucrypt( irc, s ); + line = deobfucrypt( s, password ); + if (line == NULL) return STORAGE_OTHER_ERROR; root_command_string( irc, ru, line, 0 ); g_free( line ); } @@ -128,11 +129,11 @@ static storage_status_t text_save( irc_t *irc, int overwrite ) * me. I just thought it was funny. \*/ - hash = hashpass( irc ); + hash = hashpass( irc->password ); if( hash == NULL ) { irc_usermsg( irc, "Please register yourself if you want to save your settings." ); - return( 0 ); + return STORAGE_OTHER_ERROR; } g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".nicks~" ); @@ -191,7 +192,7 @@ static storage_status_t text_save( irc_t *irc, int overwrite ) 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 ); + line = obfucrypt( s, irc->password ); if( *line ) { if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 ) @@ -209,7 +210,7 @@ static storage_status_t text_save( irc_t *irc, int overwrite ) if( set->value && set->def ) { g_snprintf( s, sizeof( s ), "set %s \"%s\"", set->key, set->value ); - line = obfucrypt( irc, s ); + line = obfucrypt( s, irc->password ); if( *line ) { if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 ) @@ -226,7 +227,7 @@ static storage_status_t text_save( irc_t *irc, int overwrite ) if( strcmp( irc->mynick, ROOT_NICK ) != 0 ) { g_snprintf( s, sizeof( s ), "rename %s %s", ROOT_NICK, irc->mynick ); - line = obfucrypt( irc, s ); + line = obfucrypt( s, irc->password ); if( *line ) { if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 ) @@ -269,7 +270,7 @@ static storage_status_t 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" ); + g_snprintf( s, 511, "%s%s%s", global.conf->configdir, nick, ".accounts" ); fp = fopen( s, "r" ); if (!fp) return STORAGE_NO_SUCH_USER; @@ -71,9 +71,10 @@ int main( int argc, char *argv[] ) if( i != 0 ) return( i ); - global.storage = storage_init( global.conf->storage ); + global.storage = storage_init( global.conf->primary_storage, + global.conf->migrate_storage ); if ( global.storage == NULL) { - log_message( LOGLVL_ERROR, "No such storage backend '%s'", global.conf->storage ); + log_message( LOGLVL_ERROR, "Unable to load storage backend '%s'", global.conf->primary_storage ); return( 1 ); } |