diff options
Diffstat (limited to 'storage.c')
-rw-r--r-- | storage.c | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/storage.c b/storage.c new file mode 100644 index 00000000..b766c9e3 --- /dev/null +++ b/storage.c @@ -0,0 +1,185 @@ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2002-2004 Wilmer van der Gaast and others * + \********************************************************************/ + +/* Support for multiple storage backends */ + +/* + 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" + +extern storage_t storage_text; + +static GList text_entry = { &storage_text, NULL, NULL }; +static GList *storage_backends = &text_entry; + +void register_storage_backend(storage_t *backend) +{ + storage_backends = g_list_append(storage_backends, backend); +} + +static storage_t *storage_init_single(const char *name) +{ + GList *gl; + storage_t *st; + + for (gl = storage_backends; gl; gl = gl->next) { + st = gl->data; + if (strcmp(st->name, name) == 0) + break; + } + + if (gl == NULL) + return NULL; + + if (st->init) + st->init(); + + 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) +{ + 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) +{ + 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 ((storage_t *)global.storage->data)->save(irc, overwrite); +} + +storage_status_t storage_remove (const char *nick, const char *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) +{ + 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; +} |