}
cmd=findcommandintree(csctcpcommands, cargv[0]+1, 1);
if (cmd) {
+ cmd->calls++;
rejoinline(cargv[1],cargc-1);
cmd->handler((void *)sender, cargc-1, &(cargv[1]));
}
break;
}
+ if ((cmd->level & QCMD_STAFF) &&
+ (!(rup=getreguserfromnick(sender)) || !UHasStaffPriv(rup))) {
+ chanservstdmessage(sender, QM_NOACCESS, cargv[0]);
+ break;
+ }
+
if ((cmd->level & QCMD_HELPER) &&
(!(rup=getreguserfromnick(sender)) || !UHasHelperPriv(rup))) {
chanservstdmessage(sender, QM_NOACCESS, cargv[0]);
break;
}
+ cmd->calls++;
+
if (cmd->maxparams < (cargc-1)) {
rejoinline(cargv[cmd->maxparams],cargc-(cmd->maxparams));
cargc=(cmd->maxparams)+1;
deletecommandfromtree(cscommands, command, handler);
}
+void chanservpartchan(channel *cp, char *reason) {
+ /* Sanity check that we exist and are on the channel.
+ *
+ * Note that we don't do any of the other usual sanity checks here; if
+ * this channel is unregged or suspended or whatever then all the more
+ * reason to get Q off it ASAP! */
+ if (!chanservnick || !cp || !cp->users || !getnumerichandlefromchanhash(cp->users, chanservnick->numeric))
+ return;
+
+ localpartchannel(chanservnick, cp, reason);
+}
+
void chanservjoinchan(channel *cp) {
regchan *rcp;
unsigned int i;
if (!chanservnick)
return;
+ /* In gerenal this function shouldn't be used any more as a reason to get
+ * Q to leave, but if it should be leaving then just part with no reason. */
if ((CIsSuspended(rcp) || !CIsJoined(rcp)) && getnumerichandlefromchanhash(cp->users, chanservnick->numeric)) {
- if(rcp->suspendreason) {
- localpartchannel(chanservnick, cp, rcp->suspendreason->content);
- } else {
- localpartchannel(chanservnick, cp, NULL);
- }
+ localpartchannel(chanservnick, cp, NULL);
}
/* Right, we are definately going to either join the channel or at least
va_list va;
nick *np;
unsigned int i=0;
-
+
va_start(va,message);
vsnprintf(buf,5000,message,va);
va_end(va);
/* Scan for users */
- for (i=0;i<NICKHASHSIZE;i++)
- for (np=nicktable[i];np;np=np->next)
- if (IsOper(np))
- chanservsendmessage(np, "%s", buf);
+ for (i=0;i<NICKHASHSIZE;i++) {
+ for (np=nicktable[i];np;np=np->next) {
+ if (!IsOper(np)) /* optimisation, if VIEWWALLMESSAGE changes change this */
+ continue;
+
+ if (!cs_privcheck(QPRIV_VIEWWALLMESSAGE, np))
+ continue;
+
+ chanservsendmessage(np, "%s", buf);
+ }
+ }
}
void chanservkillstdmessage(nick *target, int messageid, ... ) {
va_start(va, messageid);
q9vsnprintf(buf, 511, message, messageargs, va);
va_end(va);
- killuser(chanservnick, target, buf);
+ killuser(chanservnick, target, "%s", buf);
}
int checkpassword(reguser *rup, const char *pass) {
+ if (!(*rup->password))
+ return 0;
+
if (!strncmp(rup->password, pass, PASSLEN))
return 1;
return 0;
int checkresponse(reguser *rup, const unsigned char *entropy, const char *response, CRAlgorithm algorithm) {
char usernamel[NICKLEN+1], *dp, *up;
+ if (!(*rup->password))
+ return 0;
+
for(up=rup->username,dp=usernamel;*up;)
*dp++ = ToLower(*up++);
*dp = '\0';
rup->created=time(NULL);
rup->lastauth=0;
rup->lastemailchange=0;
+ rup->lastpasschange=0;
rup->flags=QUFLAG_NOTICE;
rup->languageid=0;
rup->suspendby=0;
continue;
if ((np=getnickbynumeric(cp->users->content[i]))==NULL) {
- Error("chanserv",ERR_ERROR,"Found non-existent numeric %d on channel %s",cp->users->content[i],
+ Error("chanserv",ERR_ERROR,"Found non-existent numeric %lu on channel %s",cp->users->content[i],
cp->index->name->content);
continue;
}
else
rcup=NULL;
- if (rcup && CUIsBanned(rcup) && !IsService(np)) {
- cs_banuser(changes, cp->index, np, NULL);
- continue;
- }
-
- /* chanflag +k checks; kick them if they "obviously" can't rejoin without a ban */
- if (!IsService(np) && CIsKnownOnly(rcp) && !(rcup && CUKnown(rcup))) {
- if (IsInviteOnly(cp) || (IsRegOnly(cp) && !IsAccount(np))) {
- localkickuser(chanservnick,cp,np,"Authorised users only.");
- } else {
- cs_banuser(NULL, cp->index, np, "Authorised users only.");
+ /* Various things that might ban the user - don't apply these to +o, +k or +X users */
+ if (!IsService(np) && !IsXOper(np) && !IsOper(np)) {
+ if (rcup && CUIsBanned(rcup)) {
+ cs_banuser(changes, cp->index, np, NULL);
+ continue;
+ }
+
+ /* chanflag +k checks; kick them if they "obviously" can't rejoin without a ban */
+ if (CIsKnownOnly(rcp) && !(rcup && CUKnown(rcup))) {
+ if (IsInviteOnly(cp) || (IsRegOnly(cp) && !IsAccount(np))) {
+ localkickuser(chanservnick,cp,np,"Authorised users only.");
+ } else {
+ cs_banuser(NULL, cp->index, np, "Authorised users only.");
+ }
+ continue;
}
- continue;
}
if ((cp->users->content[i] & CUMODE_OP) && !IsService(np)) {
return;
for (rcup=rup->knownon;rcup;rcup=rcup->nextbyuser) {
+ /* Skip suspended channels */
+ if (CIsSuspended(rcup->chan))
+ continue;
+
if (rcup->chan->index->channel) {
/* Channel exists */
if ((lp=getnumerichandlefromchanhash(rcup->chan->index->channel->users, np->numeric))) {
/* User is on channel.. */
+ /* Update last use time. Do early in case of ban. */
+ rcup->usetime=getnettime();
+
+ if (CUIsBanned(rcup)) {
+ cs_banuser(NULL, rcup->chan->index, np, NULL);
+ continue;
+ }
+
if (CUKnown(rcup) && rcup->chan->index->channel->users->totalusers >= 3) {
/* This meets the channel use criteria, update. */
rcup->chan->lastactive=time(NULL);
}
}
- /* Update last use time */
- rcup->usetime=getnettime();
localsetmodeinit(&changes, rcup->chan->index->channel, chanservnick);
if (*lp & CUMODE_OP) {
} else {
/* Channel exists but user is not joined: invite if they are +j-b */
if (CUIsAutoInvite(rcup) && CUKnown(rcup) && !CUIsBanned(rcup)) {
- localinvite(chanservnick, rcup->chan->index->channel, np);
+ localinvite(chanservnick, rcup->chan->index, np);
}
}
}
regchan *rcp;
int i,j;
- if (IsService(np))
+ if (IsService(np) || IsOper(np) || IsXOper(np))
return;
/* Avoid races: memcpy the channel array */
for (j=0;j<i;j++) {
if ((rcp=ca[j]->index->exts[chanservext]) && !CIsSuspended(rcp) &&
- CIsEnforce(rcp) && nickbanned_visible(np, ca[j]))
+ CIsEnforce(rcp) && nickbanned(np, ca[j], 1))
localkickuser(chanservnick, ca[j], np, "Banned.");
}
continue;
if ((np=getnickbynumeric(cp->users->content[i]))==NULL) {
- Error("chanserv",ERR_ERROR,"Found numeric %d on channel %s who doesn't exist.",
+ Error("chanserv",ERR_ERROR,"Found numeric %lu on channel %s who doesn't exist.",
cp->users->content[i], cp->index->name->content);
continue;
}
- if (IsService(np))
+ if (IsService(np) || IsOper(np) || IsXOper(np))
continue;
for (rbp=rcp->bans;rbp;rbp=rbp->next) {
if (((!rbp->expiry) || (rbp->expiry <= now)) &&
- nickmatchban_visible(np, rbp->cbp)) {
- if (!nickbanned_visible(np, cp)) {
+ nickmatchban(np, rbp->cbp, 1)) {
+ if (!nickbanned(np, cp, 1)) {
localdosetmode_ban(&changes, bantostring(rbp->cbp), MCB_ADD);
}
localkickuser(chanservnick,cp,np,rbp->reason?rbp->reason->content:"Banned.");
if (CIsEnforce(rcp)) {
for (cbp=cp->bans;cbp;cbp=cbp->next) {
- if ((cbp->timeset>=rcp->lastbancheck) && nickmatchban_visible(np, cbp))
+ if ((cbp->timeset>=rcp->lastbancheck) && nickmatchban(np, cbp, 1))
localkickuser(chanservnick,cp,np,"Banned.");
}
rcp->lastbancheck=time(NULL);
localsetmodeflush(&changes, 1);
}
-void cs_removechannel(regchan *rcp) {
+void cs_removechannel(regchan *rcp, char *reason) {
int i;
chanindex *cip;
regchanuser *rcup, *nrcup;
deleteschedule(rcp->checksched, cs_timerfunc, rcp->index);
if (cip->channel) {
- rcp->flags=QCFLAG_SUSPENDED;
- chanservjoinchan(cip->channel); /* Force off the channel */
+ chanservpartchan(cip->channel, reason);
}
csdb_deletechannel(rcp);
}
cs_log(sender,"DELCHAN %s (Empty)",rcp->index->name->content);
- cs_removechannel(rcp);
+ cs_removechannel(rcp, "Last user removed - channel deleted.");
return 1;
}
freesstring(rbp->reason);
freechanban(rbp->cbp);
freeregban(rbp);
- } else if (nickmatchban_visible(np,(*rbh)->cbp)) {
+ } else if (nickmatchban(np,(*rbh)->cbp,1)) {
/* This user matches this ban.. */
- if (!nickbanned_visible(np,cp)) {
+ if (!nickbanned(np,cp,1)) {
/* Only bother putting the ban on the channel if they're not banned already */
/* (might be covered by this ban or a different one.. doesn't really matter */
localsetmodeinit(&changes, cp, chanservnick);
for (i=0;(cip->channel) && i<cip->channel->users->hashsize;i++) {
if (cip->channel->users->content[i]!=nouser &&
(np=getnickbynumeric(cip->channel->users->content[i])) &&
- !IsService(np) &&
- nickmatchban_visible(np, rbp->cbp))
+ !IsService(np) && !IsOper(np) && !IsXOper(np) &&
+ nickmatchban(np, rbp->cbp, 1))
localkickuser(chanservnick, cip->channel, np, rbp->reason ? rbp->reason->content : "Banned.");
}
if (!cip->channel)
return;
- if (nickbanned_visible(np, cip->channel)) {
+ if (nickbanned(np, cip->channel, 1)) {
localkickuser(chanservnick, cip->channel, np, reason?reason:"Banned.");
return;
}
}
if (!(rup=findreguserbynick(str+1)) && sender)
chanservstdmessage(sender, QM_UNKNOWNUSER, str);
- } else if (*str=='&' && vrup && UHasHelperPriv(vrup)) {
+ } else if (*str=='&' && vrup && UHasStaffPriv(vrup)) {
if (str[1]=='\0') {
if (sender)
chanservstdmessage(sender, QM_UNKNOWNUSER, str);
rcp->chanopaccts[rcp->chanoppos]=rup->ID;
rcp->chanoppos=(rcp->chanoppos+1)%CHANOPHISTORY;
}
+
+int checkreason(nick *np, char *reason) {
+ if((strlen(reason) < MIN_REASONLEN) || !strchr(reason, ' ')) {
+ chanservstdmessage(np, QM_REASONREQUIRED);
+ return 0;
+ }
+
+ return 1;
+}