*
* This file is part of x3.
*
- * srvx is free software; you can redistribute it and/or modify
+ * x3 is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
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) {
+ unsigned int ip4;
+ pos = irc_pton_ip4(input, bits, &ip4);
+ if (pos) {
+ 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)]
m++;
/* allow escaping to force capitalization */
if (*m++ != *n++)
- return 0;
+ goto backtrack;
break;
case '*': case '?':
for (star_p = 0; ; m++) {
return(match_ircglob("abcdefghijklmnopqrstuv!frcmbghilnrtoasde@apdic.yfa.dsfsdaffsdasfdasfd.abcdefghijklmnopqrstuvwxyz.asdfasfdfsdsfdasfda.ydfbe", mask));
}
-int user_matches_glob(struct userNode *user, const char *orig_glob, int include_nick)
-{
- /* A new glob function, the old one had many false positives.
- * look at IsSetHost(user) etc and include_nick, build a nick!user@host string
- * from user and save it in a variable. Compare with match_ircglob() and
- * return the results. Match any of the possible user@host combos (ugh) -Rubin
- */
- char *matchstr_user;
- char *matchstr_host;
- char *matchstr_full = NULL;
-
- if(IsSetHost(user)) /* S: line sethosts */
- {
- /* Grab host and user from sethost instead of real host */
- char *buff;
- buff = alloca(strlen(user->sethost) + 1);
- strcpy(buff, user->sethost);
- matchstr_user = mysep(&buff, "@");
- matchstr_host = mysep(&buff, "@");
-
- matchstr_full = alloca(strlen(user->nick) + strlen(matchstr_user) + strlen(matchstr_host) + 4);
- if(include_nick)
- sprintf(matchstr_full, "%s!%s@%s", user->nick, matchstr_user, matchstr_host);
- else
- sprintf(matchstr_full, "%s@%s", matchstr_user, matchstr_host);
- if(match_ircglob(matchstr_full, orig_glob))
- return(1);
- }
- else if(IsFakeHost(user)) /* Fakehost */
- {
- matchstr_full = alloca(strlen(user->nick) + strlen(user->ident) + strlen(user->fakehost) + 4);
- if(include_nick)
- sprintf(matchstr_full, "%s!%s@%s", user->nick, user->ident, user->fakehost);
- else
- sprintf(matchstr_full, "%s@%s", user->ident, user->fakehost);
- if(match_ircglob(matchstr_full, orig_glob))
- return(1);
- }
- else if(hidden_host_suffix && user->handle_info) /* name.users.network.org host */
- {
- matchstr_host = alloca(strlen(user->handle_info->handle) + strlen(hidden_host_suffix) + 2);
- sprintf(matchstr_host, "%s.%s", user->handle_info->handle, hidden_host_suffix);
- matchstr_user = user->ident;
-
- matchstr_full = alloca(strlen(user->nick) + strlen(user->ident) + strlen(matchstr_host) + 4);
- if(include_nick)
- sprintf(matchstr_full, "%s!%s@%s", user->nick, user->ident, matchstr_host);
- else
- sprintf(matchstr_full, "%s@%s", user->ident, matchstr_host);
- if(match_ircglob(matchstr_full, orig_glob))
- return(1);
- }
-
- /* Check normal hostname */
- matchstr_full = alloca(strlen(user->nick) + strlen(user->ident) + strlen(user->hostname) + 4);
- if(include_nick)
- sprintf(matchstr_full, "%s!%s@%s", user->nick, user->ident, user->hostname);
- else
- sprintf(matchstr_full, "%s@%s", user->ident, user->hostname);
- if(match_ircglob(matchstr_full, orig_glob))
- return(1);
-
- /* Check IP hostname (could skip this if same as above?)*/
- matchstr_host = inet_ntoa(user->ip);
- matchstr_full = alloca(strlen(user->nick) + strlen(user->ident) + strlen(matchstr_host) + 4);
- if(include_nick)
- sprintf(matchstr_full, "%s!%s@%s", user->nick, user->ident, matchstr_host);
- else
- sprintf(matchstr_full, "%s@%s", user->ident, matchstr_host);
- if(match_ircglob(matchstr_full, orig_glob))
- return(1);
-
- return(0); /* Didnt match anything */
-}
-
int
-user_matches_glob_broken(struct userNode *user, const char *orig_glob, int include_nick)
+user_matches_glob(struct userNode *user, const char *orig_glob, int flags)
{
char *glob, *marker;
- char *setident = NULL, *sethostname = NULL; // sethost - reed/apples
/* 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;
-
- // sethost - reed/apples
- if (IsSetHost(user)) {
- setident = alloca(strcspn(user->sethost, "@")+2);
- safestrncpy(setident, user->sethost, strcspn(user->sethost, "@")+1);
- sethostname = strchr(user->sethost, '@') + 1;
- }
-
- if (!match_ircglob(user->ident, glob) && (IsSetHost(user) && !match_ircglob(setident, glob)))
- return 0;
+ if (!match_ircglob(user->ident, 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;
- if (IsSetHost(user) && match_ircglob(sethostname, glob))
+
+ /* Check for a sethost (S:lines) */
+ if (IsSetHost(user) && match_ircglob(user->sethost, glob))
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 (!glob[strspn(glob, "0123456789./*?")]
+ && match_ircglob(irc_ntoa(&user->ip), glob))
+ return 1;
/* None of the above; could only be a hostname match. */
return match_ircglob(user->hostname, glob);
}
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)
{
return(buf);
}
+char* x3_strtok(char **save, char *str, char *fs)
+{
+ char *pos = *save; /* keep last position across calls */
+ char *tmp;
+
+ if (str)
+ pos = str; /* new string scan */
+
+ while (pos && *pos && strchr(fs, *pos) != NULL)
+ pos++; /* skip leading separators */
+
+ if (!pos || !*pos)
+ return (pos = *save = NULL); /* string contains only sep's */
+
+ tmp = pos; /* now, keep position of the token */
+
+ while (*pos && strchr(fs, *pos) == NULL)
+ pos++; /* skip content of the token */
+
+ if (*pos)
+ *pos++ = '\0'; /* remove first sep after the token */
+ else
+ pos = NULL; /* end of string */
+
+ *save = pos;
+ return (tmp);
+}
+
+int valid_email(const char *email)
+{
+ unsigned int i;
+ for (i=0;i<strlen(email);i++)
+ {
+ if(!isalnum(email[i]) &&
+ email[i] != '.' &&
+ email[i] != '@' &&
+ email[i] != '-' &&
+ email[i] != '+' &&
+ email[i] != '_' )
+ return false;
+ }
+ if(strchr(email, '@') == NULL)
+ return false;
+ return true;
+}
+