]> jfr.im git - irc/quakenet/newserv.git/blame - noperserv/noperserv_db.c
Fix off by one bug in dbvsnprintf, convert noperserv to use safe queries.
[irc/quakenet/newserv.git] / noperserv / noperserv_db.c
CommitLineData
3e3692bf
CP
1/*
2 * NOperserv v0.01
3 *
4 * A replacement for Germania's ageing Operservice2
5 * DB functions
6 *
7 * Copyright (C) 2005 Chris Porter.
8 */
9
10#include "../nick/nick.h"
11#include "../core/error.h"
12#include "../lib/irc_string.h"
13#include "../core/schedule.h"
114b4eea 14#include "../dbapi2/dbapi2.h"
3e3692bf
CP
15
16#include "noperserv.h"
3e3692bf
CP
17#include "noperserv_db.h"
18
3e3692bf
CP
19#include <stdlib.h>
20
e43481af 21int db_loaded = 0;
3e3692bf
CP
22unsigned long loadedusers = 0;
23
24unsigned long lastuserid;
25
26no_autheduser *authedusers = NULL;
27
e43481af
CP
28void noperserv_create_tables(void);
29
3e3692bf 30void noperserv_free_user(no_autheduser *au);
e54cd6b5 31void noperserv_load_users(const DBAPIResult *res, void *arg);
3e3692bf
CP
32
33void noperserv_check_nick(nick *np);
34void noperserv_nick_account(int hooknum, void *arg);
35void noperserv_quit_account(int hooknum, void *arg);
36
37void nopserserv_delete_from_autheduser(nick *np, no_autheduser *au);
3e3692bf 38
114b4eea
CP
39static DBAPIConn *nodb;
40
7a32ca6e 41int noperserv_load_db(void) {
114b4eea
CP
42 if(!nodb) {
43 nodb = dbapi2open(DBAPI2_DEFAULT, "noperserv");
44 if(!nodb) {
45 Error("noperserv", ERR_STOP, "Could not connect to database.");
46 return 0;
47 }
ad50c27c 48 }
7a32ca6e 49
e43481af 50 db_loaded = 1;
3e3692bf
CP
51
52 authedusers = NULL;
53
e43481af
CP
54 noperserv_create_tables();
55
e54cd6b5
CP
56 nodb->safequery(nodb, noperserv_load_users, NULL,
57 "SELECT ID, authname, flags, noticelevel FROM ?", "T", "users");
7a32ca6e
CP
58
59 return 1;
3e3692bf
CP
60}
61
e54cd6b5 62void noperserv_load_users(const DBAPIResult *res, void *arg) {
3e3692bf
CP
63 no_autheduser *nu;
64 nick *np;
ee8cd7d0 65 int i;
3e3692bf 66
114b4eea
CP
67 if(!res)
68 return;
69
70 if(!res->success) {
3e3692bf 71 Error("noperserv", ERR_ERROR, "Error loading user list.");
114b4eea
CP
72 res->clear(res);
73 return;
3e3692bf
CP
74 }
75
3e3692bf
CP
76 lastuserid = 0;
77
114b4eea
CP
78 while(res->next(res)) {
79 nu = noperserv_new_autheduser(res->get(res, 1));
3e3692bf
CP
80 if(!nu)
81 continue;
82
114b4eea
CP
83 nu->id = strtoul(res->get(res, 0), NULL, 10);
84 nu->authlevel = strtoul(res->get(res, 2), NULL, 10);
85 nu->noticelevel = strtoul(res->get(res, 3), NULL, 10);
3e3692bf
CP
86 nu->newuser = 0;
87 if(nu->id > lastuserid)
88 lastuserid = nu->id;
89 }
90
16739dbe 91 Error("noperserv", ERR_INFO, "Loaded %lu users", loadedusers);
3e3692bf
CP
92
93 for(i=0;i<NICKHASHSIZE;i++)
94 for(np=nicktable[i];np;np=np->next)
95 if(IsAccount(np))
96 noperserv_check_nick(np);
97
98 registerhook(HOOK_NICK_ACCOUNT, &noperserv_nick_account);
99 registerhook(HOOK_NICK_NEWNICK, &noperserv_nick_account);
100 registerhook(HOOK_NICK_LOSTNICK, &noperserv_quit_account);
ee8cd7d0 101
114b4eea 102 res->clear(res);
3e3692bf
CP
103}
104
105void noperserv_create_tables(void) {
e54cd6b5
CP
106 nodb->safecreatetable(nodb, NULL, NULL,
107 "CREATE TABLE ? ("
3e3692bf 108 "ID INT NOT NULL,"
e54cd6b5 109 "authname VARCHAR(?) NOT NULL,"
3e3692bf
CP
110 "flags INT NOT NULL,"
111 "noticelevel INT NOT NULL,"
e54cd6b5 112 "PRIMARY KEY (ID))", "Td", "users", ACCOUNTLEN);
3e3692bf
CP
113}
114
115void noperserv_cleanup_db(void) {
116 no_autheduser *ap, *np;
117
118 deregisterhook(HOOK_NICK_LOSTNICK, &noperserv_quit_account);
119 deregisterhook(HOOK_NICK_NEWNICK, &noperserv_nick_account);
120 deregisterhook(HOOK_NICK_ACCOUNT, &noperserv_nick_account);
121
122 ap = authedusers;
123 while(ap) {
124 np = ap->next;
125 noperserv_free_user(ap);
126 ap = np;
127 }
aa944539 128
114b4eea
CP
129 nodb->close(nodb);
130 nodb = NULL;
3e3692bf
CP
131}
132
133no_autheduser *noperserv_new_autheduser(char *authname) {
134 no_autheduser *au = (no_autheduser *)malloc(sizeof(no_autheduser));
135 if(!au)
136 return NULL;
137
138 au->authname = getsstring(authname, ACCOUNTLEN);
139 if(!au->authname) {
140 free(au);
141 return NULL;
142 }
143
144 loadedusers++;
145 au->newuser = 1;
146 au->nick = NULL;
147
148 au->next = authedusers;
149 authedusers = au;
150
151 return au;
152}
153
154void noperserv_delete_autheduser(no_autheduser *au) {
155 no_autheduser *ap = authedusers, *lp = NULL;
156
157 if(!au->newuser)
e54cd6b5 158 nodb->safesquery(nodb, "DELETE FROM ? WHERE id = ?", "Tu", "users", au->id);
3e3692bf
CP
159
160 for(;ap;lp=ap,ap=ap->next) {
161 if(ap == au) {
162 if(lp) {
163 lp->next = ap->next;
164 } else {
165 authedusers = ap->next;
166 }
167 noperserv_free_user(ap);
168 return;
169 }
170 }
171}
172
173void noperserv_update_autheduser(no_autheduser *au) {
174 if(au->newuser) {
175 char escapedauthname[ACCOUNTLEN * 2 + 1];
114b4eea 176 nodb->escapestring(nodb, escapedauthname, au->authname->content, au->authname->length);
e54cd6b5 177 nodb->safesquery(nodb, "INSERT INTO ? (id, authname, flags, noticelevel) VALUES (?,?,?,?)", "Tusuu", "users", au->id, au->authname->content, NOGetAuthLevel(au), NOGetNoticeLevel(au));
3e3692bf
CP
178 au->newuser = 0;
179 } else {
e54cd6b5 180 nodb->safesquery(nodb, "UPDATE ? SET flags = ?, noticelevel = ? WHERE id = ?", "Tuuu", "users", NOGetAuthLevel(au), NOGetNoticeLevel(au), au->id);
3e3692bf
CP
181 }
182}
183
184void noperserv_free_user(no_autheduser *au) {
185 no_nicklist *cp = au->nick, *np;
186
187 while(cp) {
188 cp->nick->exts[noperserv_ext] = NULL;
189 np = cp->next;
190 free(cp);
191 cp = np;
192 }
193
194 freesstring(au->authname);
195 free(au);
196
197 loadedusers--;
198}
199
200void noperserv_check_nick(nick *np) {
201 no_autheduser *au = noperserv_get_autheduser(np->authname);
202 if(au)
203 noperserv_add_to_autheduser(np, au);
204}
205
206void noperserv_nick_account(int hooknum, void *arg) {
207 noperserv_check_nick((nick *)arg);
208}
209
210void noperserv_quit_account(int hooknum, void *arg) {
211 nick *np = (void *)arg;
212 no_autheduser *au = NOGetAuthedUser(np);
213 no_nicklist *nl, *ln = NULL;
214 if(!au)
215 return;
216
217 for(nl=au->nick;nl;ln=nl,nl=nl->next)
218 if(nl->nick == np) {
219 if(ln) {
220 ln->next = nl->next;
221 } else {
222 au->nick = nl->next;
223 }
224 free(nl);
225 break;
226 }
227}
228
229no_autheduser *noperserv_get_autheduser(char *authname) {
230 no_autheduser *au = authedusers;
231
232 for(;au;au=au->next)
233 if(!ircd_strcmp(authname, au->authname->content))
234 return au;
235
236 return NULL;
237}
238
239unsigned long noperserv_get_autheduser_count(void) {
240 return loadedusers;
241}
242
243unsigned long noperserv_next_autheduser_id(void) {
244 return ++lastuserid;
245}
246
247void noperserv_add_to_autheduser(nick *np, no_autheduser *au) {
248 no_nicklist *nl = (no_nicklist *)malloc(sizeof(no_nicklist));
249 if(!nl)
250 return;
251
252 np->exts[noperserv_ext] = au;
253
254 nl->nick = np;
255
256 nl->next = au->nick;
257 au->nick = nl;
258}
259
260void nopserserv_delete_from_autheduser(nick *np, no_autheduser *au) {
261 no_nicklist *cp = au->nick, *lp = NULL;
262
263 for(;cp;lp=cp,cp=cp->next)
264 if(cp->nick == np) {
265 if(lp) {
266 lp->next = cp->next;
267 } else {
268 au->nick = cp->next;
269 }
270 free(cp);
271 break;
272 }
273}