0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 52,53,54,55,56,57,58,59,60,61, 0, 0, 0, 0, 0, 0,
+ 52,53,54,55,56,57,58,59,60,61, 0, 0, 0, 0, 0, 0,
0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
15,16,17,18,19,20,21,22,23,24,25,62, 0,63, 0, 0,
0,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
41,42,43,44,45,46,47,48,49,50,51, 0, 0, 0, 0, 0
};
+static const unsigned char ctype[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
+ 0,10,11,12,13,14,15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,10,11,12,13,14,15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
unsigned long int
base64toint(const char* s, int count)
{
return buf;
}
+unsigned int
+irc_ntop(char *output, unsigned int out_size, const irc_in_addr_t *addr)
+{
+ static const char hexdigits[] = "0123456789abcdef";
+ unsigned int pos;
+
+ assert(output);
+ assert(addr);
+
+ if (irc_in_addr_is_ipv4(*addr)) {
+ unsigned int ip4;
+
+ ip4 = (ntohs(addr->in6[6]) << 16) | ntohs(addr->in6[7]);
+ pos = snprintf(output, out_size, "%u.%u.%u.%u", (ip4 >> 24), (ip4 >> 16) & 255, (ip4 >> 8) & 255, ip4 & 255);
+ } else {
+ unsigned int part, max_start, max_zeros, curr_zeros, ii;
+
+ /* Find longest run of zeros. */
+ for (max_start = max_zeros = curr_zeros = ii = 0; ii < 8; ++ii) {
+ if (!addr->in6[ii])
+ curr_zeros++;
+ else if (curr_zeros > max_zeros) {
+ max_start = ii - curr_zeros;
+ max_zeros = curr_zeros;
+ curr_zeros = 0;
+ }
+ }
+ if (curr_zeros > max_zeros) {
+ max_start = ii - curr_zeros;
+ max_zeros = curr_zeros;
+ }
+
+ /* Print out address. */
+#define APPEND(CH) do { if (pos < out_size) output[pos] = (CH); pos++; } while (0)
+ for (pos = 0, ii = 0; ii < 8; ++ii) {
+ if ((max_zeros > 0) && (ii == max_start)) {
+ if (ii == 0)
+ APPEND(':');
+ APPEND(':');
+ ii += max_zeros - 1;
+ continue;
+ }
+ part = ntohs(addr->in6[ii]);
+ if (part >= 0x1000)
+ APPEND(hexdigits[part >> 12]);
+ if (part >= 0x100)
+ APPEND(hexdigits[(part >> 8) & 15]);
+ if (part >= 0x10)
+ APPEND(hexdigits[(part >> 4) & 15]);
+ APPEND(hexdigits[part & 15]);
+ if (ii < 7)
+ APPEND(':');
+ }
+#undef APPEND
+ output[pos < out_size ? pos : out_size - 1] = '\0';
+ }
+
+ return pos;
+}
+
+unsigned int
+irc_ntop_mask(char *output, unsigned int out_size, const irc_in_addr_t *addr, unsigned char bits)
+{
+ char base_addr[IRC_NTOP_MAX_SIZE];
+ int len;
+
+ if (bits >= 128)
+ return irc_ntop(output, out_size, addr);
+ if (!irc_ntop(base_addr, sizeof(base_addr), addr))
+ return 0;
+ len = snprintf(output, out_size, "%s/%d", base_addr, bits);
+ if ((unsigned int)len >= out_size)
+ return 0;
+ return len;
+}
+
+static unsigned int
+irc_pton_ip4(const char *input, unsigned char *pbits, uint32_t *output)
+{
+ unsigned int dots = 0, pos = 0, part = 0, ip = 0, bits = 32;
+
+ /* Intentionally no support for bizarre IPv4 formats (plain
+ * integers, octal or hex components) -- only vanilla dotted
+ * decimal quads, optionally with trailing /nn.
+ */
+ if (input[0] == '.')
+ return 0;
+ while (1) switch (input[pos]) {
+ default:
+ if (dots < 3)
+ return 0;
+ out:
+ ip |= part << (24 - 8 * dots++);
+ *output = htonl(ip);
+ if (pbits)
+ *pbits = bits;
+ return pos;
+ case '.':
+ if (input[++pos] == '.')
+ return 0;
+ ip |= part << (24 - 8 * dots++);
+ part = 0;
+ if (input[pos] == '*') {
+ while (input[++pos] == '*') ;
+ if (input[pos] != '\0')
+ return 0;
+ if (pbits)
+ *pbits = dots * 8;
+ *output = htonl(ip);
+ return pos;
+ }
+ break;
+ case '/':
+ if (!pbits || !isdigit(input[pos + 1]))
+ return 0;
+ for (bits = 0; isdigit(input[++pos]); )
+ bits = bits * 10 + input[pos] - '0';
+ if (bits > 32)
+ return 0;
+ goto out;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ part = part * 10 + input[pos++] - '0';
+ if (part > 255)
+ return 0;
+ break;
+ }
+}
+
+unsigned int
+irc_pton(irc_in_addr_t *addr, unsigned char *bits, const char *input)
+{
+ const char *part_start = NULL;
+ char *colon;
+ char *dot;
+ unsigned int part = 0, pos = 0, ii = 0, cpos = 8;
+
+ assert(input);
+ memset(addr, 0, sizeof(*addr));
+ colon = strchr(input, ':');
+ dot = strchr(input, '.');
+
+ if (colon && (!dot || (dot > colon))) {
+ /* Parse IPv6, possibly like ::127.0.0.1.
+ * This is pretty straightforward; the only trick is borrowed
+ * from Paul Vixie (BIND): when it sees a "::" continue as if
+ * it were a single ":", but note where it happened, and fill
+ * with zeros afterwards.
+ */
+ if (input[pos] == ':') {
+ if ((input[pos+1] != ':') || (input[pos+2] == ':'))
+ return 0;
+ cpos = 0;
+ pos += 2;
+ part_start = input + pos;
+ }
+ while (ii < 8) switch (input[pos]) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ part = (part << 4) | (ctype[(unsigned char)input[pos++]] & 15);
+ if (part > 0xffff)
+ return 0;
+ break;
+ case ':':
+ part_start = input + ++pos;
+ if (input[pos] == '.')
+ return 0;
+ addr->in6[ii++] = htons(part);
+ part = 0;
+ if (input[pos] == ':') {
+ if (cpos < 8)
+ return 0;
+ cpos = ii;
+ }
+ break;
+ case '.': {
+ uint32_t ip4;
+ unsigned int len;
+ len = irc_pton_ip4(part_start, bits, &ip4);
+ if (!len || (ii > 6))
+ return 0;
+ memcpy(addr->in6 + ii, &ip4, sizeof(ip4));
+ if (bits)
+ *bits += 96;
+ ii += 2;
+ pos = part_start + len - input;
+ goto finish;
+ }
+ case '/':
+ if (!bits || !isdigit(input[pos + 1]))
+ return 0;
+ addr->in6[ii++] = htons(part);
+ for (part = 0; isdigit(input[++pos]); )
+ part = part * 10 + input[pos] - '0';
+ if (part > 128)
+ return 0;
+ *bits = part;
+ goto finish;
+ case '*':
+ while (input[++pos] == '*') ;
+ if (input[pos] != '\0' || cpos < 8)
+ return 0;
+ if (bits)
+ *bits = ii * 16;
+ return pos;
+ default:
+ addr->in6[ii++] = htons(part);
+ if (cpos == 8 && ii < 8)
+ return 0;
+ if (bits)
+ *bits = 128;
+ goto finish;
+ }
+ finish:
+ /* Shift stuff after "::" up and fill middle with zeros. */
+ if (cpos < 8) {
+ unsigned int jj;
+ for (jj = 0; jj < ii - cpos; jj++)
+ addr->in6[7 - jj] = addr->in6[ii - jj - 1];
+ for (jj = 0; jj < 8 - ii; jj++)
+ addr->in6[cpos + jj] = 0;
+ }
+ } else if (dot) {
+ uint32_t ip4;
+ pos = irc_pton_ip4(input, bits, &ip4);
+ if (pos) {
+/* glibc's htons() macro is not -Wshadow-safe. */
+#undef htons
+ addr->in6[5] = htons(65535);
+ addr->in6[6] = htons(ntohl(ip4) >> 16);
+ addr->in6[7] = htons(ntohl(ip4) & 65535);
+ if (bits)
+ *bits += 96;
+ }
+ } else if (input[0] == '*') {
+ while (input[++pos] == '*') ;
+ if (input[pos] != '\0')
+ return 0;
+ if (bits)
+ *bits = 0;
+ }
+ return pos;
+}
+
+const char *irc_ntoa(const irc_in_addr_t *addr)
+{
+ static char ntoa[IRC_NTOP_MAX_SIZE];
+ irc_ntop(ntoa, sizeof(ntoa), addr);
+ return ntoa;
+}
+
+unsigned int
+irc_check_mask(const irc_in_addr_t *check, const irc_in_addr_t *mask, unsigned char bits)
+{
+ unsigned int ii;
+
+ for (ii = 0; (ii < 8) && (bits > 16); bits -= 16, ++ii)
+ if (check->in6[ii] != mask->in6[ii])
+ return 0;
+ if (ii < 8 && bits > 0
+ && (ntohs(check->in6[ii] ^ mask->in6[ii]) >> (16 - bits)))
+ return 0;
+ return 1;
+}
+
static char irc_tolower[256];
#undef tolower
#define tolower(X) irc_tolower[(unsigned char)(X)]
return NULL;
}
+char *
+ircstrlower(char *str) {
+ size_t ii;
+ for (ii = 0; str[ii] != '\0'; ++ii)
+ str[ii] = tolower(str[ii]);
+ return str;
+}
+
int
split_line(char *line, int irc_colon, int argv_size, char *argv[])
{
int argc = 0;
int n;
while (*line && (argc < argv_size)) {
- while (*line == ' ')
+ while (*line == ' ')
*line++ = 0;
- if (*line == ':' && irc_colon && argc > 0) {
- /* the rest is a single parameter */
- argv[argc++] = line + 1;
- break;
- }
+ if (*line == ':' && irc_colon && argc > 0) {
+ /* the rest is a single parameter */
+ argv[argc++] = line + 1;
+ break;
+ }
if (!*line)
break;
- argv[argc++] = line;
- if (argc >= argv_size)
+ argv[argc++] = line;
+ if (argc >= argv_size)
break;
- while (*line != ' ' && *line)
+ while (*line != ' ' && *line)
line++;
}
#ifdef NDEBUG
if (*m == '*')
{
while (*m == '*')
- m++;
+ m++;
wild = 1;
ma = m;
na = n;
if (!*m)
{
if (!*n)
- return 0;
+ return 0;
for (m--; (m > old_mask) && (*m == '?'); m--)
- ;
+ ;
if ((*m == '*') && (m > old_mask) && (m[-1] != '\\'))
- return 0;
+ return 0;
if (!wild)
- return 1;
+ return 1;
m = ma;
/* Added to `mmatch' : Because '\?' and '\*' now is one character: */
if ((*na == '\\') && ((na[1] == '*') || (na[1] == '?')))
- ++na;
+ ++na;
n = ++na;
}
else if (!*n)
{
while (*m == '*')
- m++;
+ m++;
return (*m != 0);
}
if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?')))
* cases upfront (which took 2 hours!)).
*/
if ((*m == '*' && !mq) ||
- ((!mq || nq) && tolower(*m) == tolower(*n)) ||
- (*m == '?' && !mq && (*n != '*' || nq)))
+ ((!mq || nq) && tolower(*m) == tolower(*n)) ||
+ (*m == '?' && !mq && (*n != '*' || nq)))
{
if (*m)
- m++;
+ m++;
if (*n)
- n++;
+ n++;
}
else
{
if (!wild)
- return 1;
+ return 1;
m = ma;
/* Added to `mmatch' : Because '\?' and '\*' now is one character: */
if ((*na == '\\') && ((na[1] == '*') || (na[1] == '?')))
- ++na;
+ ++na;
n = ++na;
}
return 0;
m = m_tmp;
n = ++n_tmp;
+ if (!*n)
+ return 0;
break;
case '\\':
m++;
/* allow escaping to force capitalization */
if (*m++ != *n++)
- return 0;
+ goto backtrack;
break;
case '*': case '?':
for (star_p = 0; ; m++) {
extern const char *hidden_host_suffix;
int
-user_matches_glob(struct userNode *user, const char *orig_glob, int include_nick)
+user_matches_glob(struct userNode *user, const char *orig_glob, int flags)
{
+ irc_in_addr_t mask;
char *glob, *marker;
+ unsigned char mask_bits;
/* Make a writable copy of the glob */
glob = alloca(strlen(orig_glob)+1);
strcpy(glob, orig_glob);
/* Check the nick, if it's present */
- if (include_nick) {
+ if (flags & MATCH_USENICK) {
if (!(marker = strchr(glob, '!'))) {
- log_module(MAIN_LOG, LOG_ERROR, "user_matches_glob(\"%s\", \"%s\", %d) called, and glob doesn't include a '!'", user->nick, orig_glob, include_nick);
+ log_module(MAIN_LOG, LOG_ERROR, "user_matches_glob(\"%s\", \"%s\", %d) called, and glob doesn't include a '!'", user->nick, orig_glob, flags);
return 0;
}
*marker = 0;
}
/* Check the ident */
if (!(marker = strchr(glob, '@'))) {
- log_module(MAIN_LOG, LOG_ERROR, "user_matches_glob(\"%s\", \"%s\", %d) called, and glob doesn't include an '@'", user->nick, orig_glob, include_nick);
+ log_module(MAIN_LOG, LOG_ERROR, "user_matches_glob(\"%s\", \"%s\", %d) called, and glob doesn't include an '@'", user->nick, orig_glob, flags);
return 0;
}
*marker = 0;
- if (!match_ircglob(user->ident, glob))
+ if (((IsFakeIdent(user) && IsHiddenHost(user) && (flags & MATCH_VISIBLE)) || !match_ircglob(user->ident, glob)) &&
+ !(IsFakeIdent(user) && match_ircglob(user->fakeident, glob)))
return 0;
glob = marker + 1;
- /* If it might be an IP glob, test that. */
- if (!glob[strspn(glob, "0123456789./*?")]
- && match_ircglob(inet_ntoa(user->ip), glob))
- return 1;
/* Check for a fakehost match. */
if (IsFakeHost(user) && match_ircglob(user->fakehost, glob))
- return 1;
+ return 1;
/* Check for an account match. */
if (hidden_host_suffix && user->handle_info) {
char hidden_host[HOSTLEN+1];
if (match_ircglob(hidden_host, glob))
return 1;
}
+ /* If only matching the visible hostnames, bail early. */
+ if ((flags & MATCH_VISIBLE) && IsHiddenHost(user)
+ && (IsFakeHost(user) || (hidden_host_suffix && user->handle_info)))
+ return 0;
+ /* If it might be an IP glob, test that. */
+ if (irc_pton(&mask, &mask_bits, glob)
+ && irc_check_mask(&user->ip, &mask, mask_bits))
+ return 1;
/* None of the above; could only be a hostname match. */
return match_ircglob(user->hostname, glob);
}
mask = input;
while(*input++ != '!')
{
- length++;
+ length++;
}
if(length > NICKLEN)
{
- mask += NICKLEN;
- *mask++ = '!';
+ mask += NICKLEN;
+ *mask++ = '!';
- /* This flag is used to indicate following parts should
- be shifted. */
- flag = 1;
+ /* This flag is used to indicate following parts should
+ be shifted. */
+ flag = 1;
}
else
{
- mask = input;
+ mask = input;
}
/* The ident and host must be truncated at the beginning and
start = input;
while(*input++ != '@')
{
- length++;
+ length++;
}
if(length > USERLEN || flag)
{
- if(length > USERLEN)
- {
- start = input - USERLEN;
- *mask++ = '*';
- }
- while(*start != '@')
- {
- *mask++ = *start++;
- }
- *mask++ = '@';
-
- flag = 1;
+ if(length > USERLEN)
+ {
+ start = input - USERLEN;
+ *mask++ = '*';
+ }
+ while(*start != '@')
+ {
+ *mask++ = *start++;
+ }
+ *mask++ = '@';
+
+ flag = 1;
}
else
{
- mask = input;
+ mask = input;
}
length = 0;
start = input;
while(*input++)
{
- length++;
+ length++;
}
if(length > HOSTLEN || flag)
{
- if(length > HOSTLEN)
- {
- start = input - HOSTLEN;
- *mask++ = '*';
- }
- while(*start)
- {
- *mask++ = *start++;
- }
- *mask = '\0';
+ if(length > HOSTLEN)
+ {
+ start = input - HOSTLEN;
+ *mask++ = '*';
+ }
+ while(*start)
+ {
+ *mask++ = *start++;
+ }
+ *mask = '\0';
}
return output;
/* process the string, resetting the count if we find a unit character */
while ((c = *interval++)) {
- if (isdigit((int)c)) {
- partial = partial*10 + c - '0';
- } else {
- seconds += TypeLength(c) * partial;
- partial = 0;
- }
+ if (isdigit((int)c)) {
+ partial = partial*10 + c - '0';
+ } else if (strchr("yMwdhms", c)) {
+ seconds += TypeLength(c) * partial;
+ partial = 0;
+ } else {
+ return 0;
+ }
}
/* assume the last chunk is seconds (the normal case) */
return seconds + partial;
return accum + partial;
}
-int
-parse_ipmask(const char *str, struct in_addr *addr, unsigned long *mask)
-{
- int accum, pos;
- unsigned long t_a, t_m;
-
- t_a = t_m = pos = 0;
- if (addr)
- addr->s_addr = htonl(t_a);
- if (mask)
- *mask = t_m;
- while (*str) {
- if (!isdigit(*str))
- return 0;
- accum = 0;
- do {
- accum = (accum * 10) + *str++ - '0';
- } while (isdigit(*str));
- if (accum > 255)
- return 0;
- t_a = (t_a << 8) | accum;
- t_m = (t_m << 8) | 255;
- pos += 8;
- if (*str == '.') {
- str++;
- while (*str == '*') {
- str++;
- if (*str == '.') {
- t_a <<= 8;
- t_m <<= 8;
- pos += 8;
- str++;
- } else if (*str == 0) {
- t_a <<= 32 - pos;
- t_m <<= 32 - pos;
- pos = 32;
- goto out;
- } else
- return 0;
- }
- } else if (*str == '/') {
- int start = pos;
- accum = 0;
- do {
- accum = (accum * 10) + *str++ - '0';
- } while (isdigit(*str));
- while (pos < start+accum && pos < 32) {
- t_a = (t_a << 1) | 0;
- t_m = (t_m << 1) | 1;
- pos++;
- }
- if (pos != start+accum)
- return 0;
- } else if (*str == 0)
- break;
- else
- return 0;
- }
-out:
- if (pos != 32)
- return 0;
- if (addr)
- addr->s_addr = htonl(t_a);
- if (mask)
- *mask = t_m;
- return 1;
-}
-
char *
unsplit_string(char *set[], unsigned int max, char *dest)
{
}
char *
-intervalString(char *output, time_t interval, struct handle_info *hi)
+intervalString(char *output, unsigned long interval, struct handle_info *hi)
{
static const struct {
const char *msg_single;
const char *msg_plural;
- long length;
+ unsigned long length;
} unit[] = {
{ "MSG_YEAR", "MSG_YEARS", 365 * 24 * 60 * 60 },
{ "MSG_WEEK", "MSG_WEEKS", 7 * 24 * 60 * 60 },
if(!interval)
{
msg = language_find_message(lang, "MSG_0_SECONDS");
- return strcpy(output, msg);
+ return strcpy(output, msg);
}
for (type = 0, words = pos = 0;
interval && (words < 2) && (type < ArrayLength(unit));
type++) {
- if (interval < unit[type].length)
+ if (interval < unit[type].length)
continue;
count = interval / unit[type].length;
interval = interval % unit[type].length;