X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/blobdiff_plain/bdd430cb4a74b16c6deea69fd63937ab777e20ef..9e5f0d797a0957172a9fd7b79f20115bc6fdcbd7:/request/sqrequest.c diff --git a/request/sqrequest.c b/request/sqrequest.c index fc150519..f2e06988 100644 --- a/request/sqrequest.c +++ b/request/sqrequest.c @@ -13,6 +13,10 @@ #include "../localuser/localuser.h" #include "../lib/irc_string.h" #include "../core/schedule.h" +#include "../core/config.h" +/* +#include "../spamscan2/spamscan2.h" +*/ #include #include @@ -46,7 +50,7 @@ requestrec *nextreql, *lastreql; requestrec *nextreqq, *lastreqq; -requestrec *nextqreq, *lastqreq; +static requestrec *nextqreq, *lastqreq; extern nick *rqnick; int rlstate; @@ -59,6 +63,12 @@ int qr_toosmall = 0; int qr_nochanlev = 0; int qr_notowner = 0; +int qr_a = 0; +int qr_b = 0; +int qr_c = 0; +int qr_d = 0; +int qr_e = 0; + /* Check whether the user is blocked */ int qr_blockcheck(requestrec *req) { nick *np; @@ -78,21 +88,35 @@ int qr_blockcheck(requestrec *req) { return 0; } +unsigned int rq_countchanusers(channel *cp) { + int i, count=0; + + for (i=0;iusers->hashsize;i++) { + if (cp->users->content[i]==nouser) + continue; + + count++; + } + + return count; +} + /* * Deal with outcome of a queued request. The request should be freed * as part of the process. */ -void qr_result(requestrec *req, int outcome, char *message, ...) { +static void qr_result(requestrec *req, int outcome, char failcode, char *message, ...) __attribute__ ((format (printf, 4, 5))); +static void qr_result(requestrec *req, int outcome, char failcode, char *message, ...) { sstring *user, *password; requestrec **rh; char msgbuf[512]; va_list va; - channel *cplog; - nick *lnp, *qnp, *np, *tnp, *snp; + nick *np, *tnp, *snp; char now[50]; time_t now_ts; - + unsigned int unique, total; + /* Delete the request from the list first.. */ for (rh=&nextreql;*rh;rh=&((*rh)->next)) { if (*rh==req) { @@ -136,45 +160,40 @@ void qr_result(requestrec *req, int outcome, char *message, ...) { now[0] = '\0'; now_ts = time(NULL); + if (req->cip->channel) { + unique = countuniquehosts(req->cip->channel); + total = rq_countchanusers(req->cip->channel); + } else { + unique = 0; + total = 0; + } + strftime(now, sizeof(now), "%c", localtime(&now_ts)); - 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"); + fprintf(rq_logfd, "%s: request (%s) for %s (%d unique users, " + "%d total users) from %s!%s@%s%s%s: Request was %s (%c).\n", now, + (req->what == QR_CSERVE) ? rq_qnick->content : rq_snick->content, + req->cip->name->content, unique, total, + tnp->nick, tnp->ident, tnp->host->name->content, IsAccount(tnp)?"/":"", IsAccount(tnp)?tnp->authname:"", + (outcome == QR_OK) ? "accepted" : "denied", failcode); fflush(rq_logfd); } if (outcome==QR_OK) { - if (req->what == QR_CSERVE) { - /* Delete L, add Q. Check that they both exist first, though. */ - - if (!(lnp=getnickbynick(RQ_LNICK)) || !(qnp=getnickbynick(RQ_QNICK))) { - sendnoticetouser(rqnick, tnp, - "Error: Cannot find %s and %s on the network. " - "Please request again later.", RQ_LNICK, RQ_QNICK); - free(req); - return; - } - - /* /msg Q ADDCHAN */ - sendmessagetouser(rqnick, qnp, "ADDCHAN %s +ap #%s upgrade", - req->cip->name->content, - np->authname); - - sendnoticetouser(rqnick, tnp, "Adding %s to channel, please wait...", - RQ_QNICK); - } else if (req->what == QR_SPAMSCAN) { + if (req->what == QR_SPAMSCAN) { /* Add S */ - if (!(snp=getnickbynick(RQ_SNICK))) { + if (!(snp=getnickbynick(rq_snick->content))) { sendnoticetouser(rqnick, tnp, - "Error: Cannot find %s on the network. " - "Please request again later.", RQ_SNICK); + "Cannot find %s on the network. " + "Please try your request again later.", rq_snick->content); free(req); return; } - sendnoticetouser(rqnick, tnp, "Requirements met, %s should be added. " - "Contact #help should further assistance be required.", - RQ_SNICK); + sendnoticetouser(rqnick, tnp, "Success! %s has been added to '%s' " + "(contact #help if you require further assistance).", + rq_snick->content, req->cip->name->content); /* auth */ user = (sstring *)getcopyconfigitem("request", "user", "R", 30); @@ -184,7 +203,47 @@ void qr_result(requestrec *req, int outcome, char *message, ...) { freesstring(password); /* /msg S addchan default */ - sendmessagetouser(rqnick, snp, "ADDCHAN %s default +op", req->cip->name->content); + sendmessagetouser(rqnick, snp, "ADDCHAN %s default +o", req->cip->name->content); + +/* +{ + spamscan_channelprofile *cp; + spamscan_channelsettings *cs; + spamscan_channelext *ce; + chanindex *sc_index; + + cs = spamscan_getchannelsettings(req->cip->name->content, 0); + + if ( !cs ) { + cp = spamscan_getchannelprofile("Default", 0); + + if ( cp ) { + cs = spamscan_getchannelsettings(req->cip->name->content, 1); + + if ( cs ) { + cs->cp = cp; + cs->addedby = spamscan_getaccountsettings("R", 0); + cs->flags = SPAMSCAN_CF_IGNOREOPS; + + sc_index = findorcreatechanindex(req->cip->name->content); + + if ( sc_index ) { + ce = spamscan_getchanext(sc_index, 1); + ce->cs = cs; + + if ( s_nickname && !CFIsSuspended(cs) && sc_index->channel ) { + ce->joinedchan = 1; + localjoinchannel(s_nickname, sc_index->channel); + localgetops(s_nickname, sc_index->channel); + } + } + + spamscan_insertchanneldb(cs); + } + } + } +} +*/ /* we do not put the request into another queue, so free it here */ free(req); @@ -222,11 +281,11 @@ void qr_result(requestrec *req, int outcome, char *message, ...) { * Checks that a channel is beeeeg enough for teh Q */ -int qr_checksize(chanindex *cip, int what) { +static int qr_checksize(chanindex *cip, int what, char *failcode) { chanstats *csp; channel *cp; - nick *np; - int i , avg, tot=0, authedcount=0, count=0; + nick *np, *qbot; + int i , avg, tot=0, authedcount=0, count=0, uniquecount, avgcount; cp = cip->channel; @@ -237,6 +296,20 @@ int qr_checksize(chanindex *cip, int what) { return 1; #endif + /* make sure we can actually add Q */ + if (what == QR_CSERVE) { + qbot = getnickbynick(rq_qnick->content); + + if (!qbot) + return 0; + + if (QR_MAXQCHANS != 0 && qbot->channels->cursi > QR_MAXQCHANS) { + qr_a++; + *failcode = 'A'; + return 0; /* no Q for you :p */ + } + } + /* make sure that there are enough authed users */ for (i=0;iusers->hashsize;i++) { if (cp->users->content[i] != nouser) { @@ -249,8 +322,32 @@ int qr_checksize(chanindex *cip, int what) { } } - if (authedcount * 100 / count < ((what == QR_CSERVE) ? QR_AUTHEDPCT_CSERVE : QR_AUTHEDPCT_SPAMSCAN)) + int authedpct; + + if (what == QR_CSERVE) { + if ( count <= QR_AUTHEDPCT_SCALE ) { + authedpct = QR_AUTHEDPCT_CSERVE; + } else if ( count >= QR_AUTHEDPCT_SCALEMAX ) { + authedpct = QR_AUTHEDPCT_CSERVEMIN; + } else { + authedpct = (QR_AUTHEDPCT_CSERVEMIN + (((QR_AUTHEDPCT_CSERVE - QR_AUTHEDPCT_CSERVEMIN) * (100 - (((count - QR_AUTHEDPCT_SCALE) * 100) / (QR_AUTHEDPCT_SCALEMAX - QR_AUTHEDPCT_SCALE)))) / 100)); + } + } + else { + if ( count <= QR_AUTHEDPCT_SCALE ) { + authedpct = QR_AUTHEDPCT_SPAMSCAN; + } else if ( count >= QR_AUTHEDPCT_SCALEMAX ) { + authedpct = QR_AUTHEDPCT_SPAMSCANMIN; + } else { + authedpct = (QR_AUTHEDPCT_SPAMSCANMIN + (((QR_AUTHEDPCT_SPAMSCAN - QR_AUTHEDPCT_SPAMSCANMIN) * (100 - (((count - QR_AUTHEDPCT_SCALE) * 100) / (QR_AUTHEDPCT_SCALEMAX - QR_AUTHEDPCT_SCALE)))) / 100)); + } + } + + if (authedcount * 100 / count < authedpct) { + qr_b++; + *failcode = 'B'; return 0; /* too few authed users */ + } if (!(csp=cip->exts[csext])) return 0; @@ -259,12 +356,33 @@ int qr_checksize(chanindex *cip, int what) { tot += csp->lastdays[i]; } + uniquecount = countuniquehosts(cp); + avgcount = tot / HISTORYDAYS / 10; + + /* chan needs at least QR_MINUSERPCT% of the avg usercount, and can't have + * more than QR_MAXUSERPCT% */ + if ( what == QR_CSERVE ) { + if ((avgcount * QR_MINUSERSPCT / 100 > uniquecount)) { + qr_c++; + *failcode = 'C'; + return 0; + } + if ((avgcount * QR_MAXUSERSPCT / 100 < uniquecount)) { + qr_e++; + *failcode = 'E'; + return 0; + } + } + avg = (what == QR_CSERVE) ? QR_REQUIREDSIZE_CSERVE : QR_REQUIREDSIZE_SPAMSCAN; if (tot > (avg * 140)) return 1; - - return 0; + else { + qr_d++; + *failcode = 'D'; + return 0; + } } /* This function deals with notices from L: basically we track the @@ -279,50 +397,25 @@ int qr_checksize(chanindex *cip, int what) { * 11:12 -L(TheLBot@lightweight.quakenet.org)- End of chanlev for #twilightzone. */ -void qr_handlenotice(nick *sender, char *message) { +void qr_handle_notice(nick *sender, char *message) { char *ch, *chop; chanindex *cip; requestrec *rrp1, *rrp2; nick *np; int delrequest = 0, state, who; requestrec *nextreq; - channel *logcp; -/* logcp = findchannel("#qnet.request"); - - if (logcp) - sendmessagetochannel(rqnick, logcp, "%s: %s - %d %d %x %x", sender->nick, message, rlstate, rqstate, nextreql, nextreqq); -*/ - if (!ircd_strcmp(sender->nick, RQ_QNICK) && nextqreq) { + if (!ircd_strcmp(sender->nick, rq_qnick->content) && nextqreq) { /* Message from Q */ if (!ircd_strcmp(message,"Done.")) { /* Q added the channel: delete from L and tell the user. */ /* If L has conspired to vanish between the request and the outcome, * we have a chan with Q and L... too bad. */ - - if ((np=getnickbynick(RQ_LNICK))) { - sendmessagetouser(rqnick, np, "SENDCHANLEV %s %s", - nextqreq->cip->name->content, RQ_QNICK); - - sendmessagetouser(rqnick, np, "DELCHAN %s", - nextqreq->cip->name->content); - } - - if ((np=getnickbynumeric(nextqreq->reqnumeric))) { - sendnoticetouser(rqnick, np, "Request completed. %s added.", RQ_QNICK); - } delrequest = 1; } else if (!ircd_strcmp(message,"That channel already exists.")) { - if ((np=getnickbynumeric(nextqreq->reqnumeric))) { - sendnoticetouser(rqnick, np, - "Your channel appears to have %s already " - "(it may be suspended).", RQ_QNICK); - - qr_suspended++; delrequest = 1; - } } /* For either of the two messages above we want to delete the request @@ -338,8 +431,8 @@ void qr_handlenotice(nick *sender, char *message) { } } - if (!ircd_strcmp(sender->nick, RQ_LNICK) || !ircd_strcmp(sender->nick, RQ_QNICK)) { - who = !ircd_strcmp(sender->nick, RQ_LNICK) ? QR_L : QR_Q; + if (!ircd_strcmp(sender->nick, rq_qnick->content)) { + who = QR_Q; state = (who == QR_Q) ? rqstate : rlstate; nextreq = (who == QR_Q) ? nextreqq : nextreql; @@ -355,7 +448,6 @@ void qr_handlenotice(nick *sender, char *message) { (!ircd_strncmp(message,"Known users on",14) && who == QR_Q) ) { /* Looks like the right message. Let's find a channel name */ - for (ch=message;*ch;ch++) if (*ch=='#') break; @@ -369,12 +461,11 @@ void qr_handlenotice(nick *sender, char *message) { /* chop off any remaining words */ chop = ch; while (*(chop++)) { - if (*chop == ' ') { + if (*chop == ' ' || *chop == ':') { *chop = '\0'; break; } } - if (!(cip=findchanindex(ch))) { Error("qrequest",ERR_WARNING, "Unable to find channel from L/Q message: %s",ch); @@ -388,7 +479,6 @@ void qr_handlenotice(nick *sender, char *message) { rlstate = QRLstate_AWAITINGUSER; else rqstate = QRLstate_AWAITINGUSER; - return; } else { /* Uh-oh, not the channel we wanted. Something is fucked @@ -417,7 +507,7 @@ void qr_handlenotice(nick *sender, char *message) { "Lost response for channel %s; skipping.", rrp2->cip->name->content); - qr_result(rrp2, QR_FAILED, + qr_result(rrp2, QR_FAILED, 'X', "Sorry, an error occurred while processing your request."); rrp2 = nextreq = (who == QR_Q) ? nextreqq : nextreql; @@ -452,8 +542,7 @@ void qr_handlenotice(nick *sender, char *message) { /* Oh dear, we got to the end of the chanlev in this state. * This means that we didn't find the user. */ - - qr_result(nextreq, QR_FAILED, + qr_result(nextreq, QR_FAILED, 'X', "Error: You are not known on %s.", nextreq->cip->name->content); @@ -497,33 +586,42 @@ void qr_handlenotice(nick *sender, char *message) { /* This is not the user you are looking for */ return; } - /* Check for owner flag. Both branches of this if will * take the request off the list, one way or the other. */ - if (strchr(ch, 'n')) { + + /* chop off any remaining words */ + chop = ch; + while (*(chop++)) { + if (*chop != ' ' ) { + break; + } + } + /* chop off any remaining words */ + ch = chop; + while (*(chop++)) { + if (*chop == ' ' || *chop == ':') { + *chop = '\0'; + break; + } + } + + if (strchr(ch, 'n')) { + char failcode; /* They iz teh +n! */ - /* Note: We're checking for blocks kind of late, so the request system gets a chance to send other error messages first (like 'no chanstats', 'not known on channel', etc.). This is required so that the user doesn't notice that he's being blocked. */ - if (qr_checksize(nextreq->cip, nextreq->what) && !qr_blockcheck(nextreq)) { - qr_result(nextreq, QR_OK, "OK"); + if (qr_checksize(nextreq->cip, nextreq->what, &failcode) && !qr_blockcheck(nextreq)) { + qr_result(nextreq, QR_OK, '-', "OK"); } else { - if (nextreq->what == QR_CSERVE) { - qr_result(nextreq, QR_FAILED, - "Error: You do not meet the requirements " - "for %s. Please continue to use %s.", RQ_QNICK, RQ_LNICK); - } else { - qr_result(nextreq, QR_FAILED, - "Error: Your channel does not require %s. " - "Try again later.", RQ_SNICK); - } - + qr_result(nextreq, QR_FAILED, failcode, + "Error: Sorry, Your channel '%s' does not require %s. Please try again in a few days.", nextreq->cip->name->content, rq_snick->content); + qr_toosmall++; } } else { - qr_result(nextreq, QR_FAILED, + qr_result(nextreq, QR_FAILED, 'X', "Error: You don't hold the +n flag on %s.", nextreq->cip->name->content); @@ -571,57 +669,6 @@ void qr_handlenotice(nick *sender, char *message) { */ int qr_requestq(nick *rqnick, nick *sender, channel *cp, nick *lnick, nick *qnick) { - chanindex *cip = cp->index; - - /* Check: - * - we have some form of channel stats for the channel - * - * Note that the actual channel stats will not be checked - * until we're sure the user has +n on the channel. - */ - - if (rq_isspam(sender)) { - sendnoticetouser(rqnick, sender, "Error: Do not flood the request system." - " Try again in %s.", rq_longtoduration(rq_blocktime(sender))); - - return RQ_ERROR; - } - - if (!cip->exts[csext]) { - sendnoticetouser(rqnick, sender, - "Error: No historical record exists for %s.", - cip->name->content); - - qr_nohist++; - - return RQ_ERROR; - } - - /* Request stats from L */ - sendmessagetouser(rqnick, lnick, "CHANLEV %s", cip->name->content); - - /* Sort out a request record */ - if (lastreql) { - lastreql->next = (requestrec *)malloc(sizeof(requestrec)); - lastreql=lastreql->next; - } else { - lastreql=nextreql=(requestrec *)malloc(sizeof(requestrec)); - } - - lastreql->next = NULL; - lastreql->cip = cip; - lastreql->what = QR_CSERVE; - lastreql->who = QR_L; - lastreql->reqnumeric = sender->numeric; - - if (rlstate == QRLstate_IDLE) - rlstate = QRLstate_AWAITINGCHAN; - - sendnoticetouser(rqnick, sender, - "Checking your %s access. " - "This may take a while, please be patient...", RQ_LNICK); - - /* we don't know yet whether the request was successful */ return RQ_UNKNOWN; } @@ -630,9 +677,10 @@ int qr_instantrequestq(nick *sender, channel *cp) { chanfix *cf; regop *ro; int rocount, i; + char failcode; regop *rolist[QR_TOPX]; - if (!qr_checksize(cp->index, QR_CSERVE)) + if (!qr_checksize(cp->index, QR_CSERVE, &failcode)) return RQ_ERROR; cf = cf_findchanfix(cp->index); @@ -675,37 +723,17 @@ int qr_instantrequestq(nick *sender, channel *cp) { nextreql = fakerequest; } - qr_result(fakerequest, QR_OK, "OK"); + qr_result(fakerequest, QR_OK, '-', "OK"); return RQ_OK; } -int qr_requests(nick *rqnick, nick *sender, channel *cp, nick *lnick, nick *qnick) { +int qr_requests(nick *rqnick, nick *sender, channel *cp, nick *qnick) { chanindex *cip = cp->index; - int who; requestrec *nextreq, *lastreq; - if (rq_isspam(sender)) { - sendnoticetouser(rqnick, sender, "Error: Do not flood the request system." - " Try again in %s.", rq_longtoduration(rq_blocktime(sender))); - - return RQ_ERROR; - } - /* check which service is on the channel */ - if (getnumerichandlefromchanhash(cp->users, lnick->numeric) != NULL) { - /* we've found L */ - who = QR_L; - - /* Request stats from L */ - sendmessagetouser(rqnick, lnick, "CHANLEV %s", cip->name->content); - - if (rlstate == QRLstate_IDLE) - rlstate = QRLstate_AWAITINGCHAN; - } else if (getnumerichandlefromchanhash(cp->users, qnick->numeric) != NULL) { - /* we've found Q */ - who = QR_Q; - + if (getnumerichandlefromchanhash(cp->users, qnick->numeric) != NULL) { /* Request stats from Q */ sendmessagetouser(rqnick, qnick, "CHANLEV %s", cip->name->content); @@ -713,8 +741,8 @@ int qr_requests(nick *rqnick, nick *sender, channel *cp, nick *lnick, nick *qnic rqstate = QRLstate_AWAITINGCHAN; } /* 'else' cannot happen as R has already checked whether the user has L or Q */ - lastreq = (who == QR_Q) ? lastreqq : lastreql; - nextreq = (who == QR_Q) ? nextreqq : nextreql; + lastreq = lastreqq; + nextreq = nextreqq; /* Sort out a request record */ if (lastreq) { @@ -729,18 +757,13 @@ int qr_requests(nick *rqnick, nick *sender, channel *cp, nick *lnick, nick *qnic lastreq->what = QR_SPAMSCAN; lastreq->reqnumeric = sender->numeric; - if (who == QR_Q) { - nextreqq = nextreq; - lastreqq = lastreq; - } else { - nextreql = nextreq; - lastreql = lastreq; - } + nextreqq = nextreq; + lastreqq = lastreq; - sendnoticetouser(rqnick, sender, - "Checking your %s access. " + sendnoticetouser(rqnick, sender, + "Checking your %s access in '%s'. " "This may take a while, please be patient...", - who == QR_Q ? RQ_QNICK : RQ_LNICK); + rq_qnick->content, cip->name->content); return RQ_UNKNOWN; } @@ -774,9 +797,15 @@ void qr_finirequest(void) { } void qr_requeststats(nick *rqnick, nick *np) { - sendnoticetouser(rqnick, np, "- Suspended (Q): %d", qr_suspended); - sendnoticetouser(rqnick, np, "- No chanstats (Q/S): %d", qr_nohist); - sendnoticetouser(rqnick, np, "- Too small (Q/S): %d", qr_toosmall); - sendnoticetouser(rqnick, np, "- User was not on chanlev (Q/S): %d", qr_nochanlev); - sendnoticetouser(rqnick, np, "- User was not the owner (Q/S): %d", qr_notowner); + sendnoticetouser(rqnick, np, "- Suspended (S): %d", qr_suspended); + sendnoticetouser(rqnick, np, "- No chanstats (S): %d", qr_nohist); + sendnoticetouser(rqnick, np, "- Too small (S): %d", qr_toosmall); + sendnoticetouser(rqnick, np, "- User was not on chanlev (S): %d", qr_nochanlev); + sendnoticetouser(rqnick, np, "- User was not the owner (S): %d", qr_notowner); + sendnoticetouser(rqnick, np, "- A: %d", qr_a); + sendnoticetouser(rqnick, np, "- B: %d", qr_b); + sendnoticetouser(rqnick, np, "- C: %d", qr_c); + sendnoticetouser(rqnick, np, "- D: %d", qr_d); + sendnoticetouser(rqnick, np, "- E: %d", qr_e); + }