Index: bitlbee.h
===================================================================
--- bitlbee.h	(revision a301379c2035d9d0dd86926c4bdeebf95db18fac)
+++ bitlbee.h	(revision b73ac9c35fb53203b8d0668251dfb66096883863)
@@ -116,5 +116,5 @@
 	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;
Index: commands.c
===================================================================
--- commands.c	(revision a301379c2035d9d0dd86926c4bdeebf95db18fac)
+++ commands.c	(revision b73ac9c35fb53203b8d0668251dfb66096883863)
@@ -102,5 +102,5 @@
 		break;
 	}
-	
+
 	return( 0 );
 }
Index: conf.c
===================================================================
--- conf.c	(revision a301379c2035d9d0dd86926c4bdeebf95db18fac)
+++ conf.c	(revision b73ac9c35fb53203b8d0668251dfb66096883863)
@@ -50,5 +50,5 @@
 	conf->nofork = 0;
 	conf->verbose = 0;
-	conf->storage = "text";
+	conf->primary_storage = "text";
 	conf->runmode = RUNMODE_INETD;
 	conf->authmode = AUTHMODE_OPEN;
@@ -199,8 +199,13 @@
 				conf->motdfile = g_strdup( ini->value );
 			}
-			else if( g_strcasecmp( ini->key, "storage" ) == 0 )
-			{
-				g_free( conf->storage );
-				conf->storage = g_strdup( ini->value );
+			else if( g_strcasecmp( ini->key, "account_storage" ) == 0 )
+			{
+				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 )
Index: conf.h
===================================================================
--- conf.h	(revision a301379c2035d9d0dd86926c4bdeebf95db18fac)
+++ conf.h	(revision b73ac9c35fb53203b8d0668251dfb66096883863)
@@ -42,5 +42,6 @@
 	char *configdir;
 	char *motdfile;
-	char *storage;
+	char *primary_storage;
+	char **migrate_storage;
 	int ping_interval;
 	int ping_timeout;
Index: irc.c
===================================================================
--- irc.c	(revision a301379c2035d9d0dd86926c4bdeebf95db18fac)
+++ irc.c	(revision b73ac9c35fb53203b8d0668251dfb66096883863)
@@ -161,5 +161,5 @@
 	
 	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!" );
 	
Index: storage.c
===================================================================
--- storage.c	(revision a301379c2035d9d0dd86926c4bdeebf95db18fac)
+++ storage.c	(revision b73ac9c35fb53203b8d0668251dfb66096883863)
@@ -38,5 +38,5 @@
 }
 
-storage_t *storage_init(const char *name)
+static storage_t *storage_init_single(const char *name)
 {
 	GList *gl;
@@ -58,26 +58,128 @@
 }
 
+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;
 }
Index: storage.h
===================================================================
--- storage.h	(revision a301379c2035d9d0dd86926c4bdeebf95db18fac)
+++ storage.h	(revision b73ac9c35fb53203b8d0668251dfb66096883863)
@@ -62,5 +62,5 @@
 
 void register_storage_backend(storage_t *);
-storage_t *storage_init(const char *name);
+GList *storage_init(const char *primary, char **migrate);
 
 #endif /* __STORAGE_H__ */
Index: storage_text.c
===================================================================
--- storage_text.c	(revision a301379c2035d9d0dd86926c4bdeebf95db18fac)
+++ storage_text.c	(revision b73ac9c35fb53203b8d0668251dfb66096883863)
@@ -67,5 +67,6 @@
 	{
 		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 );
@@ -129,9 +130,9 @@
 	\*/
 	
-	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;
 	}
 	
@@ -192,5 +193,5 @@
 			            proto_name[a->protocol], a->user, a->pass, a->server ? a->server : "" );
 		
-		line = obfucrypt( irc, s );
+		line = obfucrypt( s, irc->password );
 		if( *line )
 		{
@@ -210,5 +211,5 @@
 		{
 			g_snprintf( s, sizeof( s ), "set %s \"%s\"", set->key, set->value );
-			line = obfucrypt( irc, s );
+			line = obfucrypt( s, irc->password );
 			if( *line )
 			{
@@ -227,5 +228,5 @@
 	{
 		g_snprintf( s, sizeof( s ), "rename %s %s", ROOT_NICK, irc->mynick );
-		line = obfucrypt( irc, s );
+		line = obfucrypt( s, irc->password );
 		if( *line )
 		{
@@ -270,5 +271,5 @@
 	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)
Index: unix.c
===================================================================
--- unix.c	(revision a301379c2035d9d0dd86926c4bdeebf95db18fac)
+++ unix.c	(revision b73ac9c35fb53203b8d0668251dfb66096883863)
@@ -72,7 +72,8 @@
 		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 );
 	}
