]> jfr.im git - irc/quakenet/newserv.git/blob - noperserv/noperserv_db.c
Add jupe support
[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 #include "../pqsql/pqsql.h"
15
16 #include "noperserv.h"
17 #include "noperserv_db.h"
18
19 #include <libpq-fe.h>
20 #include <stdlib.h>
21
22 int db_loaded = 0;
23 unsigned long loadedusers = 0;
24
25 unsigned long lastuserid;
26
27 no_autheduser *authedusers = NULL;
28
29 void noperserv_create_tables(void);
30
31 void noperserv_free_user(no_autheduser *au);
32 void noperserv_load_users(PGconn *dbconn, void *arg);
33
34 void noperserv_check_nick(nick *np);
35 void noperserv_nick_account(int hooknum, void *arg);
36 void noperserv_quit_account(int hooknum, void *arg);
37
38 void nopserserv_delete_from_autheduser(nick *np, no_autheduser *au);
39
40 int noperserv_load_db(void) {
41 if(!pqconnected())
42 return 0;
43
44 if(db_loaded)
45 noperserv_cleanup_db();
46
47 db_loaded = 1;
48
49 authedusers = NULL;
50
51 noperserv_create_tables();
52
53 pqasyncquery(noperserv_load_users, NULL,
54 "SELECT ID, authname, flags, noticelevel FROM noperserv.users");
55
56 return 1;
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 pqcreatequery("CREATE SCHEMA noperserv");
100 pqcreatequery(
101 "CREATE TABLE noperserv.users ("
102 "ID INT NOT NULL,"
103 "authname VARCHAR(%d) NOT NULL,"
104 "flags INT NOT NULL,"
105 "noticelevel INT NOT NULL,"
106 "PRIMARY KEY (ID))", ACCOUNTLEN);
107 }
108
109 void noperserv_cleanup_db(void) {
110 no_autheduser *ap, *np;
111
112 deregisterhook(HOOK_NICK_LOSTNICK, &noperserv_quit_account);
113 deregisterhook(HOOK_NICK_NEWNICK, &noperserv_nick_account);
114 deregisterhook(HOOK_NICK_ACCOUNT, &noperserv_nick_account);
115
116 ap = authedusers;
117 while(ap) {
118 np = ap->next;
119 noperserv_free_user(ap);
120 ap = np;
121 }
122 }
123
124 no_autheduser *noperserv_new_autheduser(char *authname) {
125 no_autheduser *au = (no_autheduser *)malloc(sizeof(no_autheduser));
126 if(!au)
127 return NULL;
128
129 au->authname = getsstring(authname, ACCOUNTLEN);
130 if(!au->authname) {
131 free(au);
132 return NULL;
133 }
134
135 loadedusers++;
136 au->newuser = 1;
137 au->nick = NULL;
138
139 au->next = authedusers;
140 authedusers = au;
141
142 return au;
143 }
144
145 void noperserv_delete_autheduser(no_autheduser *au) {
146 no_autheduser *ap = authedusers, *lp = NULL;
147
148 if(!au->newuser)
149 pqquery("DELETE FROM noperserv.users WHERE id = %d", au->id);
150
151 for(;ap;lp=ap,ap=ap->next) {
152 if(ap == au) {
153 if(lp) {
154 lp->next = ap->next;
155 } else {
156 authedusers = ap->next;
157 }
158 noperserv_free_user(ap);
159 return;
160 }
161 }
162 }
163
164 void noperserv_update_autheduser(no_autheduser *au) {
165 if(au->newuser) {
166 char escapedauthname[ACCOUNTLEN * 2 + 1];
167 PQescapeString(escapedauthname, au->authname->content, au->authname->length);
168 pqquery("INSERT INTO noperserv.users (id, authname, flags, noticelevel) VALUES (%lu,'%s',%u,%u)", au->id, au->authname->content, NOGetAuthLevel(au), NOGetNoticeLevel(au));
169 au->newuser = 0;
170 } else {
171 pqquery("UPDATE noperserv.users SET flags = %u, noticelevel = %u WHERE id = %lu", NOGetAuthLevel(au), NOGetNoticeLevel(au), au->id);
172 }
173 }
174
175 void noperserv_free_user(no_autheduser *au) {
176 no_nicklist *cp = au->nick, *np;
177
178 while(cp) {
179 cp->nick->exts[noperserv_ext] = NULL;
180 np = cp->next;
181 free(cp);
182 cp = np;
183 }
184
185 freesstring(au->authname);
186 free(au);
187
188 loadedusers--;
189 }
190
191 void noperserv_check_nick(nick *np) {
192 no_autheduser *au = noperserv_get_autheduser(np->authname);
193 if(au)
194 noperserv_add_to_autheduser(np, au);
195 }
196
197 void noperserv_nick_account(int hooknum, void *arg) {
198 noperserv_check_nick((nick *)arg);
199 }
200
201 void noperserv_quit_account(int hooknum, void *arg) {
202 nick *np = (void *)arg;
203 no_autheduser *au = NOGetAuthedUser(np);
204 no_nicklist *nl, *ln = NULL;
205 if(!au)
206 return;
207
208 for(nl=au->nick;nl;ln=nl,nl=nl->next)
209 if(nl->nick == np) {
210 if(ln) {
211 ln->next = nl->next;
212 } else {
213 au->nick = nl->next;
214 }
215 free(nl);
216 break;
217 }
218 }
219
220 no_autheduser *noperserv_get_autheduser(char *authname) {
221 no_autheduser *au = authedusers;
222
223 for(;au;au=au->next)
224 if(!ircd_strcmp(authname, au->authname->content))
225 return au;
226
227 return NULL;
228 }
229
230 unsigned long noperserv_get_autheduser_count(void) {
231 return loadedusers;
232 }
233
234 unsigned long noperserv_next_autheduser_id(void) {
235 return ++lastuserid;
236 }
237
238 void noperserv_add_to_autheduser(nick *np, no_autheduser *au) {
239 no_nicklist *nl = (no_nicklist *)malloc(sizeof(no_nicklist));
240 if(!nl)
241 return;
242
243 np->exts[noperserv_ext] = au;
244
245 nl->nick = np;
246
247 nl->next = au->nick;
248 au->nick = nl;
249 }
250
251 void nopserserv_delete_from_autheduser(nick *np, no_autheduser *au) {
252 no_nicklist *cp = au->nick, *lp = NULL;
253
254 for(;cp;lp=cp,cp=cp->next)
255 if(cp->nick == np) {
256 if(lp) {
257 lp->next = cp->next;
258 } else {
259 au->nick = cp->next;
260 }
261 free(cp);
262 break;
263 }
264 }