*
* 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
+ * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
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) {
+ 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)]
+void
+irc_strtolower(char *str) {
+ char *p;
+ for(p = str;*p;p++) {
+ *p = tolower(*p);
+ }
+}
+
int
irccasecmp(const char *stra, const char *strb) {
+ if (!stra)
+ return -1;
+ if (!strb)
+ return 1;
while (*stra && (tolower(*stra) == tolower(*strb)))
stra++, strb++;
return tolower(*stra) - tolower(*strb);
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[])
{
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++) {
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)
+int
+user_matches_glob(struct userNode *user, const char *orig_glob, int flags, int shared)
{
- /* 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;
+ char *tmpglob, *glob, *marker;
+ char exttype = 0;
+ int extreverse = 0, is_extended = 0, match = 0, banned = 0;
+ unsigned int count, n;
+ struct modeNode *mn;
+ struct chanNode *channel;
+ struct banNode *ban;
- 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;
+ /* Make a writable copy of the glob */
+ glob = alloca(strlen(orig_glob)+1);
+ strcpy(glob, orig_glob);
- 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);
- }
+ /* Extended bans */
+ tmpglob = alloca(strlen(orig_glob)+1);
+ tmpglob = strdup(orig_glob);
- /* 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);
+ if (*tmpglob == '~') {
+ tmpglob++; /* get rid of the ~ */
- return(0); /* Didnt match anything */
-}
+ if (*tmpglob == '!') {
+ extreverse = 1;
+ tmpglob++; /* get rid of the ! */
+ }
-int
-user_matches_glob_broken(struct userNode *user, const char *orig_glob, int include_nick)
-{
- char *glob, *marker;
- char *setident = NULL, *sethostname = NULL; // sethost - reed/apples
+ exttype = *tmpglob;
+ tmpglob++; /* get rid of the type */
+
+ if (*tmpglob == ':') {
+ is_extended = 1;
+ tmpglob++; /* get rid of the : */
+ glob = strdup(tmpglob);
+ }
+ }
+
+ if (is_extended) {
+ log_module(MAIN_LOG, LOG_DEBUG, "Extended ban. T (%c) R (%d) M (%s)", exttype, extreverse, glob);
+ switch (exttype) {
+ case 'a': // account
+ if (user->handle_info) {
+ if (extreverse) {
+ if (0 != strcasecmp(glob, user->handle_info->handle))
+ return 1;
+ } else {
+ if (0 == strcasecmp(glob, user->handle_info->handle))
+ return 1;
+ }
+ } else {
+ if (extreverse)
+ return 1;
+ }
+ return match_ircglob(user->hostname, glob);
+ case 'c': // another channel
+ if (!strstr(glob, "#"))
+ return -1;
+
+ if (extreverse) {
+ for (n=count=0; n<user->channels.used; n++) {
+ mn = user->channels.list[n];
+ match = 0;
+
+ if (*glob == '#') {
+ if (0 == strcasecmp(glob, mn->channel->name))
+ match = 1;
+ } else {
+ if (0 == strcasecmp(glob+1, mn->channel->name)) {
+ if ((*glob == '@') && (mn->modes & MODE_CHANOP))
+ match = 1;
+ else if ((*glob == '%') && (mn->modes & MODE_HALFOP))
+ match = 1;
+ else if ((*glob == '+') && (mn->modes & MODE_VOICE))
+ match = 1;
+ }
+ }
+
+ if (match == 0)
+ banned = 1;
+ else {
+ banned = 0;
+ break;
+ }
+ }
+ } else {
+ for (n=count=0; n<user->channels.used; n++) {
+ mn = user->channels.list[n];
+ match = 0;
+
+ if (*glob == '#') {
+ if (0 == strcasecmp(glob, mn->channel->name))
+ match = 1;
+ } else {
+ if (0 == strcasecmp(glob+1, mn->channel->name)) {
+ if ((*glob == '@') && (mn->modes & MODE_CHANOP))
+ match = 1;
+ else if ((*glob == '%') && (mn->modes & MODE_HALFOP))
+ match = 1;
+ else if ((*glob == '+') && (mn->modes & MODE_VOICE))
+ match = 1;
+ }
+ }
+
+ if (match == 1)
+ banned = 1;
+ }
+ }
+
+ if (banned)
+ return 1;
+ else
+ return match_ircglob(user->hostname, glob);
+ case 'j':
+ if (shared == 0) {
+ if (*glob != '#')
+ return -1;
+ if ((channel = GetChannel(glob))) {
+ for (n = 0; n < channel->banlist.used; n++) {
+ ban = channel->banlist.list[n];
+ if (user_matches_glob(user, ban->ban, flags, 1))
+ return 1;
+ }
+ }
+ }
+ return match_ircglob(user->hostname, glob);
+ case 'n': /* this is handled ircd side */
+ return match_ircglob(user->hostname, glob);
+ case 'q': /* this is handled ircd side */
+ return match_ircglob(user->hostname, glob);
+ case 't': /* this is handled ircd side */
+ return match_ircglob(user->hostname, glob);
+ case 'R': /* this is handled ircd side */
+ return match_ircglob(user->hostname, glob);
+ case 'm': // mute by mark
+ if(user->mark && !strcmp(glob, user->mark))
+ return true;
+ else
+ return false;
+
+ case 'M': // mute by mark unless authed
+ return false; // can never match a logged in user
+
+ default:
+ return -1;
+ }
+ }
- /* 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;
}
+
+ /* Match crypt hostname */
+ if (match_ircglob(user->crypthost, glob))
+ return 1;
+
+ /* Match crypt IP */
+ if (match_ircglob(user->cryptip, 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) ||
+ user->crypthost || user->cryptip))
+ 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);
}
int
is_ircmask(const char *text)
{
+ char *tmptext;
+
+ if (*text == '~') {
+ tmptext = alloca(strlen(text)+1);
+ tmptext = strdup(text);
+
+ tmptext++; /* get rid of the ~ */
+
+ if (*tmptext == '!')
+ tmptext++; /* get rid of the ! if it exists */
+
+ tmptext++; /* get rid of the ext ban type */
+
+ if (*tmptext == ':') {
+ tmptext++; /* get rid of the : */
+ while (*tmptext && !isspace((char)*tmptext))
+ tmptext++; /* get rid of the rest */
+ return !*tmptext;
+ }
+ }
+
while (*text && (isalnum((char)*text) || strchr("-_[]|\\`^{}?*", *text)))
text++;
if (*text++ != '!')
/* 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)
{
return(retstr);
}
+/* Mallocing snprintf *
+ *
+ * If it overruns size, it will simply be safely truncated.
+ */
+char *
+x3_msnprintf(const int size, const char *format, ...)
+{
+ va_list ap;
+ char* buff = calloc(sizeof(char *), size+1);
+
+ va_start(ap, format);
+ vsnprintf(buff, size, format, ap);
+ va_end(ap);
+ buff = realloc(buff, strlen(buff) + 1);
+ return buff;
+}
+
char *time2str(time_t thetime)
{
char *buf, *tmp;
return true;
}
+/*
+ * Create a string of form "foo!bar@fubar" given foo, bar and fubar
+ * as the parameters. If NULL, they become "*".
+ */
+#define NUH_BUFSIZE (NICKLEN + USERLEN + HOSTLEN + 10)
+static char *make_nick_user_host(char *namebuf, const char *nick,
+ const char *name, const char *host)
+{
+ snprintf(namebuf, NUH_BUFSIZE, "%s!%s@%s", nick, name, host);
+ return namebuf;
+}
+
+/*
+ * pretty_mask
+ *
+ * by Carlo Wood (Run), 05 Oct 1998.
+ *
+ * Canonify a mask.
+ *
+ * When the nick is longer then NICKLEN, it is cut off (its an error of course).
+ * When the user name or host name are too long (USERLEN and HOSTLEN
+ * respectively) then they are cut off at the start with a '*'.
+ *
+ * The following transformations are made:
+ *
+ * 1) xxx -> nick!*@*
+ * 2) xxx.xxx -> *!*@host
+ * 3) xxx!yyy -> nick!user@*
+ * 4) xxx@yyy -> *!user@host
+ * 5) xxx!yyy@zzz -> nick!user@host
+ */
+char *pretty_mask(char *mask)
+{
+ static char star[2] = { '*', 0 };
+ static char retmask[NUH_BUFSIZE] = "";
+ char *last_dot = NULL;
+ char *ptr = NULL;
+
+ /* Case 1: default */
+ char *nick = mask;
+ char *user = star;
+ char *host = star;
+
+ /* Do a _single_ pass through the characters of the mask: */
+ for (ptr = mask; *ptr; ++ptr)
+ {
+ if (*ptr == '!')
+ {
+ /* Case 3 or 5: Found first '!' (without finding a '@' yet) */
+ user = ++ptr;
+ host = star;
+ }
+ else if (*ptr == '@')
+ {
+ /* Case 4: Found last '@' (without finding a '!' yet) */
+ nick = star;
+ user = mask;
+ host = ++ptr;
+ }
+ else if (*ptr == '.')
+ {
+ /* Case 2: Found last '.' (without finding a '!' or '@' yet) */
+ last_dot = ptr;
+ continue;
+ }
+ else
+ continue;
+ for (; *ptr; ++ptr)
+ {
+ if (*ptr == '@')
+ {
+ /* Case 4 or 5: Found last '@' */
+ host = ptr + 1;
+ }
+ }
+ break;
+ }
+ if (user == star && last_dot)
+ {
+ /* Case 2: */
+ nick = star;
+ user = star;
+ host = mask;
+ }
+ /* Check lengths */
+ if (nick != star)
+ {
+ char *nick_end = (user != star) ? user - 1 : ptr;
+ if (nick_end - nick > NICKLEN)
+ nick[NICKLEN] = 0;
+ *nick_end = 0;
+ }
+ if (user != star)
+ {
+ char *user_end = (host != star) ? host - 1 : ptr;
+ if (user_end - user > USERLEN)
+ {
+ user = user_end - USERLEN;
+ *user = '*';
+ }
+ *user_end = 0;
+ }
+ if (host != star && ptr - host > HOSTLEN)
+ {
+ host = ptr - HOSTLEN;
+ *host = '*';
+ }
+ return make_nick_user_host(retmask, nick, user, host);
+}
+
+int str_is_number(const char *str)
+{
+ char *ptr;
+ int ret = false;
+ for(ptr = (char *)str;*ptr;ptr++) {
+ if((*ptr >= '0' && *ptr <= '9') || *ptr == '-')
+ ret = true;
+ else
+ return false;
+ }
+ return ret;
+}