]> jfr.im git - irc/quakenet/newserv.git/blame - request/sqrequest.c
r506@blue (orig r448): services.no | 2006-03-11 15:41:22 +0000
[irc/quakenet/newserv.git] / request / sqrequest.c
CommitLineData
25b7d0fa
P
1/*
2 * S and Q request system!
3 *
4 * Depends on "chanstats" and "chanfix"
5 */
6
bdd430cb 7#include <stdio.h>
25b7d0fa
P
8#include "request.h"
9#include "sqrequest.h"
10#include "request_block.h"
11#include "../chanfix/chanfix.h"
12#include "../chanstats/chanstats.h"
13#include "../localuser/localuser.h"
14#include "../lib/irc_string.h"
15#include "../core/schedule.h"
16
17#include <stdarg.h>
18#include <stdio.h>
19#include <string.h>
20
21#define QRLstate_IDLE 0x0 /* No request active */
22#define QRLstate_AWAITINGCHAN 0x1 /* Awaiting "Users for channel.." */
23#define QRLstate_AWAITINGUSER 0x2 /* Looking for our user in the list */
24#define QRLstate_AWAITINGEND 0x3 /* Waiting for "End of chanlev" */
25
26#define QR_FAILED 0x0
27#define QR_OK 0x1
28
29#define QR_CSERVE 0x0
30#define QR_SPAMSCAN 0x1
31
32#define QR_L 0x0
33#define QR_Q 0x1
34
35#define min(a,b) ((a > b) ? b : a)
36
37typedef struct requestrec {
38 unsigned int reqnumeric; /* Who made the request */
39 chanindex *cip; /* Which channel the request is for */
40 int what; /* Which service does the user want? */
41 int who; /* Who are we talking to about CHANLEV? */
42 struct requestrec *next;
43} requestrec;
44
45requestrec *nextreql, *lastreql;
46requestrec *nextreqq, *lastreqq;
47
48
49requestrec *nextqreq, *lastqreq;
50
51extern nick *rqnick;
52int rlstate;
53int rqstate;
54
55/* stats counters */
56int qr_suspended = 0;
57int qr_nohist = 0;
58int qr_toosmall = 0;
59int qr_nochanlev = 0;
60int qr_notowner = 0;
61
62/* Check whether the user is blocked */
63int qr_blockcheck(requestrec *req) {
64 nick *np;
65 rq_block *block;
66
67 np = getnickbynumeric(req->reqnumeric);
68
69 /* user is not online anymore */
70 if (np == NULL)
71 return 0;
72
73 block = rq_findblock(np->authname);
74
75 if (block != NULL)
76 return 1; /* user is blocked */
77 else
78 return 0;
79}
80
81/*
82 * Deal with outcome of a queued request. The request should be freed
83 * as part of the process.
84 */
85
86void qr_result(requestrec *req, int outcome, char *message, ...) {
87 sstring *user, *password;
88 requestrec **rh;
89 char msgbuf[512];
90 va_list va;
cbdd5aab 91 channel *cplog;
25b7d0fa 92 nick *lnp, *qnp, *np, *tnp, *snp;
bdd430cb
CP
93 char now[50];
94 time_t now_ts;
25b7d0fa
P
95
96 /* Delete the request from the list first.. */
97 for (rh=&nextreql;*rh;rh=&((*rh)->next)) {
98 if (*rh==req) {
99 *rh=req->next;
100 break;
101 }
102 }
103
104 for (rh=&nextreqq;*rh;rh=&((*rh)->next)) {
105 if (*rh==req) {
106 *rh=req->next;
107 break;
108 }
109 }
110
111 /* If this was the last request (unlikely),
112 * we need to fix the last pointer */
113 if (lastreql==req) {
114 if (nextreql)
115 for (lastreql=nextreql;lastreql->next;lastreql=lastreql->next)
116 ; /* empty loop */
117 else
118 lastreql=NULL;
119 }
120
121 if (lastreqq==req) {
122 if (nextreqq)
123 for (lastreqq=nextreqq;lastreqq->next;lastreqq=lastreqq->next)
124 ; /* empty loop */
125 else
126 lastreqq=NULL;
127 }
128
129 /* Check that the nick is still here. If not, drop the request. */
130 if (!(tnp=np=getnickbynumeric(req->reqnumeric))) {
131 free(req);
132 return;
133 }
134
bdd430cb
CP
135 if (rq_logfd != NULL) {
136 now[0] = '\0';
137 now_ts = time(NULL);
cbdd5aab 138
bdd430cb
CP
139 strftime(now, sizeof(now), "%c", localtime(&now_ts));
140 fprintf(rq_logfd, "%s: request (%s) for %s from %s: Request was %s.\n", now, (req->what == QR_CSERVE) ? RQ_QNICK : RQ_SNICK, req->cip->name->content, tnp->nick, (outcome == QR_OK) ? "accepted" : "denied");
141 fflush(rq_logfd);
cbdd5aab
P
142 }
143
25b7d0fa
P
144 if (outcome==QR_OK) {
145 if (req->what == QR_CSERVE) {
146 /* Delete L, add Q. Check that they both exist first, though. */
147
148 if (!(lnp=getnickbynick(RQ_LNICK)) || !(qnp=getnickbynick(RQ_QNICK))) {
149 sendnoticetouser(rqnick, tnp,
150 "Error: Cannot find %s and %s on the network. "
151 "Please request again later.", RQ_LNICK, RQ_QNICK);
152 free(req);
153 return;
154 }
155
156 /* /msg Q ADDCHAN <channel> <flags> <owners nick> <channeltype> */
157 sendmessagetouser(rqnick, qnp, "ADDCHAN %s +ap #%s upgrade",
158 req->cip->name->content,
159 np->authname);
160
161 sendnoticetouser(rqnick, tnp, "Adding %s to channel, please wait...",
162 RQ_QNICK);
163 } else if (req->what == QR_SPAMSCAN) {
164 /* Add S */
165
166 if (!(snp=getnickbynick(RQ_SNICK))) {
167 sendnoticetouser(rqnick, tnp,
168 "Error: Cannot find %s on the network. "
169 "Please request again later.", RQ_SNICK);
170
171 free(req);
172 return;
173 }
174
175 sendnoticetouser(rqnick, tnp, "Requirements met, %s should be added. "
176 "Contact #help should further assistance be required.",
177 RQ_SNICK);
178
179 /* auth */
bdd430cb
CP
180 user = (sstring *)getcopyconfigitem("request", "user", "R", 30);
181 password = (sstring *)getcopyconfigitem("request", "password", "bla", 30);
25b7d0fa
P
182 sendmessagetouser(rqnick, snp, "AUTH %s %s", user->content, password->content);
183 freesstring(user);
184 freesstring(password);
185
186 /* /msg S addchan <channel> default */
bdd430cb 187 sendmessagetouser(rqnick, snp, "ADDCHAN %s default +op", req->cip->name->content);
25b7d0fa
P
188
189 /* we do not put the request into another queue, so free it here */
190 free(req);
191
192 return;
193 }
194
195 if (lastqreq)
196 lastqreq->next=req;
197 else
198 lastqreq=nextqreq=req;
199
200 req->next=NULL;
201
202 rq_success++;
203
204 /* Don't free, it's in new queue now */
205 } else {
206 /* Sort out the message.. */
207 va_start(va, message);
208 vsnprintf(msgbuf,511,message,va);
209 va_end(va);
210
211 sendnoticetouser(rqnick, tnp, "%s", msgbuf);
212 /* This is a failure message. Add disclaimer. */
213 /*sendnoticetouser(rqnick, tnp, "Do not complain about this result in #help or #feds.");*/
214 free(req);
215
216 rq_failed++;
217 }
218}
219
220/*
221 * qr_checksize:
222 * Checks that a channel is beeeeg enough for teh Q
223 */
224
225int qr_checksize(chanindex *cip, int what) {
226 chanstats *csp;
227 channel *cp;
228 nick *np;
229 int i , avg, tot=0, authedcount=0, count=0;
230
231 cp = cip->channel;
232
233 if (cp == NULL)
234 return 0; /* this shouldn't ever happen */
235
236#if QR_DEBUG
237 return 1;
238#endif
239
240 /* make sure that there are enough authed users */
241 for (i=0;i<cp->users->hashsize;i++) {
242 if (cp->users->content[i] != nouser) {
243 np = getnickbynumeric(cp->users->content[i]);
244
245 if (IsAccount(np))
246 authedcount++;
247
248 count++;
249 }
250 }
251
bdd430cb 252 if (authedcount * 100 / count < ((what == QR_CSERVE) ? QR_AUTHEDPCT_CSERVE : QR_AUTHEDPCT_SPAMSCAN))
25b7d0fa
P
253 return 0; /* too few authed users */
254
255 if (!(csp=cip->exts[csext]))
256 return 0;
257
258 for (i=0;i<HISTORYDAYS;i++) {
259 tot += csp->lastdays[i];
260 }
261
262 avg = (what == QR_CSERVE) ? QR_REQUIREDSIZE_CSERVE : QR_REQUIREDSIZE_SPAMSCAN;
263
264 if (tot > (avg * 140))
265 return 1;
266
267 return 0;
268}
269
270/* This function deals with notices from L: basically we track the
271 * responses to the L chanlev requests we've been making until we can
272 * decide what to do with the requests.
273 *
274 * Here's the L chanlev format:
275 * 11:12 -L(TheLBot@lightweight.quakenet.org)- Users for channel #twilightzone
276 * 11:12 -L(TheLBot@lightweight.quakenet.org)- Authname Access flags
277 * 11:12 -L(TheLBot@lightweight.quakenet.org)- -----------------------------
278 * 11:12 -L(TheLBot@lightweight.quakenet.org)- Bigfoot amno
279 * 11:12 -L(TheLBot@lightweight.quakenet.org)- End of chanlev for #twilightzone.
280 */
281
282void qr_handlenotice(nick *sender, char *message) {
283 char *ch, *chop;
284 chanindex *cip;
285 requestrec *rrp1, *rrp2;
286 nick *np;
287 int delrequest = 0, state, who;
288 requestrec *nextreq;
289 channel *logcp;
290
291/* logcp = findchannel("#qnet.request");
292
293 if (logcp)
294 sendmessagetochannel(rqnick, logcp, "%s: %s - %d %d %x %x", sender->nick, message, rlstate, rqstate, nextreql, nextreqq);
295*/
296 if (!ircd_strcmp(sender->nick, RQ_QNICK) && nextqreq) {
297 /* Message from Q */
298 if (!ircd_strcmp(message,"Done.")) {
299 /* Q added the channel: delete from L and tell the user. */
300 /* If L has conspired to vanish between the request and the outcome,
301 * we have a chan with Q and L... too bad. */
302
303 if ((np=getnickbynick(RQ_LNICK))) {
304 sendmessagetouser(rqnick, np, "SENDCHANLEV %s %s",
305 nextqreq->cip->name->content, RQ_QNICK);
306
307 sendmessagetouser(rqnick, np, "DELCHAN %s",
308 nextqreq->cip->name->content);
309 }
310
311 if ((np=getnickbynumeric(nextqreq->reqnumeric))) {
312 sendnoticetouser(rqnick, np, "Request completed. %s added.", RQ_QNICK);
313 }
314
315 delrequest = 1;
316 } else if (!ircd_strcmp(message,"That channel already exists.")) {
317 if ((np=getnickbynumeric(nextqreq->reqnumeric))) {
318 sendnoticetouser(rqnick, np,
319 "Your channel appears to have %s already "
320 "(it may be suspended).", RQ_QNICK);
321
322 qr_suspended++;
323
324 delrequest = 1;
325 }
326 }
327
328 /* For either of the two messages above we want to delete the request
329 * at the head of the queue. */
330 if (delrequest) {
331 rrp1=nextqreq;
332
333 nextqreq=nextqreq->next;
334 if (!nextqreq)
335 lastqreq=NULL;
336
337 free(rrp1);
338 }
339 }
340
341 if (!ircd_strcmp(sender->nick, RQ_LNICK) || !ircd_strcmp(sender->nick, RQ_QNICK)) {
342 who = !ircd_strcmp(sender->nick, RQ_LNICK) ? QR_L : QR_Q;
343 state = (who == QR_Q) ? rqstate : rlstate;
344 nextreq = (who == QR_Q) ? nextreqq : nextreql;
345
346 /* Message from L or Q */
347 switch (state) {
348 case QRLstate_IDLE:
349 /* We're idle, do nothing */
350 return;
351
352 case QRLstate_AWAITINGCHAN:
353 /* We're waiting for conformation of the channel name */
354 if ((!ircd_strncmp(message,"Users for",9) && who == QR_L) ||
355 (!ircd_strncmp(message,"Known users on",14) && who == QR_Q)
356 ) {
357 /* Looks like the right message. Let's find a channel name */
358
359 for (ch=message;*ch;ch++)
360 if (*ch=='#')
361 break;
362
363 if (!*ch) {
364 Error("qrequest",ERR_WARNING,
365 "Unable to parse channel name from L/Q message: %s",message);
366 return;
367 }
368
369 /* chop off any remaining words */
370 chop = ch;
371 while (*(chop++)) {
372 if (*chop == ' ') {
373 *chop = '\0';
374 break;
375 }
376 }
377
378 if (!(cip=findchanindex(ch))) {
379 Error("qrequest",ERR_WARNING,
380 "Unable to find channel from L/Q message: %s",ch);
381 return;
382 }
383
384 if (cip==nextreq->cip) {
385 /* Ok, this is the correct channel, everything is proceeding
386 * exactly as I had forseen */
387 if (who == QR_L)
388 rlstate = QRLstate_AWAITINGUSER;
389 else
390 rqstate = QRLstate_AWAITINGUSER;
391
392 return;
393 } else {
394 /* Uh-oh, not the channel we wanted. Something is fucked
395 * here. I think the only possible way out of this mess is
396 * to skip through in case we find a match for a later channel..
397 */
398 for (rrp1=nextreq;rrp1;rrp1=rrp1->next)
399 if (rrp1->cip==cip)
400 break;
401
402 if (rrp1) {
403 /* OK, we found a match further down the chain. This means
404 * that something bad has happened to every request between
405 * the head of the list and the one we just found - send
406 * error responses.
407 *
408 * Note weird loop head: qr_result will free up requests from
409 * the list as it goes, so we can just keep picking off the first
410 * entry
411 */
f3c45977 412 for(rrp2=nextreq;rrp2;) {
25b7d0fa
P
413 if (rrp2==rrp1)
414 break;
415
416 Error("qrequest",ERR_WARNING,
417 "Lost response for channel %s; skipping.",
418 rrp2->cip->name->content);
419
420 qr_result(rrp2, QR_FAILED,
421 "Sorry, an error occurred while processing your request.");
f3c45977
P
422
423 rrp2 = nextreq = (who == QR_Q) ? nextreqq : nextreql;
25b7d0fa
P
424 }
425
426 if (rrp2) {
427 /* We seem to be back in sync. */
428 if (who == QR_L)
429 rlstate = QRLstate_AWAITINGUSER;
430 else
431 rqstate = QRLstate_AWAITINGUSER;
432
433 return;
434 }
435 /* Some form of hole in the space time continuum exists
436 * if we get here. Unclear how to proceed. */
437 return;
438 } else {
439 /* No match - let's just ignore this completely */
440 Error("qrequest",ERR_WARNING,
441 "Ignoring L/Q response for spurious channel %s",
442 cip->name->content);
443 return;
444 }
445 }
446 }
447 break;
448
449 case QRLstate_AWAITINGUSER:
450 if ((!ircd_strncmp(message, "End of chanlev",14) && who == QR_L) ||
451 (!ircd_strncmp(message, "End of list.",12) && who == QR_Q)) {
452 /* Oh dear, we got to the end of the chanlev in this state.
453 * This means that we didn't find the user.
454 */
455
456 qr_result(nextreq, QR_FAILED,
457 "Error: You are not known on %s.",
458 nextreq->cip->name->content);
459
460 /* need to reset nextreq .. just in case
461 * qr_result has cleaned up records */
462
463 nextreq = (who == QR_Q) ? nextreqq : nextreql;
464
465 if (nextreq) {
466 if (who == QR_L)
467 rlstate = QRLstate_AWAITINGUSER;
468 else
469 rqstate = QRLstate_AWAITINGUSER;
470 } else {
471 if (who == QR_L)
472 rlstate = QRLstate_IDLE;
473 else
474 rqstate = QRLstate_IDLE;
475 }
476
477 qr_nochanlev++;
478
479 return;
480 } else {
481 /* Brutalise the message :-) */
482
483 if (who == QR_Q) {
484 while (*message == ' ')
485 message++;
486 }
487
488 if (!(ch=strchr(message, ' ')))
489 return;
490
491 *ch++='\0';
492
493 if (!(np=getnickbynumeric(nextreq->reqnumeric)))
494 return;
495
496 if (ircd_strcmp(message, np->authname)) {
497 /* This is not the user you are looking for */
498 return;
499 }
500
501 /* Check for owner flag. Both branches of this if will
502 * take the request off the list, one way or the other. */
503 if (strchr(ch, 'n')) {
504 /* They iz teh +n! */
505
506 /* Note: We're checking for blocks kind of late, so the request
507 system gets a chance to send other error messages first (like
508 'no chanstats', 'not known on channel', etc.). This is required
509 so that the user doesn't notice that he's being blocked. */
510 if (qr_checksize(nextreq->cip, nextreq->what) && !qr_blockcheck(nextreq)) {
511 qr_result(nextreq, QR_OK, "OK");
512 } else {
513 if (nextreq->what == QR_CSERVE) {
514 qr_result(nextreq, QR_FAILED,
515 "Error: You do not meet the requirements "
516 "for %s. Please continue to use %s.", RQ_QNICK, RQ_LNICK);
517 } else {
518 qr_result(nextreq, QR_FAILED,
519 "Error: Your channel does not require %s. "
520 "Try again later.", RQ_SNICK);
521 }
522
523 qr_toosmall++;
524 }
525 } else {
526 qr_result(nextreq, QR_FAILED,
527 "Error: You don't hold the +n flag on %s.",
528 nextreq->cip->name->content);
529
530 qr_notowner++;
531 }
532
533 /* OK, we found what we wanted so make sure we skip the rest */
534 if (who == QR_L)
535 rlstate = QRLstate_AWAITINGEND;
536 else
537 rqstate = QRLstate_AWAITINGEND;
538
539 return;
540 }
541 break;
542
543 case QRLstate_AWAITINGEND:
544 if (!ircd_strncmp(message, "End of chanlev",14) ||
545 !ircd_strncmp(message, "End of list.",12)) {
546 /* Found end of list */
547
548 if (nextreq) {
549 if (who == QR_L)
550 rlstate = QRLstate_AWAITINGCHAN;
551 else
552 rqstate = QRLstate_AWAITINGCHAN;
553 } else {
554 if (who == QR_L)
555 rlstate = QRLstate_IDLE;
556 else
557 rqstate = QRLstate_IDLE;
558 }
559
560 return;
561 }
562 break;
563 }
564 }
565}
566
567/*
568 * This function deals with requests from users for Q.
569 * Some sanity checks are made and the request is
570 * added to the queue.
571 */
572
573int qr_requestq(nick *rqnick, nick *sender, channel *cp, nick *lnick, nick *qnick) {
574 chanindex *cip = cp->index;
575
576 /* Check:
577 * - we have some form of channel stats for the channel
578 *
579 * Note that the actual channel stats will not be checked
580 * until we're sure the user has +n on the channel.
581 */
582
583 if (rq_isspam(sender)) {
584 sendnoticetouser(rqnick, sender, "Error: Do not flood the request system."
585 " Try again in %s.", rq_longtoduration(rq_blocktime(sender)));
586
587 return RQ_ERROR;
588 }
589
590 if (!cip->exts[csext]) {
591 sendnoticetouser(rqnick, sender,
592 "Error: No historical record exists for %s.",
593 cip->name->content);
594
595 qr_nohist++;
596
597 return RQ_ERROR;
598 }
599
600 /* Request stats from L */
601 sendmessagetouser(rqnick, lnick, "CHANLEV %s", cip->name->content);
602
603 /* Sort out a request record */
604 if (lastreql) {
605 lastreql->next = (requestrec *)malloc(sizeof(requestrec));
606 lastreql=lastreql->next;
607 } else {
608 lastreql=nextreql=(requestrec *)malloc(sizeof(requestrec));
609 }
610
611 lastreql->next = NULL;
612 lastreql->cip = cip;
613 lastreql->what = QR_CSERVE;
614 lastreql->who = QR_L;
615 lastreql->reqnumeric = sender->numeric;
616
617 if (rlstate == QRLstate_IDLE)
618 rlstate = QRLstate_AWAITINGCHAN;
619
620 sendnoticetouser(rqnick, sender,
621 "Checking your %s access. "
622 "This may take a while, please be patient...", RQ_LNICK);
623
624 /* we don't know yet whether the request was successful */
625 return RQ_UNKNOWN;
626}
627
628int qr_instantrequestq(nick *sender, channel *cp) {
629 requestrec *fakerequest;
630 chanfix *cf;
631 regop *ro;
632 int rocount, i;
633 regop *rolist[QR_TOPX];
634
635 if (!qr_checksize(cp->index, QR_CSERVE))
636 return RQ_ERROR;
637
638 cf = cf_findchanfix(cp->index);
639
640 if (cf == NULL)
641 return RQ_ERROR;
642
643 rocount = cf_getsortedregops(cf, QR_TOPX, rolist);
644
645 ro = NULL;
646
647 for (i = 0; i < min(QR_TOPX, rocount); i++) {
648 if (cf_cmpregopnick(rolist[i], sender)) {
649 ro = rolist[i];
650 break;
651 }
652 }
653
654 /* not in top 5 - we don't have to worry about that error here
655 as the L request code will detect it again and send the user
656 an appropriate message */
657 if (ro == NULL)
658 return RQ_ERROR;
659
660 /* allocate a fake request */
661 fakerequest = (requestrec *)malloc(sizeof(requestrec));
662
663 fakerequest->reqnumeric = sender->numeric;
664 fakerequest->cip = cp->index;
665 fakerequest->what = QR_CSERVE;
666 fakerequest->who = QR_L; /* pretend that we asked L about the chanlev */
667
668 /* add it to the queue */
669 if (nextreql == NULL) {
670 fakerequest->next = NULL;
671 nextreql = fakerequest;
672 lastreql = fakerequest;
673 } else {
674 fakerequest->next = nextreql;
675 nextreql = fakerequest;
676 }
677
678 qr_result(fakerequest, QR_OK, "OK");
679
680 return RQ_OK;
681}
682
683int qr_requests(nick *rqnick, nick *sender, channel *cp, nick *lnick, nick *qnick) {
684 chanindex *cip = cp->index;
685 int who;
686 requestrec *nextreq, *lastreq;
687
688 if (rq_isspam(sender)) {
689 sendnoticetouser(rqnick, sender, "Error: Do not flood the request system."
690 " Try again in %s.", rq_longtoduration(rq_blocktime(sender)));
691
692 return RQ_ERROR;
693 }
694
695 /* check which service is on the channel */
696 if (getnumerichandlefromchanhash(cp->users, lnick->numeric) != NULL) {
697 /* we've found L */
698 who = QR_L;
699
700 /* Request stats from L */
701 sendmessagetouser(rqnick, lnick, "CHANLEV %s", cip->name->content);
702
703 if (rlstate == QRLstate_IDLE)
704 rlstate = QRLstate_AWAITINGCHAN;
705 } else if (getnumerichandlefromchanhash(cp->users, qnick->numeric) != NULL) {
706 /* we've found Q */
707 who = QR_Q;
708
709 /* Request stats from Q */
710 sendmessagetouser(rqnick, qnick, "CHANLEV %s", cip->name->content);
711
712 if (rqstate == QRLstate_IDLE)
713 rqstate = QRLstate_AWAITINGCHAN;
714 } /* 'else' cannot happen as R has already checked whether the user has L or Q */
715
716 lastreq = (who == QR_Q) ? lastreqq : lastreql;
717 nextreq = (who == QR_Q) ? nextreqq : nextreql;
718
719 /* Sort out a request record */
720 if (lastreq) {
721 lastreq->next = (requestrec *)malloc(sizeof(requestrec));
722 lastreq=lastreq->next;
723 } else {
724 lastreq=nextreq=(requestrec *)malloc(sizeof(requestrec));
725 }
726
727 lastreq->next = NULL;
728 lastreq->cip = cip;
729 lastreq->what = QR_SPAMSCAN;
730 lastreq->reqnumeric = sender->numeric;
731
732 if (who == QR_Q) {
733 nextreqq = nextreq;
734 lastreqq = lastreq;
735 } else {
736 nextreql = nextreq;
737 lastreql = lastreq;
738 }
739
740 sendnoticetouser(rqnick, sender,
741 "Checking your %s access. "
742 "This may take a while, please be patient...",
743 who == QR_Q ? RQ_QNICK : RQ_LNICK);
744
745 return RQ_UNKNOWN;
746}
747
748void qr_initrequest(void) {
749 nextreql=lastreql=NULL;
750 nextreqq=lastreqq=NULL;
751 nextqreq=lastqreq=NULL;
752}
753
754void qr_finirequest(void) {
755 struct requestrec *rp;
756
757 while (nextreqq) {
758 rp=nextreqq;
759 nextreqq=nextreqq->next;
760 free(rp);
761 }
762
763 while (nextreql) {
764 rp=nextreql;
765 nextreql=nextreql->next;
766 free(rp);
767 }
768
769 while (nextqreq) {
770 rp=nextqreq;
771 nextqreq=nextqreq->next;
772 free(rp);
773 }
774}
775
776void qr_requeststats(nick *rqnick, nick *np) {
777 sendnoticetouser(rqnick, np, "- Suspended (Q): %d", qr_suspended);
778 sendnoticetouser(rqnick, np, "- No chanstats (Q/S): %d", qr_nohist);
779 sendnoticetouser(rqnick, np, "- Too small (Q/S): %d", qr_toosmall);
780 sendnoticetouser(rqnick, np, "- User was not on chanlev (Q/S): %d", qr_nochanlev);
781 sendnoticetouser(rqnick, np, "- User was not the owner (Q/S): %d", qr_notowner);
782}