source: storage.c @ 693ff09

Last change on this file since 693ff09 was 2dcaf9a, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-09-01T22:35:06Z

Load/save code. It'd be better if the OTR module would just save its info
in BitlBee settings that automatically end up in the existing .xml files
(or whatever storage is used), but I realise this is non-trivial.

  • Property mode set to 100644
File size: 5.6 KB
Line 
1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
4  * Copyright 2002-2004 Wilmer van der Gaast and others                *
5  \********************************************************************/
6
7/* Support for multiple storage backends */
8
9/* Copyright (C) 2005 Jelmer Vernooij <jelmer@samba.org> */
10
11/*
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.
16
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.
21
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
26*/
27
28#define BITLBEE_CORE
29#include "bitlbee.h"
30
31extern storage_t storage_text;
32extern storage_t storage_xml;
33
34static GList *storage_backends = NULL;
35
36void register_storage_backend(storage_t *backend)
37{
38        storage_backends = g_list_append(storage_backends, backend);
39}
40
41static storage_t *storage_init_single(const char *name)
42{
43        GList *gl;
44        storage_t *st = NULL;
45
46        for (gl = storage_backends; gl; gl = gl->next) {
47                st = gl->data;
48                if (strcmp(st->name, name) == 0)
49                        break;
50        }
51
52        if (gl == NULL) 
53                return NULL;
54
55        if (st->init)
56                st->init();
57
58        return st;
59}
60
61GList *storage_init(const char *primary, char **migrate)
62{
63        GList *ret = NULL;
64        int i;
65        storage_t *storage;
66       
67        register_storage_backend(&storage_xml);
68       
69        storage = storage_init_single(primary);
70        if (storage == NULL && storage->save == NULL)
71                return NULL;
72
73        ret = g_list_append(ret, storage);
74
75        for (i = 0; migrate && migrate[i]; i++) {
76                storage = storage_init_single(migrate[i]);
77       
78                if (storage)
79                        ret = g_list_append(ret, storage);
80        }
81
82        return ret;
83}
84
85storage_status_t storage_check_pass (const char *nick, const char *password)
86{
87        GList *gl;
88       
89        /* Loop until we don't get NO_SUCH_USER */
90
91        for (gl = global.storage; gl; gl = gl->next) {
92                storage_t *st = gl->data;
93                storage_status_t status;
94
95                status = st->check_pass(nick, password);
96                if (status != STORAGE_NO_SUCH_USER)
97                        return status;
98        }
99       
100        return STORAGE_NO_SUCH_USER;
101}
102
103storage_status_t storage_load (irc_t * irc, const char *password)
104{
105        GList *gl;
106       
107        if (irc && irc->status & USTATUS_IDENTIFIED)
108                return STORAGE_OTHER_ERROR;
109       
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;
114
115                status = st->load(irc, password);
116                if (status == STORAGE_OK)
117                {
118                        GSList *l;
119                        for( l = irc_plugins; l; l = l->next )
120                        {
121                                irc_plugin_t *p = l->data;
122                                if( p->storage_load )
123                                        p->storage_load( irc );
124                        }
125                        return status;
126                }
127               
128                if (status != STORAGE_NO_SUCH_USER) 
129                        return status;
130        }
131       
132        return STORAGE_NO_SUCH_USER;
133}
134
135storage_status_t storage_save (irc_t *irc, char *password, int overwrite)
136{
137        storage_status_t st;
138        GSList *l;
139       
140        if (password != NULL) {
141                /* Should only use this in the "register" command. */
142                if (irc->password || overwrite)
143                        return STORAGE_OTHER_ERROR;
144               
145                irc_setpass(irc, password);
146        } else if ((irc->status & USTATUS_IDENTIFIED) == 0) {
147                return STORAGE_NO_SUCH_USER;
148        }
149       
150        st = ((storage_t *)global.storage->data)->save(irc, overwrite);
151       
152        for( l = irc_plugins; l; l = l->next )
153        {
154                irc_plugin_t *p = l->data;
155                if( p->storage_save )
156                        p->storage_save( irc );
157        }
158       
159        if (password != NULL) {
160                irc_setpass(irc, NULL);
161        }
162       
163        return st;
164}
165
166storage_status_t storage_remove (const char *nick, const char *password)
167{
168        GList *gl;
169        storage_status_t ret = STORAGE_OK;
170        gboolean ok = FALSE;
171        GSList *l;
172       
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;
179
180                status = st->remove(nick, password);
181                ok |= status == STORAGE_OK;
182                if (status != STORAGE_NO_SUCH_USER && status != STORAGE_OK)
183                        ret = status;
184        }
185       
186        /* If at least one succeeded, remove plugin data. */
187        if( ok )
188                for( l = irc_plugins; l; l = l->next )
189                {
190                        irc_plugin_t *p = l->data;
191                        if( p->storage_remove )
192                                p->storage_remove( nick );
193                }
194       
195        return ret;
196}
197
198#if 0
199Not using this yet. Test thoroughly before adding UI hooks to this function.
200
201storage_status_t storage_rename (const char *onick, const char *nnick, const char *password)
202{
203        storage_status_t status;
204        GList *gl = global.storage;
205        storage_t *primary_storage = gl->data;
206        irc_t *irc;
207
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;
213
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 */
217       
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;
223        }
224
225        g_free(irc->nick);
226        irc->nick = g_strdup(nnick);
227
228        status = storage_save(irc, FALSE);
229        if (status != STORAGE_OK) {
230                irc_free(irc);
231                return status;
232        }
233        irc_free(irc);
234
235        storage_remove(onick, password);
236
237        return STORAGE_OK;
238}
239#endif
Note: See TracBrowser for help on using the repository browser.