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