]> jfr.im git - irc/quakenet/newserv.git/blob - noperserv/noperserv_db.c
Began manual merge.
[irc/quakenet/newserv.git] / noperserv / noperserv_db.c
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"
14
15 #include "noperserv.h"
16 #include "noperserv_psql.h"
17 #include "noperserv_db.h"
18
19 #include <libpq-fe.h>
20 #include <stdlib.h>
21
22 int dontclose = 0;
23 int odb_connected = 0; /* seperate from the db one */
24 unsigned long loadedusers = 0;
25
26 unsigned long lastuserid;
27
28 no_autheduser *authedusers = NULL;
29
30 void noperserv_free_user(no_autheduser *au);
31 void noperserv_load_users(PGconn *dbconn, void *arg);
32
33 void noperserv_check_nick(nick *np);
34 void noperserv_nick_account(int hooknum, void *arg);
35 void noperserv_quit_account(int hooknum, void *arg);
36
37 void nopserserv_delete_from_autheduser(nick *np, no_autheduser *au);
38 void noperserv_create_tables(void);
39
40 void noperserv_load_db(void) {
41 if(odb_connected) {
42 dontclose = 1;
43 noperserv_cleanup_db();
44 } else {
45 if(noperserv_connect_db(&noperserv_create_tables)) {
46 Error("noperserv", ERR_ERROR, "Unable to connect to database!");
47 return;
48 }
49
50 odb_connected = 1;
51 }
52
53 authedusers = NULL;
54
55 noperserv_async_query(noperserv_load_users, NULL,
56 "SELECT ID, authname, flags, noticelevel FROM users");
57 }
58
59 void noperserv_load_users(PGconn *dbconn, void *arg) {
60 PGresult *pgres = PQgetResult(dbconn);
61 int rows, i;
62 no_autheduser *nu;
63 nick *np;
64
65 if(PQresultStatus(pgres) != PGRES_TUPLES_OK) {
66 Error("noperserv", ERR_ERROR, "Error loading user list.");
67 return;
68 }
69
70 rows = PQntuples(pgres);
71 lastuserid = 0;
72
73 for(i=0;i<rows;i++) {
74 nu = noperserv_new_autheduser(PQgetvalue(pgres, i, 1));
75 if(!nu)
76 continue;
77
78 nu->id = strtoul(PQgetvalue(pgres, i, 0), NULL, 10);
79 nu->authlevel = strtoul(PQgetvalue(pgres, i, 2), NULL, 10);
80 nu->noticelevel = strtoul(PQgetvalue(pgres, i, 3), NULL, 10);
81 nu->newuser = 0;
82 if(nu->id > lastuserid)
83 lastuserid = nu->id;
84 }
85
86 Error("noperserv", ERR_INFO, "Loaded %d users", loadedusers);
87
88 for(i=0;i<NICKHASHSIZE;i++)
89 for(np=nicktable[i];np;np=np->next)
90 if(IsAccount(np))
91 noperserv_check_nick(np);
92
93 registerhook(HOOK_NICK_ACCOUNT, &noperserv_nick_account);
94 registerhook(HOOK_NICK_NEWNICK, &noperserv_nick_account);
95 registerhook(HOOK_NICK_LOSTNICK, &noperserv_quit_account);
96 }
97
98 void noperserv_create_tables(void) {
99 noperserv_sync_query(
100 "CREATE TABLE users ("
101 "ID INT NOT NULL,"
102 "authname VARCHAR(%d) NOT NULL,"
103 "flags INT NOT NULL,"
104 "noticelevel INT NOT NULL,"
105 "PRIMARY KEY (ID))", ACCOUNTLEN);
106 }
107
108 void noperserv_cleanup_db(void) {
109 no_autheduser *ap, *np;
110
111 deregisterhook(HOOK_NICK_LOSTNICK, &noperserv_quit_account);
112 deregisterhook(HOOK_NICK_NEWNICK, &noperserv_nick_account);
113 deregisterhook(HOOK_NICK_ACCOUNT, &noperserv_nick_account);
114
115 ap = authedusers;
116 while(ap) {
117 np = ap->next;
118 noperserv_free_user(ap);
119 ap = np;
120 }
121
122 /* other stuff */
123 if(!dontclose && odb_connected)
124 noperserv_disconnect_db();
125
126 dontclose = 0;
127 }
128
129 no_autheduser *noperserv_new_autheduser(char *authname) {
130 no_autheduser *au = (no_autheduser *)malloc(sizeof(no_autheduser));
131 if(!au)
132 return NULL;
133
134 au->authname = getsstring(authname, ACCOUNTLEN);
135 if(!au->authname) {
136 free(au);
137 return NULL;
138 }
139
140 loadedusers++;
141 au->newuser = 1;
142 au->nick = NULL;
143
144 au->next = authedusers;
145 authedusers = au;
146
147 return au;
148 }
149
150 void noperserv_delete_autheduser(no_autheduser *au) {
151 no_autheduser *ap = authedusers, *lp = NULL;
152
153 if(!au->newuser)
154 noperserv_query("DELETE FROM users WHERE id = %d", au->id);
155
156 for(;ap;lp=ap,ap=ap->next) {
157 if(ap == au) {
158 if(lp) {
159 lp->next = ap->next;
160 } else {
161 authedusers = ap->next;
162 }
163 noperserv_free_user(ap);
164 return;
165 }
166 }
167 }
168
169 void noperserv_update_autheduser(no_autheduser *au) {
170 if(au->newuser) {
171 char escapedauthname[ACCOUNTLEN * 2 + 1];
172 PQescapeString(escapedauthname, au->authname->content, au->authname->length);
173 noperserv_query("INSERT INTO users (id, authname, flags, noticelevel) VALUES (%lu,'%s',%lu,%lu)", au->id, au->authname->content, NOGetAuthLevel(au), NOGetNoticeLevel(au));
174 au->newuser = 0;
175 } else {
176 noperserv_query("UPDATE users SET flags = %lu, noticelevel = %lu WHERE id = %lu", NOGetAuthLevel(au), NOGetNoticeLevel(au), au->id);
177 }
178 }
179
180 void noperserv_free_user(no_autheduser *au) {
181 no_nicklist *cp = au->nick, *np;
182
183 while(cp) {
184 cp->nick->exts[noperserv_ext] = NULL;
185 np = cp->next;
186 free(cp);
187 cp = np;
188 }
189
190 freesstring(au->authname);
191 free(au);
192
193 loadedusers--;
194 }
195
196 void noperserv_check_nick(nick *np) {
197 no_autheduser *au = noperserv_get_autheduser(np->authname);
198 if(au)
199 noperserv_add_to_autheduser(np, au);
200 }
201
202 void noperserv_nick_account(int hooknum, void *arg) {
203 noperserv_check_nick((nick *)arg);
204 }
205
206 void noperserv_quit_account(int hooknum, void *arg) {
207 nick *np = (void *)arg;
208 no_autheduser *au = NOGetAuthedUser(np);
209 no_nicklist *nl, *ln = NULL;
210 if(!au)
211 return;
212
213 for(nl=au->nick;nl;ln=nl,nl=nl->next)
214 if(nl->nick == np) {
215 if(ln) {
216 ln->next = nl->next;
217 } else {
218 au->nick = nl->next;
219 }
220 free(nl);
221 break;
222 }
223 }
224
225 no_autheduser *noperserv_get_autheduser(char *authname) {
226 no_autheduser *au = authedusers;
227
228 for(;au;au=au->next)
229 if(!ircd_strcmp(authname, au->authname->content))
230 return au;
231
232 return NULL;
233 }
234
235 unsigned long noperserv_get_autheduser_count(void) {
236 return loadedusers;
237 }
238
239 unsigned long noperserv_next_autheduser_id(void) {
240 return ++lastuserid;
241 }
242
243 void noperserv_add_to_autheduser(nick *np, no_autheduser *au) {
244 no_nicklist *nl = (no_nicklist *)malloc(sizeof(no_nicklist));
245 if(!nl)
246 return;
247
248 np->exts[noperserv_ext] = au;
249
250 nl->nick = np;
251
252 nl->next = au->nick;
253 au->nick = nl;
254 }
255
256 void nopserserv_delete_from_autheduser(nick *np, no_autheduser *au) {
257 no_nicklist *cp = au->nick, *lp = NULL;
258
259 for(;cp;lp=cp,cp=cp->next)
260 if(cp->nick == np) {
261 if(lp) {
262 lp->next = cp->next;
263 } else {
264 au->nick = cp->next;
265 }
266 free(cp);
267 break;
268 }
269 }