--- /dev/null
+#!/usr/bin/python
+__author__ = 'Thomas Dixon'
+__license__ = 'MIT'
+
+import copy, struct, sys
+
+def new(m=None):
+ return sha256(m)
+
+class sha256(object):
+ _k = (0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2)
+ _h = (0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
+ 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19)
+ _output_size = 8
+
+ blocksize = 1
+ digest_size = 32
+
+ def __init__(self, m=None):
+ self._buffer = ''
+ self._counter = 0
+
+ if m is not None:
+ if type(m) is not str:
+ raise TypeError, '%s() argument 1 must be string, not %s' % (self.__class__.__name__, type(m).__name__)
+ self.update(m)
+
+ def _rotr(self, x, y):
+ return ((x >> y) | (x << (32-y))) & 0xFFFFFFFF
+
+ def _sha256_process(self, c):
+ w = [0]*64
+ w[0:15] = struct.unpack('!16L', c)
+
+ for i in range(16, 64):
+ s0 = self._rotr(w[i-15], 7) ^ self._rotr(w[i-15], 18) ^ (w[i-15] >> 3)
+ s1 = self._rotr(w[i-2], 17) ^ self._rotr(w[i-2], 19) ^ (w[i-2] >> 10)
+ w[i] = (w[i-16] + s0 + w[i-7] + s1) & 0xFFFFFFFF
+
+ a,b,c,d,e,f,g,h = self._h
+
+ for i in range(64):
+ s0 = self._rotr(a, 2) ^ self._rotr(a, 13) ^ self._rotr(a, 22)
+ maj = (a & b) ^ (a & c) ^ (b & c)
+ t2 = s0 + maj
+ s1 = self._rotr(e, 6) ^ self._rotr(e, 11) ^ self._rotr(e, 25)
+ ch = (e & f) ^ ((~e) & g)
+ t1 = h + s1 + ch + self._k[i] + w[i]
+
+ h = g
+ g = f
+ f = e
+ e = (d + t1) & 0xFFFFFFFF
+ d = c
+ c = b
+ b = a
+ a = (t1 + t2) & 0xFFFFFFFF
+
+ self._h = [(x+y) & 0xFFFFFFFF for x,y in zip(self._h, [a,b,c,d,e,f,g,h])]
+
+ def update(self, m):
+ if not m:
+ return
+ if type(m) is not str:
+ raise TypeError, '%s() argument 1 must be string, not %s' % (sys._getframe().f_code.co_name, type(m).__name__)
+
+ self._buffer += m
+ self._counter += len(m)
+
+ while len(self._buffer) >= 64:
+ self._sha256_process(self._buffer[:64])
+ self._buffer = self._buffer[64:]
+
+ def digest(self):
+ mdi = self._counter & 0x3F
+ length = struct.pack('!Q', self._counter<<3)
+
+ if mdi < 56:
+ padlen = 55-mdi
+ else:
+ padlen = 119-mdi
+
+ r = self.copy()
+ r.update('\x80'+('\x00'*padlen)+length)
+ return ''.join([struct.pack('!L', i) for i in r._h[:self._output_size]])
+
+ def hexdigest(self):
+ return self.digest().encode('hex')
+
+ def copy(self):
+ return copy.deepcopy(self)
+
+digest_size = new().digest_size
*
* CMDNAME: chanstat
* CMDLEVEL: QCMD_AUTHED
- * CMDARGS: 1
+ * CMDARGS: 2
* CMDDESC: Displays channel activity statistics.
* CMDFUNC: csc_dochanstat
* CMDPROTO: int csc_dochanstat(void *source, int cargc, char **cargv);
- * CMDHELP: Usage: CHANSTAT <channel>
+ * CMDHELP: Usage: CHANSTAT <channel> [RESET]
* CMDHELP: Shows some statistics about a channel, including total number of joins and
* CMDHELP: maximum channel size. Two sets of statistics are displayed, a lifetime
* CMDHELP: counter, and a trip meter counter which can be reset. Where:
chanservstdmessage(sender, QM_STATSJOINS, timebuf, rcp->tripusers, rcp->tripjoins,
(float)rcp->tripjoins / ((time(NULL)-rcp->statsreset)/(3600*24)));
+
+ if (cargc>1 && !ircd_strcmp(cargv[1],"reset")) {
+ rcp->statsreset=time(NULL);
+ rcp->tripusers=0;
+ rcp->tripjoins=0;
+ chanservstdmessage(sender, QM_STATSRESET, cip->name->content);
+ csdb_updatechannel(rcp);
+ }
return CMD_OK;
}
#define QM_CHANOPHISTORYHEADER 177
#define QM_OTHERUSERAUTHEDLIMIT 178
#define QM_OTHERUSERAUTHED 179
+#define QM_STATSRESET 180
/* List of privileged operations */
/* 0 */ "Channel %s is protected by %s.",
/* 1 */ "Unknown command %s. Type SHOWCOMMANDS for a list of available commands.",
/* 2 */ "To prevent sensitive information being accidentally send to malicious users\non other networks, when using the %s command, you must use\n/msg %s@%s.",
- /* 3 */ "%s is only available to authed users.",
- /* 4 */ "%s is only available to unauthed users.",
+ /* 3 */ "%s is only available to authed users. Try AUTH to authenticate with your\naccount, or HELLO to create an account.",
+ /* 4 */ "%s is not available once you have authed.",
/* 5 */ "The following commands are available to you.\nFor more information on a specific command, type HELP <command>:",
/* 6 */ "End of list.",
/* 7 */ "Done.",
/* 62 */ "Removed registered ban %s from %s.",
/* 63 */ "Channel settings prevent %s being voiced on %s.",
/* 64 */ "Sorry, no help available for %s.",
- /* 65 */ "-Information for user %s (using account %s)-----",
- /* 66 */ "-Information for account %s-----",
+ /* 65 */ "-Information for user %s (using account %s):",
+ /* 66 */ "-Information for account %s:",
/* 67 */ "Account users : %s",
/* 68 */ "Last auth : %s",
/* 69 */ "Last user@host : %s",
/* 133*/ "#: User: Authed: Disconnected: Reason:",
/* 134*/ "Current modes on %s: %s",
/* 135*/ "Domain: Users: Flags:",
- /* 136*/ "Too many accounts exist from this email domain",
+ /* 136*/ "Sorry, no more accounts are allowed from this email domain.",
/* 137*/ "Password too weak - You need to avoid repeating characters, and have different character types (e.g. 1 number and 1 letter)",
/* 138*/ "User %s is not a master on %s - you must promote user to master status first.",
/* 139*/ "User %s is already an owner on %s.",
/* 140*/ "WARNING: This command will give COMPLETE control over %s to %s, including the ability to remove you as owner.\nIf you are sure you want to do this, type /msg Q GIVEOWNER %s #%s %s",
- /* 141*/ "Hash value incorrect.",
+ /* 141*/ "Hash value incorrect, try again.",
/* 142*/ "Showing %s for last %s.",
/* 143*/ "Change your nickname to something with none of the following characters: `~^[]{}|_\\",
/* 144*/ "Invalid digest algorithm.",
/* 149*/ "New ban would replace at least one existing ban (%s), use UNBANMASK %s first if you want to set this ban.",
/* 150*/ "A temporary ban with this mask already exists, replacing it.",
/* 151*/ "That permanent ban already exists.",
- /* 152*/ "A ban with the same mask and longer duration exists, aborting.",
- /* 153*/ "Replacing existing ban with the same mask as it has a shorter duration.",
+ /* 152*/ "That ban is already set with a longer duration.",
+ /* 153*/ "Replaced existing ban which was set with a shorter duration.",
/* 154*/ "Channel has too many user entries, aborting.",
- /* 155*/ "Channel has too many bans set, aborting.",
+ /* 155*/ "No more bans are allowed on that channel.",
/* 156*/ "Warning: not removing registered ban %s from %s.",
/* 157*/ "Sorry, the registration service is unavailable to you at this time. Please try again later.", /* a deliberately vague message */
/* 158*/ "Too many accounts exist from this email address.",
/* 176*/ "No channel op events have been logged for %s.",
/* 177*/ "Channel op events on %s:\nNickname Account used",
/* 178*/ "Warning: %s (%s@%s) attempted to auth with your password but you already had %d users authed to your account.",
- /* 179*/ "Warning: %s (%s@%s) authed with your password."
+ /* 179*/ "Warning: %s (%s@%s) authed with your password.",
+ /* 180*/ "Resettable statistics reset for %s."
};
void initmessages() {
insertcommand(ct->cmd,(CommandTree *)ct->next[oldcharindex],depth+1);
}
ct->cmd=c;
- ct->final=&(c->command->content[depth]);
+ /* Use a static NUL string rather than the allocated one if possible. */
+ if (c->command->length < depth)
+ ct->final=&(c->command->content[depth]);
+ else
+ ct->final="";
return 0;
} else {
if ((ct->cmd!=NULL) && (ct->final[0]!='\0')) {
if(c->help)
free(c->help);
free(c);
+
+ /* We need to regenerate the final pointer if needed;
+ * if ct->cmd is still pointing to a command it has the same name.
+ * Otherwise we should clear it.*/
+ if (ct->cmd)
+ ct->final=&(ct->cmd->command->content[depth]);
+ else
+ ct->final="";
+
return 0;
}
}