diff options
Diffstat (limited to 'storage.c')
| -rw-r--r-- | storage.c | 114 | 
1 files changed, 108 insertions, 6 deletions
| @@ -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;  } | 
