Tidied up error message in userflags/authhistory (i.e. a message to say you can't list for the named user).
/* don't allow non-opers to view oper auth history, but allow helpers to view non-oper history */
if ((trup != rup) && ((UHasOperPriv(trup) && !UHasOperPriv(rup)) || !UHasHelperPriv(rup))) {
- chanservstdmessage(sender, QM_NOACCESSONCHAN, "authhistory", cargv[0]);
+ chanservstdmessage(sender, QM_NOACCESSONUSER, "authhistory", cargv[0]);
return CMD_ERROR;
}
- }
- else
+ } else {
trup=rup;
-
+ }
+
csdb_retreiveauthhistory(sender, trup, 10);
return CMD_OK;
Makefile:
../mkcommandlist.pl chanserv_chancmds.so
-chanserv_chancmds.so: addchan.o adduser.o autolimit.o ban.o banclear.o bandel.o banlist.o bantimer.o chanflags.o chanlev.o chanlevhistory.o chanmode.o channelcomment.o chanstat.o chantype.o clearchan.o delchan.o deopall.o devoiceall.o giveowner.o invite.o op.o permban.o recover.o rejoin.o removeuser.o renchan.o requestowner.o rollbackchan.o settopic.o suspendchan.o suspendchanlist.o tempban.o unban.o unbanall.o unbanmask.o unbanme.o unsuspendchan.o voice.o welcome.o commandlist.o
+chanserv_chancmds.so: addchan.o adduser.o autolimit.o ban.o banclear.o bandel.o banlist.o bantimer.o chanflags.o chanlev.o chanlevhistory.o chanmode.o channelcomment.o chanophistory.o chanstat.o chantype.o clearchan.o delchan.o deopall.o devoiceall.o giveowner.o invite.o op.o permban.o recover.o rejoin.o removeuser.o renchan.o requestowner.o rollbackchan.o settopic.o suspendchan.o suspendchanlist.o tempban.o unban.o unbanall.o unbanmask.o unbanme.o unsuspendchan.o voice.o welcome.o commandlist.o
ld -shared -Bdynamic -o $@ $^
reguser *founder;
flag_t flags;
short type=0;
+ unsigned int i;
if (!rup)
return CMD_ERROR;
rcp->checksched=NULL;
rcp->ltimestamp=0;
+ for (i=0;i<CHANOPHISTORY;i++) {
+ rcp->chanopnicks[i][0]='\0';
+ rcp->chanopaccts[i]=0;
+ }
+ rcp->chanoppos=0;
/* Add new channel to db.. */
csdb_createchannel(rcp);
int csc_dochanlevhistory(void *source, int cargc, char **cargv);
int csc_dochanmode(void *source, int cargc, char **cargv);
int csc_dochannelcomment(void *source, int cargc, char **cargv);
+int csc_dochanophistory(void *source, int cargc, char **cargv);
int csc_dochanstat(void *source, int cargc, char **cargv);
int csc_dochantype(void *source, int cargc, char **cargv);
int csc_doclearchan(void *source, int cargc, char **cargv);
chanservaddcommand("chanlevhistory", QCMD_HELPER, 2, csc_dochanlevhistory, "View user access changes on a channel.", "");
chanservaddcommand("chanmode", QCMD_AUTHED, 4, csc_dochanmode, "Shows which modes are forced or denied on a channel.", "Usage: CHANMODE <channel> [<modes>]\nShows or changes the list of channel modes being enforced on the channel, where:\nchannel - the channel to use\nmodes - the list of modes to allow or deny. Modes specified with + will be\n enforced on the channel at all times, those specified with - will not\n be allowed on the channel. If modes are not specified the current\n setting will be displayed. If +k or +l modes are included, the actual\n key or limit to be enforced must also be specified, for example \n \"-il+ntk mykey\", or \"+nstl-Cc 20\". If you do not want any modes\n enforced, \"CHANMODE <channel> +\" will clear the list.\nViewing the enforced modes requires operator (+o) access on the named channel.\nUpdating the enforced modes requires master (+m) access on the named channel.\nNote: unlike similar commands that work on flags, specifying modes REPLACES\nthe list of modes to be enforced rather than changing the existing list. This \nis because - modes are valid as well as + modes. Thus whenever you specify \nthe modes argument you must provide the complete list of desired modes each\ntime.\nNote: if autolimit is enabled (see CHANFLAGS) it will cause a +l limit mode\nto be enforced, with the value updating periodically as users join and leave.\nThis +l forcing cannot be changed or overridden without disabling the autolimit\nfunction using the CHANFLAGS command.\n");
chanservaddcommand("channelcomment", QCMD_OPER, 2, csc_dochannelcomment, "Shows or changes the staff comment for a channel.", "");
+ chanservaddcommand("chanophistory", QCMD_AUTHED, 1, csc_dochanophistory, "Displays a list of who has been opped on a channel recently with account names.", "Usage: CHANOPHISTORY <channel>\nDisplays a list of users who have recently been opped on a channel by the\nservice, along with the account name responsible for the opping. Usually\nthis is the account the user being opped was using, but in the case of the \nOP command being used to op other users, the account used by the user issuing\nthe OP command will be shown. Where:\nchannel - the channel to use\nCHANOPHISTORY requires operator (+o) access on the named channel.\n");
chanservaddcommand("chanstat", QCMD_AUTHED, 1, csc_dochanstat, "Displays channel activity statistics.", "Usage: CHANSTAT <channel>\nShows some statistics about a channel, including total number of joins and \nmaximum channel size. Two sets of statistics are displayed, a lifetime\ncounter, and a trip meter counter which can be reset. Where:\nchannel - channel to display statistics for.\nCHANSTAT requires master (+m) access on the named channel.\n");
chanservaddcommand("chantype", QCMD_OPER, 2, csc_dochantype, "Shows or changes a channel's type.", "");
chanservaddcommand("clearchan", QCMD_AUTHED, 1, csc_doclearchan, "Removes all modes from a channel.", "Usage: CLEARCHAN <channel>\nRemoves all channel modes (such as keys, limits, invite only, etc.) from\nthe named channel. Modes being enfored (see CHANMODE) will not be removed.\nWhere:\nchannel - channel to remove modes from\nCLEARCHAN requires master (+m) access on the named channel.\n");
chanservremovecommand("chanlevhistory", csc_dochanlevhistory);
chanservremovecommand("chanmode", csc_dochanmode);
chanservremovecommand("channelcomment", csc_dochannelcomment);
+ chanservremovecommand("chanophistory", csc_dochanophistory);
chanservremovecommand("chanstat", csc_dochanstat);
chanservremovecommand("chantype", csc_dochantype);
chanservremovecommand("clearchan", csc_doclearchan);
int csc_doop(void *source, int cargc, char **cargv) {
nick *sender=source, *np;
reguser *rup=getreguserfromnick(sender);
+ reguser *srup=rup;
chanindex *cip;
regchan *rcp=NULL;
regchanuser *rcup;
localsetmodeinit(&changes, ca[i], chanservnick);
localdosetmode_nick(&changes, sender, MC_OP);
localsetmodeflush(&changes,1);
+ cs_logchanop(rcp, sender->nick, rup);
}
}
}
localsetmodeinit(&changes, cip->channel, chanservnick);
localdosetmode_nick(&changes, sender, MC_OP);
localsetmodeflush(&changes,1);
+ cs_logchanop(rcp, sender->nick, srup);
chanservstdmessage(sender, QM_DONE);
return CMD_OK;
bufpos += sprintf(buf+bufpos,"%s%s",bufpos?", ":"",np->nick);
localdosetmode_nick(&changes, np, MC_OP);
+ cs_logchanop(rcp, np->nick, srup);
}
if (donotice && bufpos) {
#define DUMPINTERVAL 300
#define EMAILLEN 60
#define CHANTYPES 8
+#define CHANOPHISTORY 10
/* Suspension and g-line hit count limits */
#define MAXGLINEUSERS 50
#define QM_BADRESETCODE 167
#define QM_CHALLENGEDDEPRECATED 168
#define QM_CHANLEVSUMMARY 169
+#define QM_NOACCESSONUSER 170
+#define QM_NOCHANOPHISTORY 171
+#define QM_CHANOPHISTORYHEADER 172
/* List of privileged operations */
struct regchanuser *regusers[REGCHANUSERHASHSIZE];
struct regban *bans; /* List of bans on the channel */
+
+ char chanopnicks[CHANOPHISTORY][NICKLEN+1]; /* Last CHANOPHISTORY ppl to get ops */
+ unsigned int chanopaccts[CHANOPHISTORY]; /* Which account was responsible for each one */
+ short chanoppos; /* Position in the array */
} regchan;
/* Registered user */
int checkresponse(reguser *rup, const unsigned char *entropy, const char *response, CRAlgorithm algorithm);
int checkhashpass(reguser *rup, const char *junk, const char *hash);
flag_t cs_sanitisechanlev(flag_t flags);
-
typedef int (*UnbanFN)(void *arg, struct chanban *ban);
void cs_unbanfn(nick *sender, chanindex *cip, UnbanFN fn, void *arg, int removepermbans);
+void cs_logchanop(regchan *rcp, char *nick, reguser *rup);
/* chanservstdcmds.c */
int cs_doshowcommands(void *source, int cargc, char **cargv);
/* Auto op */
if (!isopped) {
modes |= MC_OP;
+ cs_logchanop(rcp, np->nick, rup);
}
} else {
/* Not auto op; deop them if they are opped and are not allowed them */
(rcup && CUIsDeny(rcup)))
localdosetmode_nick(changes, np, MC_DEOP);
} else {
- if (rcup && (CUIsProtect(rcup) || CIsProtect(rcp)) && CUIsOp(rcup) && !CUIsDeny(rcup))
+ if (rcup && (CUIsProtect(rcup) || CIsProtect(rcp)) && CUIsOp(rcup) && !CUIsDeny(rcup)) {
localdosetmode_nick(changes, np, MC_OP);
+ cs_logchanop(rcp, np->nick, rcup->user);
+ }
}
if (cp->users->content[i] & CUMODE_VOICE) {
localdosetmode_nick(&changes, np, MC_DEOP);
} else {
if (!CUIsDeny(rcup) && CUIsOp(rcup) &&
- (CUIsProtect(rcup) || CIsProtect(rcup->chan) || CUIsAutoOp(rcup)))
+ (CUIsProtect(rcup) || CIsProtect(rcup->chan) || CUIsAutoOp(rcup))) {
localdosetmode_nick(&changes, np, MC_OP);
+ cs_logchanop(rcup->chan, np->nick, rup);
+ }
}
if (*lp & CUMODE_VOICE) {
localsetmodeflush(&changes,1);
}
}
+
+/* Add entry to channel op history when someone gets ops. */
+void cs_logchanop(regchan *rcp, char *nick, reguser *rup) {
+ strncpy(rcp->chanopnicks[rcp->chanoppos], nick, NICKLEN);
+ rcp->chanopnicks[rcp->chanoppos][NICKLEN]='\0';
+ rcp->chanopaccts[rcp->chanoppos]=rup->ID;
+ rcp->chanoppos=(rcp->chanoppos+1)%CHANOPHISTORY;
+}
void loadsomechannels(PGconn *dbconn, void *arg) {
PGresult *pgres;
regchan *rcp;
- int i,num;
+ int i,j,num;
chanindex *cip;
time_t now=time(NULL);
if (CIsAutoLimit(rcp))
rcp->limit=0;
+
+ for (j=0;j<CHANOPHISTORY;j++) {
+ rcp->chanopnicks[j][0]='\0';
+ rcp->chanopaccts[j]=0;
+ }
+ rcp->chanoppos=0;
}
PQclear(pgres);
/* 43 */ "%s is authed as %s. Cannot reclaim nick.",
/* 44 */ "Username or password incorrect.",
/* 45 */ "You are now logged in as %s.",
- /* 46 */ "User %s created, account information will be sent to \"%s\"",
+ /* 46 */ "User %s created successfully.\nInformation about how to access and use your new account will be sent to your email address, %s.\nIf you do not see an email soon be sure to check your spam folder.",
/* 47 */ "A user with that name already exists. If you have said HELLO before, use AUTH to\nlogin, or REQUESTPASSWORD if you have forgotten the password. Otherwise,\nplease change your nick and try again.",
/* 48 */ "You're already on %s.",
/* 49 */ "You're not on %s.",
/* 166*/ "Your old account settings have been restored, please check your email.",
/* 167*/ "Bad reset code.",
/* 168*/ "WARNING: the selected algorithm is legacy functionality and is likely to be removed in the near future.",
- /* 169*/ "Total: %d (owner: %d, master: %d, op: %d, voice: %d, known: %d, ban: %d)."
+ /* 169*/ "Total: %d (owner: %d, master: %d, op: %d, voice: %d, known: %d, ban: %d).",
+ /* 170*/ "You do not have sufficient access to use %s on %s.",
+ /* 171*/ "No channel op events have been logged for %s.",
+ /* 172*/ "Channel op events on %s:\nNickname Account used",
};
void initmessages() {
if (!rup)
return CMD_ERROR;
- if (cargc<1) {
- chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "userflags");
- return CMD_ERROR;
- }
-
- if (*cargv[0]!='+' && *cargv[0]!='-') {
+ if (cargc>0 && (*cargv[0]!='+' && *cargv[0]!='-')) {
arg++;
/* If the first char isn't a "change" character, it must specify a target */
return CMD_ERROR;
if (target!=rup && !cs_privcheck(QPRIV_VIEWUSERFLAGS, sender)) {
- chanservstdmessage(sender, QM_NOACCESS, "userflags");
+ chanservstdmessage(sender, QM_NOACCESSONUSER, "userflags", cargv[0]);
return CMD_ERROR;
}
} else {
if (cargc>arg) {
/* OK, now we have a changestring.. */
if (target!=rup && !cs_privcheck(QPRIV_CHANGEUSERFLAGS, sender)) {
- chanservstdmessage(sender, QM_NOACCESS, "userflags");
+ /* Safe to use cargv[0] because if target != rup then first arg must have been the target name */
+ chanservstdmessage(sender, QM_NOACCESSONUSER, "userflags", cargv[0]);
return CMD_ERROR;
}