]> jfr.im git - irc/quakenet/newserv.git/blob - chanserv/database/chanservdb_hash.c
TRUSTS: require sqlite
[irc/quakenet/newserv.git] / chanserv / database / chanservdb_hash.c
1 /*
2 * chanservhash.c:
3 * Handles insertion and retrieval of various data structures
4 * from their respective hashes. Hopefully it's obvious from
5 * the name of each function what it does.
6 */
7
8 #include <string.h>
9 #include <strings.h>
10
11 #include "../chanserv.h"
12 #include "../../lib/irc_string.h"
13
14 reguser *regusernicktable[REGUSERHASHSIZE];
15
16 maildomain *maildomainnametable[MAILDOMAINHASHSIZE];
17 maildomain *maildomainIDtable[MAILDOMAINHASHSIZE];
18
19 #define regusernickhash(x) ((irc_crc32i(x))%REGUSERHASHSIZE)
20 #define maildomainnamehash(x) ((irc_crc32i(x))%MAILDOMAINHASHSIZE)
21 #define maildomainIDhash(x) ((x)%MAILDOMAINHASHSIZE)
22
23 void chanservhashinit() {
24 memset(regusernicktable,0,REGUSERHASHSIZE*sizeof(reguser *));
25 memset(maildomainnametable,0,MAILDOMAINHASHSIZE*sizeof(maildomain *));
26 memset(maildomainIDtable,0,MAILDOMAINHASHSIZE*sizeof(maildomain *));
27 }
28
29 void addregusertohash(reguser *rup) {
30 unsigned int hash;
31 authname *anp;
32
33 hash=regusernickhash(rup->username);
34
35 rup->nextbyname=regusernicktable[hash];
36 regusernicktable[hash]=rup;
37
38 anp=findorcreateauthname(rup->ID, rup->username);
39 anp->exts[chanservaext]=rup;
40 }
41
42 reguser *findreguserbynick(const char *nick) {
43 unsigned int hashnick;
44 reguser *rup;
45
46 hashnick=regusernickhash(nick);
47 for (rup=regusernicktable[hashnick];rup;rup=rup->nextbyname) {
48 if (!ircd_strcmp(nick,rup->username)) {
49 return rup;
50 }
51 }
52
53 /* Not found */
54 return NULL;
55 }
56
57 reguser *findreguserbyID(unsigned int ID) {
58 authname *anp;
59
60 anp=findauthname(ID);
61 if (anp)
62 return (reguser *)anp->exts[chanservaext];
63 else
64 return NULL;
65 }
66
67 /*
68 * findreguserbyemail()
69 */
70 reguser *findreguserbyemail(const char *email) {
71 int i;
72 reguser *rup;
73
74 for (i=0;i<REGUSERHASHSIZE;i++) {
75 for (rup=regusernicktable[i];rup;rup=rup->nextbyname) {
76 if (rup->email && !strcasecmp(email,rup->email->content)) {
77 return rup;
78 }
79 }
80 }
81 /* Not found */
82 return NULL;
83 }
84
85 void removereguserfromhash(reguser *rup) {
86 unsigned int hash;
87 reguser **ruh;
88 authname *anp;
89
90 int found;
91
92 hash=regusernickhash(rup->username);
93
94 found=0;
95 for (ruh=&(regusernicktable[hash]);*ruh;ruh=&((*ruh)->nextbyname)) {
96 if (*ruh==rup) {
97 *ruh=(rup->nextbyname);
98 found=1;
99 break;
100 }
101 }
102
103 if (found==0) {
104 Error("chanserv",ERR_ERROR,"Unable to remove reguser %s from nickhash",
105 rup->username);
106 }
107
108 anp=findauthname(rup->ID);
109
110 if (anp) {
111 anp->exts[chanservaext]=NULL;
112 releaseauthname(anp);
113 } else {
114 Error("chanserv",ERR_ERROR,"Unable to remove reguser %s from ID hash",rup->username);
115 }
116 }
117
118 void addregusertochannel(regchanuser *rcup) {
119 rcup->nextbyuser=(rcup->user->knownon);
120 rcup->nextbychan=(rcup->chan->regusers[(rcup->user->ID)%REGCHANUSERHASHSIZE]);
121
122 rcup->user->knownon=rcup;
123 rcup->chan->regusers[(rcup->user->ID)%REGCHANUSERHASHSIZE]=rcup;
124 }
125
126 regchanuser *findreguseronchannel(regchan *rcp, reguser *rup) {
127 regchanuser *rcup;
128
129 for (rcup=rcp->regusers[(rup->ID)%REGCHANUSERHASHSIZE];rcup;rcup=rcup->nextbychan) {
130 if (rcup->user==rup) {
131 return rcup;
132 }
133 }
134
135 /* Not found */
136 return NULL;
137 }
138
139 void delreguserfromchannel(regchan *rcp, reguser *rup) {
140 regchanuser **rcuh;
141 int found=0;
142
143 for (rcuh=&(rcp->regusers[(rup->ID)%REGCHANUSERHASHSIZE]);*rcuh;
144 rcuh=&((*rcuh)->nextbychan)) {
145 if ((*rcuh)->user==rup) {
146 /* Found the user */
147 freesstring((*rcuh)->info);
148 (*rcuh)->info=NULL;
149 *rcuh=(*rcuh)->nextbychan;
150 found=1;
151 break;
152 }
153 }
154
155 if (found==0) {
156 Error("chanserv",ERR_ERROR,"Unable to remove user %s from channel %s",
157 rup->username,rcp->index->name->content);
158 return;
159 }
160
161 for (rcuh=&(rup->knownon);*rcuh;rcuh=&((*rcuh)->nextbyuser)) {
162 if ((*rcuh)->chan==rcp) {
163 /* Found the channel */
164 *rcuh=(*rcuh)->nextbyuser;
165 return;
166 }
167 }
168
169 Error("chanserv",ERR_ERROR,"Unable to remove channel %s from user %s",
170 rcp->index->name->content,rup->username);
171 }
172
173 void addmaildomaintohash(maildomain *mdp) {
174 unsigned int hash;
175
176 hash=maildomainnamehash(mdp->name->content);
177
178 mdp->nextbyname=maildomainnametable[hash];
179 maildomainnametable[hash]=mdp;
180
181 hash=maildomainIDhash(mdp->ID);
182
183 mdp->nextbyID=maildomainIDtable[hash];
184 maildomainIDtable[hash]=mdp;
185 }
186
187 maildomain *findmaildomainbyID(unsigned int ID) {
188 unsigned int hash;
189 maildomain *mdp;
190
191 hash=maildomainIDhash(ID);
192 for (mdp=maildomainIDtable[hash]; mdp; mdp=mdp->nextbyID)
193 if (mdp->ID==ID)
194 return mdp;
195
196 return NULL;
197 }
198
199 maildomain *findmaildomainbydomain(char *domain) {
200 unsigned int hash;
201 maildomain *mdp;
202
203 hash=maildomainnamehash(domain);
204 for (mdp=maildomainnametable[hash]; mdp; mdp=mdp->nextbyname)
205 if (!strcasecmp(mdp->name->content, domain))
206 return mdp;
207
208 return NULL;
209 }
210
211 maildomain *findnearestmaildomain(char *domain) {
212 maildomain *m = findmaildomainbydomain(domain);
213 char *p;
214
215 if(!m && (p=strchr(domain, '.')))
216 return findnearestmaildomain(++p);
217
218 return m;
219 }
220
221 maildomain *findmaildomainbyemail(char *email) {
222 char *domain;
223
224 if (!(domain=strchr(email, '@')))
225 domain=email;
226 else
227 domain++;
228
229 return findmaildomainbydomain(domain);
230 }
231
232 maildomain *findorcreatemaildomain(char *email) {
233 unsigned int hash;
234 char *domain,*pdomain;
235 maildomain *mdp;
236
237 if (!(domain=strchr(email, '@')))
238 domain=email;
239 else
240 domain++;
241
242 if( domain[0] == '.' )
243 domain++;
244
245 hash=maildomainnamehash(domain);
246 for (mdp=maildomainnametable[hash]; mdp; mdp=mdp->nextbyname)
247 if (!strcasecmp(mdp->name->content, domain))
248 return mdp;
249
250 mdp=getmaildomain();
251 mdp->ID=0;
252 mdp->name=getsstring(domain, EMAILLEN);
253 mdp->count=0;
254 mdp->limit=0;
255 mdp->actlimit=MD_DEFAULTACTLIMIT;
256 mdp->flags=MDFLAG_DEFAULT;
257 mdp->users=NULL;
258 addmaildomaintohash(mdp);
259
260 pdomain=strchr(domain, '.');
261
262 if(pdomain) {
263 pdomain++;
264 mdp->parent = findorcreatemaildomain(pdomain);
265 } else {
266 mdp->parent = NULL;
267 }
268
269 return mdp;
270 }
271
272 void removemaildomainfromhash(maildomain *mdp) {
273 unsigned int hash;
274 maildomain **mdh;
275 int found;
276
277 hash=maildomainnamehash(mdp->name->content);
278
279 found=0;
280 for (mdh=&(maildomainnametable[hash]);*mdh;mdh=&((*mdh)->nextbyname)) {
281 if (*mdh==mdp) {
282 *mdh=(mdp->nextbyname);
283 found=1;
284 break;
285 }
286 }
287
288 if (found==0) {
289 Error("chanserv",ERR_ERROR,"Unable to remove maildomain %s from namehash",
290 mdp->name->content);
291 }
292
293 hash=maildomainIDhash(mdp->ID);
294 found=0;
295
296 for (mdh=&(maildomainIDtable[hash]);*mdh;mdh=&((*mdh)->nextbyID)) {
297 if (*mdh==mdp) {
298 *mdh=(mdp->nextbyID);
299 found=1;
300 break;
301 }
302 }
303
304 if (found==0) {
305 Error("chanserv",ERR_ERROR,"Unable to remove maildomain %s from ID hash",mdp->name->content);
306 }
307 }
308
309 void addregusertomaildomain(reguser *rup, maildomain *mdp) {
310 maildomain *smdp;
311 rup->nextbydomain=mdp->users;
312 mdp->users=rup;
313 for(smdp=mdp;smdp;smdp=smdp->parent) {
314 smdp->count++;
315 }
316 }
317
318 void delreguserfrommaildomain(reguser *rup, maildomain *mdp) {
319 maildomain *smdp, *nmdp;
320 reguser *ruh, *pruh=NULL;
321 int found=0;
322
323 if(!mdp)
324 return;
325
326 for (ruh=mdp->users; ruh; ruh=ruh->nextbydomain) {
327 if (ruh==rup) {
328 /* Found the user */
329 if (pruh)
330 pruh->nextbydomain=ruh->nextbydomain;
331 else
332 mdp->users=ruh->nextbydomain;
333 found=1;
334 break;
335 }
336 pruh=ruh;
337 }
338
339 if (found==0) {
340 Error("chanserv",ERR_ERROR,"Unable to remove user %s from maildomain %s",
341 rup->username, mdp->name->content);
342 return;
343 }
344
345 /* Free it from all the parent domains, cleaning up as we go.. */
346 for(smdp=mdp;smdp;smdp=nmdp) {
347 nmdp=smdp->parent;
348
349 /* Keep it if there are users left or we're remembering something about it. */
350 if (--smdp->count || (smdp->flags != MDFLAG_DEFAULT) || (smdp->actlimit != MD_DEFAULTACTLIMIT))
351 continue;
352
353 removemaildomainfromhash(smdp);
354 freesstring(smdp->name);
355 freemaildomain(smdp);
356 }
357
358 rup->domain=NULL;
359 freesstring(rup->localpart);
360 rup->localpart=NULL;
361 }
362