nick *sender=source;
chanindex *cip;
regchan *rcp;
- regchanuser *rcup, *rcuplist;
+ regchanuser *rcup, *trcup, *rcuplist;
regchanuser **rusers;
reguser *rup=getreguserfromnick(sender), *target;
- char time1[15],time2[15];
+ char time1[TIMELEN],time2[TIMELEN];
char flagbuf[30];
- struct tm *tmp;
flag_t flagmask, changemask, flags, oldflags;
int showtimes=0;
int donehead=0;
int i,j;
int newuser=0;
int usercount;
+ void *args[3];
if (cargc<1) {
chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "chanlev");
if (cargc==1) {
/* One arg: list chanlev */
+ int ncnt=0,mcnt=0,ocnt=0,vcnt=0,kcnt=0,bcnt=0;
+
if (cs_privcheck(QPRIV_VIEWFULLCHANLEV, sender)) {
reguser *founder=NULL, *addedby=NULL;
addedby=findreguserbyID(rcp->addedby);
}
}
+ if (CIsSuspended(rcp) && cs_privcheck(QPRIV_VIEWCHANSUSPENSION, sender)) {
+ char *bywhom;
+
+ if(cs_privcheck(QPRIV_VIEWSUSPENDEDBY, sender)) {
+ reguser *trup = findreguserbyID(rcp->suspendby);
+ if(trup) {
+ bywhom = trup->username;
+ } else {
+ bywhom = "(unknown)";
+ }
+ } else {
+ bywhom = "(hidden)";
+ }
+
+ chanservstdmessage(sender, QM_CHANLEV_SUSPENDREASON, rcp->suspendreason?rcp->suspendreason->content:"(no reason)");
+ chanservstdmessage(sender, QM_CHANLEV_SUSPENDBY, bywhom);
+ chanservstdmessage(sender, QM_CHANLEV_SUSPENDSINCE, rcp->suspendtime);
+ }
+
+ if (rcp->comment && (cs_privcheck(QPRIV_VIEWCOMMENTS, sender)))
+ chanservstdmessage(sender, QM_SHORT_COMMENT, rcp->comment->content);
+
/* Count users */
for (i=0,usercount=0;i<REGCHANUSERHASHSIZE;i++)
for (rcuplist=rcp->regusers[i];rcuplist;rcuplist=rcuplist->nextbychan)
flags=rcuplist->flags & (flagmask | QCUFLAGS_PERSONAL);
}
+ /* Do the count here; note that +n's aren't counted as +m (and so on). We're not
+ * using the IsX() macros because the displayed count needs to match up with
+ * the displayed flags... */
+ if (flags & QCUFLAG_OWNER) ncnt++; else
+ if (flags & QCUFLAG_MASTER) mcnt++; else
+ if (flags & QCUFLAG_OP) ocnt++; else
+ if (flags & QCUFLAG_VOICE) vcnt++; else
+ if (flags & QCUFLAG_KNOWN) kcnt++;
+ if (flags & QCUFLAG_BANNED) bcnt++;
+
if (!donehead) {
chanservstdmessage(sender, QM_CHANLEVHEADER, cip->name->content);
if (showtimes)
if (!rcuplist->usetime) {
strcpy(time1,"Never");
} else {
- tmp=localtime(&(rcuplist->usetime));
- strftime(time1,15,"%d/%m/%y %H:%M",tmp);
+ q9strftime(time1,sizeof(time1),rcuplist->usetime);
}
if (!rcuplist->changetime) {
strcpy(time2, "Unknown");
} else {
- tmp=localtime(&(rcuplist->changetime));
- strftime(time2,15,"%d/%m/%y %H:%M",tmp);
+ q9strftime(time2,sizeof(time2),rcuplist->changetime);
}
chanservsendmessage(sender, " %-15s %-13s %-14s %-14s %s", rcuplist->user->username,
printflags(flags, rcuflags), time1, time2, rcuplist->info?rcuplist->info->content:"");
if (donehead) {
chanservstdmessage(sender, QM_ENDOFLIST);
+ chanservstdmessage(sender, QM_CHANLEVSUMMARY, j, ncnt, mcnt, ocnt, vcnt, kcnt, bcnt);
} else {
chanservstdmessage(sender, QM_NOUSERSONCHANLEV, cip->name->content);
}
+
+ triggerhook(HOOK_CHANSERV_CHANLEVDUMP, sender);
free(rusers);
} else {
}
if (!rcuplist) {
+ /* new user, we could store a count instead... that's probably better... */
+ unsigned int chanlevcount, channelcount;
+
+ for (chanlevcount=i=0;i<REGCHANUSERHASHSIZE;i++)
+ for (rcuplist=rcp->regusers[i];rcuplist;rcuplist=rcuplist->nextbychan)
+ chanlevcount++;
+
+ if(chanlevcount >= MAXCHANLEVS) {
+ chanservstdmessage(sender, QM_TOOMANYCHANLEVS);
+ return CMD_ERROR;
+ }
+
+ channelcount=0;
+ for (trcup=target->knownon;trcup;trcup=trcup->nextbyuser)
+ channelcount++;
+
+ if(channelcount >= MAXCHANNELS) {
+ chanservstdmessage(sender, QM_TOOMANYCHANNELS);
+ return CMD_ERROR;
+ }
+
rcuplist=getregchanuser();
rcuplist->user=target;
rcuplist->chan=rcp;
/* Everyone can change their own flags (except +dqb), and control (and see) personal flags */
if (rcup==rcuplist) {
- changemask = (rcup->flags | QCUFLAGS_PERSONAL) &
- ~(QCUFLAG_BANNED | QCUFLAG_DENY | QCUFLAG_QUIET);
+ changemask = (rcup->flags | QCUFLAGS_PERSONAL) & ~(QCUFLAGS_PUNISH);
flagmask |= QCUFLAGS_PERSONAL;
}
/* Masters are allowed to manipulate +ovagtbqdpk */
if (CUHasMasterPriv(rcup))
changemask |= ( QCUFLAG_KNOWN | QCUFLAG_OP | QCUFLAG_VOICE | QCUFLAG_AUTOOP | QCUFLAG_AUTOVOICE |
- QCUFLAG_TOPIC | QCUFLAG_BANNED | QCUFLAG_QUIET | QCUFLAG_DENY | QCUFLAG_PROTECT);
+ QCUFLAG_TOPIC | QCUFLAG_PROTECT | QCUFLAGS_PUNISH);
/* Owners are allowed to manipulate +ms as well.
* We allow +n to be given initially, but we check later to see if the flag has been added.
oldflags=rcuplist->flags;
if (setflags(&(rcuplist->flags), changemask, cargv[2], rcuflags, REJECT_UNKNOWN | REJECT_DISALLOWED)) {
chanservstdmessage(sender, QM_INVALIDCHANLEVCHANGE);
+ if (newuser)
+ freeregchanuser(rcuplist);
return CMD_ERROR;
}
- /* check to see if +n has been given */
- if (!(oldflags & QCUFLAG_OWNER) && (rcuplist->flags & QCUFLAG_OWNER)) {
+ /* check to see if +n has been given. Opers can bypass this. */
+ if (!cs_privcheck(QPRIV_CHANGECHANLEV, sender) && !(oldflags & QCUFLAG_OWNER) && (rcuplist->flags & QCUFLAG_OWNER)) {
rcuplist->flags=oldflags;
chanservstdmessage(sender, QM_USEGIVEOWNER);
+ if (newuser)
+ freeregchanuser(rcuplist);
return CMD_ERROR;
}
- /* Now fix up some "impossible" combinations.. */
- /* +m can't be any of +qdb */
- if (CUHasMasterPriv(rcuplist))
- rcuplist->flags &= ~(QCUFLAG_BANNED | QCUFLAG_QUIET | QCUFLAG_DENY);
-
- /* +d can't be +o */
- if (CUIsDeny(rcuplist))
- rcuplist->flags &= ~QCUFLAG_OP;
-
- /* +q can't be +v */
- if (CUIsQuiet(rcuplist))
- rcuplist->flags &= ~QCUFLAG_VOICE;
-
- /* -o or +p can't be +a */
- if (!CUIsOp(rcuplist) || CUIsProtect(rcuplist))
- rcuplist->flags &= ~QCUFLAG_AUTOOP;
-
- /* +a or -v or +p can't be +g */
- if (!CUIsVoice(rcuplist) || CUIsAutoOp(rcuplist) || CUIsProtect(rcuplist))
- rcuplist->flags &= ~QCUFLAG_AUTOVOICE;
-
- /* and -ov can't be +p */
- if (!CUIsOp(rcuplist) && !CUIsVoice(rcuplist))
- rcuplist->flags &= ~QCUFLAG_PROTECT;
-
- /* Unknown users aren't allowed personal flags */
- if (!CUKnown(rcuplist))
- rcuplist->flags &= ~QCUFLAGS_PERSONAL;
+ /* Fix up impossible combinations */
+ rcuplist->flags = cs_sanitisechanlev(rcuplist->flags);
/* Check if anything "significant" has changed */
if ((oldflags ^ rcuplist->flags) & (QCUFLAG_OWNER | QCUFLAG_MASTER | QCUFLAG_OP))
rcuplist->changetime=time(NULL);
if(rcuplist->flags == oldflags) {
- chanservstdmessage(sender, QM_DONE);
+ chanservstdmessage(sender, QM_CHANLEVNOCHANGE);
+ if (newuser)
+ freeregchanuser(rcuplist);
return CMD_OK;
}
-
strcpy(flagbuf,printflags(oldflags,rcuflags));
cs_log(sender,"CHANLEV %s #%s %s (%s -> %s)",cip->name->content,rcuplist->user->username,cargv[2],
flagbuf,printflags(rcuplist->flags,rcuflags));
csdb_chanlevhistory_insert(rcp, sender, rcuplist->user, oldflags, rcuplist->flags);
+ /* The user has to be on the relevant chanlev list before we trigger the hook.
+ * So that enlisting has been hoisted to here. */
+ if (newuser && rcuplist->flags) {
+ addregusertochannel(rcuplist);
+ }
+
+ args[0]=sender;
+ args[1]=rcuplist;
+ args[2]=(void *)oldflags;
+
+ triggerhook(HOOK_CHANSERV_CHANLEVMOD, args);
+
/* Now see what we do next */
if (rcuplist->flags) {
/* User still valid: update or create */
if (newuser) {
- addregusertochannel(rcuplist);
csdb_createchanuser(rcuplist);
} else {
csdb_updatechanuser(rcuplist);
}
+ chanservstdmessage(sender, QM_CHANLEVCHANGED, cargv[1], cip->name->content,
+ printflags(rcuplist->flags & flagmask, rcuflags));
} else {
/* User has no flags: delete */
if (!newuser) {
+ chanservstdmessage(sender, QM_CHANLEVREMOVED, cargv[1], cip->name->content);
csdb_deletechanuser(rcuplist);
delreguserfromchannel(rcp, target);
}
freeregchanuser(rcuplist);
rcuplist=NULL;
- for (i=0;i<REGCHANUSERHASHSIZE;i++)
- if (rcp->regusers[i])
- break;
- if (i==REGCHANUSERHASHSIZE) {
- cs_log(sender,"DELCHAN %s (Cleared chanlev)",cip->name->content);
- cs_removechannel(rcp);
- }
+ if (cs_removechannelifempty(sender, rcp)) {
+ chanservstdmessage(sender, QM_CHANLEVEMPTIEDCHANNEL);
+ return CMD_OK;
+ }
}
-
- /* Say we've done it */
- chanservstdmessage(sender, QM_DONE);
+
+ /* Update the channel if needed */
rcp->status |= QCSTAT_OPCHECK;
cs_timerfunc(cip);
- }
-
- if (rcuplist && (rcuplist->flags & flagmask)) {
- chanservstdmessage(sender, QM_CHANUSERFLAGS, cargv[1], cip->name->content,
- printflags(rcuplist->flags & flagmask, rcuflags));
} else {
- chanservstdmessage(sender, QM_CHANUSERUNKNOWN, cargv[1], cip->name->content);
+ if (rcuplist == rcup)
+ flagmask |= QCUFLAGS_PERSONAL;
+ if (rcuplist && (rcuplist->flags & flagmask)) {
+ chanservstdmessage(sender, QM_CHANUSERFLAGS, cargv[1], cip->name->content,
+ printflags(rcuplist->flags & flagmask, rcuflags));
+ } else {
+ chanservstdmessage(sender, QM_CHANUSERUNKNOWN, cargv[1], cip->name->content);
+ }
}
}
+
return CMD_OK;
}