/* tools.c - miscellaneous utility functions
* Copyright 2000-2004 srvx Development Team
*
- * This file is part of srvx.
+ * This file is part of x3.
*
* srvx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
int
match_ircglob(const char *text, const char *glob)
{
- unsigned int star_p, q_cnt;
- while (1) {
- switch (*glob) {
- case 0:
- return !*text;
- case '\\':
- glob++;
- /* intentionally not tolower(...) so people can force
- * capitalization, or we can overload \ in the future */
- if (*text++ != *glob++)
- return 0;
- break;
- case '*':
- case '?':
- star_p = q_cnt = 0;
- do {
- if (*glob == '*')
- star_p = 1;
- else if (*glob == '?')
- q_cnt++;
- else
- break;
- glob++;
- } while (1);
- while (q_cnt) {
- if (!*text++)
- return 0;
- q_cnt--;
- }
- if (star_p) {
- /* if this is the last glob character, it will match any text */
- if (!*glob)
- return 1;
- /* Thanks to the loop above, we know that the next
- * character is a normal character. So just look for
- * the right character.
- */
- for (; *text; text++) {
- if ((tolower(*text) == tolower(*glob))
- && match_ircglob(text+1, glob+1)) {
- return 1;
- }
- }
- return 0;
- }
- /* if !star_p, fall through to normal character case,
- * first checking to see if ?s carried us to the end */
- if (!*glob && !*text)
+ const char *m = glob, *n = text;
+ const char *m_tmp = glob, *n_tmp = text;
+ int star_p;
+
+ for (;;) switch (*m) {
+ case '\0':
+ if (!*n)
+ return 1;
+ backtrack:
+ if (m_tmp == glob)
+ return 0;
+ m = m_tmp;
+ n = ++n_tmp;
+ break;
+ case '\\':
+ m++;
+ /* allow escaping to force capitalization */
+ if (*m++ != *n++)
+ return 0;
+ break;
+ case '*': case '?':
+ for (star_p = 0; ; m++) {
+ if (*m == '*')
+ star_p = 1;
+ else if (*m == '?') {
+ if (!*n++)
+ goto backtrack;
+ } else break;
+ }
+ if (star_p) {
+ if (!*m)
return 1;
- default:
- if (!*text)
- return 0;
- while (*text && *glob && *glob != '*' && *glob != '?' && *glob != '\\') {
- if (tolower(*text++) != tolower(*glob++))
+ else if (*m == '\\') {
+ m_tmp = ++m;
+ if (!*m)
return 0;
- }
- }
+ for (n_tmp = n; *n && *n != *m; n++) ;
+ } else {
+ m_tmp = m;
+ for (n_tmp = n; *n && tolower(*n) != tolower(*m); n++) ;
+ }
+ }
+ /* and fall through */
+ default:
+ if (!*n)
+ return *m == '\0';
+ if (tolower(*m) != tolower(*n))
+ goto backtrack;
+ m++;
+ n++;
+ break;
}
}
extern const char *hidden_host_suffix;
+/* Prevent *@* *@** *@*a* type masks, while allowing anything else. This is the best way iv found to detect
+ * a global matching mask; if it matches this string, it'll match almost anything :) */
+int is_overmask(char *mask)
+{
+ 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(struct userNode *user, const char *orig_glob, int include_nick)
+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
if (!match_ircglob(user->ident, glob) && (IsSetHost(user) && !match_ircglob(setident, glob)))
return 0;
glob = marker + 1;
- /* Now check the host part */
- if (isdigit(*glob) && !glob[strspn(glob, "0123456789./*?")]) {
- /* Looks like an IP-based mask */
- return match_ircglob(inet_ntoa(user->ip), glob);
- } else {
- /* The host part of the mask isn't IP-based */
- if (IsSetHost(user) && match_ircglob(sethostname, glob))
+ /* 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))
+ return 1;
+ /* Check for an account match. */
+ if (hidden_host_suffix && user->handle_info) {
+ char hidden_host[HOSTLEN+1];
+ snprintf(hidden_host, sizeof(hidden_host), "%s.%s", user->handle_info->handle, hidden_host_suffix);
+ if (match_ircglob(hidden_host, glob))
return 1;
- if (IsFakeHost(user) && match_ircglob(user->fakehost, glob))
- return 1;
- if (hidden_host_suffix && user->handle_info) {
- char hidden_host[HOSTLEN+1];
- snprintf(hidden_host, sizeof(hidden_host), "%s.%s", user->handle_info->handle, hidden_host_suffix);
- if (match_ircglob(hidden_host, glob))
- return 1;
- }
- return match_ircglob(user->hostname, glob);
}
+ /* None of the above; could only be a hostname match. */
+ return match_ircglob(user->hostname, glob);
}
int
return 0;
if (!*text)
return 0;
- while (*text && (isalnum((char)*text) || strchr(".-?*", *text)))
+ while (*text && (isalnum((char)*text) || strchr(".-?*:", *text)))
text++;
return !*text;
}
*ident = start;
start = ++text;
- while (*text && (isalnum((char)*text) || strchr(".-?*", *text)))
+ while (*text && (isalnum((char)*text) || strchr(".-?*:", *text)))
text++;
if (host)
*host = start;
{
switch (type) {
case 'y': return 365*24*60*60;
- case 'M': return 31*24*60*60;
+ case 'M': return 30*24*60*60;
case 'w': return 7*24*60*60;
case 'd': return 24*60*60;
case 'h': return 60*60;
}
}
+/* This function is not entirely accurate as it does not take into account leap units
+ * or varying months. TODO: use proper dateadd functions to calculate real seconds
+ * from now for the units (eg 1M should be give us seconds till todays date next month)
+ */
unsigned long
ParseInterval(const char *interval)
{
if (words++ == 1) {
msg = language_find_message(lang, "MSG_AND");
- pos += sprintf(output + pos, " %s ", msg);
+ pos += sprintf(output + pos, "%s ", msg);
}
if (count == 1)
msg = language_find_message(lang, unit[type].msg_single);
else
msg = language_find_message(lang, unit[type].msg_plural);
- pos += sprintf(output + pos, "%d %s", count, msg);
+ pos += sprintf(output + pos, "%d%s", count, msg);
}
output[pos] = 0;
* multiple dilimiters, which can really
* offset tokens and cause huge corruption
* so this function will use strsep but
- * act like strtok in that sence.
+ * act like strtok in that sense.
*/
char *mysep(char **sepstr, char *delim)
{
return(retstr);
}
+char *time2str(time_t thetime)
+{
+ char *buf, *tmp;
+
+ buf = ctime(&thetime);
+ tmp = (char *)strchr(buf, '\n');
+ *tmp = '\0';
+ return(buf);
+}
+