1 /********************************************************************\
2 * BitlBee -- An IRC to other IM-networks gateway *
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
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
)
46 for (gl
= storage_backends
; gl
; gl
= gl
->next
) {
48 if (strcmp(st
->name
, name
) == 0)
61 GList
*storage_init(const char *primary
, char **migrate
)
67 register_storage_backend(&storage_xml
);
69 storage
= storage_init_single(primary
);
70 if (storage
== NULL
&& storage
->save
== NULL
)
73 ret
= g_list_append(ret
, storage
);
75 for (i
= 0; migrate
&& migrate
[i
]; i
++) {
76 storage
= storage_init_single(migrate
[i
]);
79 ret
= g_list_append(ret
, storage
);
85 storage_status_t
storage_check_pass (const char *nick
, const char *password
)
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
)
100 return STORAGE_NO_SUCH_USER
;
103 storage_status_t
storage_load (irc_t
* irc
, const char *password
)
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
)
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
);
128 if (status
!= STORAGE_NO_SUCH_USER
)
132 return STORAGE_NO_SUCH_USER
;
135 storage_status_t
storage_save (irc_t
*irc
, char *password
, int overwrite
)
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
);
166 storage_status_t
storage_remove (const char *nick
, const char *password
)
169 storage_status_t ret
= STORAGE_OK
;
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
)
186 /* If at least one succeeded, remove plugin data. */
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
);
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
;
208 /* First, try to rename in the current write backend, assuming onick
210 status
= primary_storage
->rename(onick
, nnick
, password
);
211 if (status
!= STORAGE_NO_SUCH_USER
)
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
) {
226 irc
->nick
= g_strdup(nnick
);
228 status
= storage_save(irc
, FALSE
);
229 if (status
!= STORAGE_OK
) {
235 storage_remove(onick
, password
);