source: storage.c @ 87872c7

Last change on this file since 87872c7 was 5a8afc3, checked in by dequis <dx@…>, at 2016-11-21T06:58:47Z

Manual merge with wilmer's approach to handling missing protocols

Turns out he already implemented pretty much the same thing in the
parson branch... last year.

The differences between the two approaches are subtle (there aren't too
many ways to do this, some lines are the exact same thing) but I decided
I like his version better, so this mostly reverts a handful of my
changes while keeping others. The main advantage of his approach is that
no fake protocols are registered, no actual prpl functions are called,
and the missing prpl is a singleton constant.

New things compared to the implementation in the other branch:

  • The explain_unknown_protocol() function.
  • Fixed named chatrooms throwing a warning and losing the "account" setting when saving. See changes in irc_im.c
  • Fixed the "server" setting dropping when saving. See account.c

Differences with my previous implementation:

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