Commit two patches from RH package maintainer (#956).
[bitlbee.git] / storage.c
blobd64d9cdad1ecf0268b30b90dc9f0ce92af602ddf
1 /********************************************************************\
2 * BitlBee -- An IRC to other IM-networks gateway *
3 * *
4 * Copyright 2002-2004 Wilmer van der Gaast and others *
5 \********************************************************************/
7 /* Support for multiple storage backends */
9 /* Copyright (C) 2005 Jelmer Vernooij <jelmer@samba.org> */
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License with
23 the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
24 if not, write to the Free Software Foundation, Inc., 59 Temple Place,
25 Suite 330, Boston, MA 02111-1307 USA
28 #define BITLBEE_CORE
29 #include "bitlbee.h"
31 extern storage_t storage_text;
32 extern storage_t storage_xml;
34 static GList *storage_backends = NULL;
36 void register_storage_backend(storage_t *backend)
38 storage_backends = g_list_append(storage_backends, backend);
41 static storage_t *storage_init_single(const char *name)
43 GList *gl;
44 storage_t *st = NULL;
46 for (gl = storage_backends; gl; gl = gl->next) {
47 st = gl->data;
48 if (strcmp(st->name, name) == 0)
49 break;
52 if (gl == NULL)
53 return NULL;
55 if (st->init)
56 st->init();
58 return st;
61 GList *storage_init(const char *primary, char **migrate)
63 GList *ret = NULL;
64 int i;
65 storage_t *storage;
67 register_storage_backend(&storage_xml);
69 storage = storage_init_single(primary);
70 if (storage == NULL && storage->save == NULL)
71 return NULL;
73 ret = g_list_append(ret, storage);
75 for (i = 0; migrate && migrate[i]; i++) {
76 storage = storage_init_single(migrate[i]);
78 if (storage)
79 ret = g_list_append(ret, storage);
82 return ret;
85 storage_status_t storage_check_pass (const char *nick, const char *password)
87 GList *gl;
89 /* Loop until we don't get NO_SUCH_USER */
91 for (gl = global.storage; gl; gl = gl->next) {
92 storage_t *st = gl->data;
93 storage_status_t status;
95 status = st->check_pass(nick, password);
96 if (status != STORAGE_NO_SUCH_USER)
97 return status;
100 return STORAGE_NO_SUCH_USER;
103 storage_status_t storage_load (irc_t * irc, const char *password)
105 GList *gl;
107 if (irc && irc->status & USTATUS_IDENTIFIED)
108 return STORAGE_OTHER_ERROR;
110 /* Loop until we don't get NO_SUCH_USER */
111 for (gl = global.storage; gl; gl = gl->next) {
112 storage_t *st = gl->data;
113 storage_status_t status;
115 status = st->load(irc, password);
116 if (status == STORAGE_OK)
118 GSList *l;
119 for( l = irc_plugins; l; l = l->next )
121 irc_plugin_t *p = l->data;
122 if( p->storage_load )
123 p->storage_load( irc );
125 return status;
128 if (status != STORAGE_NO_SUCH_USER)
129 return status;
132 return STORAGE_NO_SUCH_USER;
135 storage_status_t storage_save (irc_t *irc, char *password, int overwrite)
137 storage_status_t st;
138 GSList *l;
140 if (password != NULL) {
141 /* Should only use this in the "register" command. */
142 if (irc->password || overwrite)
143 return STORAGE_OTHER_ERROR;
145 irc_setpass(irc, password);
146 } else if ((irc->status & USTATUS_IDENTIFIED) == 0) {
147 return STORAGE_NO_SUCH_USER;
150 st = ((storage_t *)global.storage->data)->save(irc, overwrite);
152 for( l = irc_plugins; l; l = l->next )
154 irc_plugin_t *p = l->data;
155 if( p->storage_save )
156 p->storage_save( irc );
159 if (password != NULL) {
160 irc_setpass(irc, NULL);
163 return st;
166 storage_status_t storage_remove (const char *nick, const char *password)
168 GList *gl;
169 storage_status_t ret = STORAGE_OK;
170 gboolean ok = FALSE;
171 GSList *l;
173 /* Remove this account from all storage backends. If this isn't
174 * done, the account will still be usable, it'd just be
175 * loaded from a different backend. */
176 for (gl = global.storage; gl; gl = gl->next) {
177 storage_t *st = gl->data;
178 storage_status_t status;
180 status = st->remove(nick, password);
181 ok |= status == STORAGE_OK;
182 if (status != STORAGE_NO_SUCH_USER && status != STORAGE_OK)
183 ret = status;
186 /* If at least one succeeded, remove plugin data. */
187 if( ok )
188 for( l = irc_plugins; l; l = l->next )
190 irc_plugin_t *p = l->data;
191 if( p->storage_remove )
192 p->storage_remove( nick );
195 return ret;
198 #if 0
199 Not using this yet. Test thoroughly before adding UI hooks to this function.
201 storage_status_t storage_rename (const char *onick, const char *nnick, const char *password)
203 storage_status_t status;
204 GList *gl = global.storage;
205 storage_t *primary_storage = gl->data;
206 irc_t *irc;
208 /* First, try to rename in the current write backend, assuming onick
209 * is stored there */
210 status = primary_storage->rename(onick, nnick, password);
211 if (status != STORAGE_NO_SUCH_USER)
212 return status;
214 /* Try to load from a migration backend and save to the current backend.
215 * Explicitly remove the account from the migration backend as otherwise
216 * it'd still be usable under the old name */
218 irc = g_new0(irc_t, 1);
219 status = storage_load(onick, password, irc);
220 if (status != STORAGE_OK) {
221 irc_free(irc);
222 return status;
225 g_free(irc->nick);
226 irc->nick = g_strdup(nnick);
228 status = storage_save(irc, FALSE);
229 if (status != STORAGE_OK) {
230 irc_free(irc);
231 return status;
233 irc_free(irc);
235 storage_remove(onick, password);
237 return STORAGE_OK;
239 #endif