source: storage.c @ d628339

Last change on this file since d628339 was d628339, checked in by Wilmer van der Gaast <wilmer@…>, at 2015-06-08T01:13:47Z

Don't fail config load if a protocol is supported, just remember the data.

Otherwise things will get quite annoying when an RPC plugin is temporarily
not running. (I think things will still be quite annoying this way, but let's
see.)

  • Property mode set to 100644
File size: 4.7 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., 51 Franklin St.,
25  Fifth Floor, Boston, MA  02110-1301  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
36const struct prpl protocol_missing = {
37        .name = "_unknown",
38};
39
40void register_storage_backend(storage_t *backend)
41{
42        storage_backends = g_list_append(storage_backends, backend);
43}
44
45static storage_t *storage_init_single(const char *name)
46{
47        GList *gl;
48        storage_t *st = NULL;
49
50        for (gl = storage_backends; gl; gl = gl->next) {
51                st = gl->data;
52                if (strcmp(st->name, name) == 0) {
53                        break;
54                }
55        }
56
57        if (gl == NULL) {
58                return NULL;
59        }
60
61        if (st->init) {
62                st->init();
63        }
64
65        return st;
66}
67
68GList *storage_init(const char *primary, char **migrate)
69{
70        GList *ret = NULL;
71        int i;
72        storage_t *storage;
73
74        register_storage_backend(&storage_xml);
75
76        storage = storage_init_single(primary);
77        if (storage == NULL && storage->save == NULL) {
78                return NULL;
79        }
80
81        ret = g_list_append(ret, storage);
82
83        for (i = 0; migrate && migrate[i]; i++) {
84                storage = storage_init_single(migrate[i]);
85
86                if (storage) {
87                        ret = g_list_append(ret, storage);
88                }
89        }
90
91        return ret;
92}
93
94storage_status_t storage_check_pass(const char *nick, const char *password)
95{
96        GList *gl;
97
98        /* Loop until we don't get NO_SUCH_USER */
99
100        for (gl = global.storage; gl; gl = gl->next) {
101                storage_t *st = gl->data;
102                storage_status_t status;
103
104                status = st->check_pass(nick, password);
105                if (status != STORAGE_NO_SUCH_USER) {
106                        return status;
107                }
108        }
109
110        return STORAGE_NO_SUCH_USER;
111}
112
113storage_status_t storage_load(irc_t * irc, const char *password)
114{
115        GList *gl;
116
117        if (irc && irc->status & USTATUS_IDENTIFIED) {
118                return STORAGE_OTHER_ERROR;
119        }
120
121        /* Loop until we don't get NO_SUCH_USER */
122        for (gl = global.storage; gl; gl = gl->next) {
123                storage_t *st = gl->data;
124                storage_status_t status;
125
126                status = st->load(irc, password);
127                if (status == STORAGE_OK) {
128                        GSList *l;
129                        for (l = irc_plugins; l; l = l->next) {
130                                irc_plugin_t *p = l->data;
131                                if (p->storage_load) {
132                                        p->storage_load(irc);
133                                }
134                        }
135                        return status;
136                }
137
138                if (status != STORAGE_NO_SUCH_USER) {
139                        return status;
140                }
141        }
142
143        return STORAGE_NO_SUCH_USER;
144}
145
146storage_status_t storage_save(irc_t *irc, char *password, int overwrite)
147{
148        storage_status_t st;
149        GSList *l;
150
151        if (password != NULL) {
152                /* Should only use this in the "register" command. */
153                if (irc->password || overwrite) {
154                        return STORAGE_OTHER_ERROR;
155                }
156
157                irc_setpass(irc, password);
158        } else if ((irc->status & USTATUS_IDENTIFIED) == 0) {
159                return STORAGE_NO_SUCH_USER;
160        }
161
162        st = ((storage_t *) global.storage->data)->save(irc, overwrite);
163
164        for (l = irc_plugins; l; l = l->next) {
165                irc_plugin_t *p = l->data;
166                if (p->storage_save) {
167                        p->storage_save(irc);
168                }
169        }
170
171        if (password != NULL) {
172                irc_setpass(irc, NULL);
173        }
174
175        return st;
176}
177
178storage_status_t storage_remove(const char *nick, const char *password)
179{
180        GList *gl;
181        storage_status_t ret = STORAGE_OK;
182        gboolean ok = FALSE;
183        GSList *l;
184
185        /* Remove this account from all storage backends. If this isn't
186         * done, the account will still be usable, it'd just be
187         * loaded from a different backend. */
188        for (gl = global.storage; gl; gl = gl->next) {
189                storage_t *st = gl->data;
190                storage_status_t status;
191
192                status = st->remove(nick, password);
193                ok |= status == STORAGE_OK;
194                if (status != STORAGE_NO_SUCH_USER && status != STORAGE_OK) {
195                        ret = status;
196                }
197        }
198
199        /* If at least one succeeded, remove plugin data. */
200        if (ok) {
201                for (l = irc_plugins; l; l = l->next) {
202                        irc_plugin_t *p = l->data;
203                        if (p->storage_remove) {
204                                p->storage_remove(nick);
205                        }
206                }
207        }
208
209        return ret;
210}
Note: See TracBrowser for help on using the repository browser.