misc.c

Go to the documentation of this file.
00001 
00002 /* Miscellaneous routines.
00003  *
00004  * (C) 2003-2008 Anope Team
00005  * Contact us at info@anope.org
00006  *
00007  * Please read COPYING and README for further details.
00008  *
00009  * Based on the original code of Epona by Lara.
00010  * Based on the original code of Services by Andy Church. 
00011  * 
00012  * $Id: misc.c 1426 2008-09-03 20:11:12Z viper $ 
00013  *
00014  */
00015 
00016 #include "services.h"
00017 #include "language.h"
00018 
00019 /* Cheaper than isspace() or isblank() */
00020 #define issp(c) ((c) == 32)
00021 
00022 struct arc4_stream {
00023     u_int8_t i;
00024     u_int8_t j;
00025     u_int8_t s[256];
00026 } rs;
00027 
00028 /*************************************************************************/
00029 
00036 int toupper(char c)
00037 {
00038     if (islower(c)) {
00039         return (unsigned char) c - ('a' - 'A');
00040     } else {
00041         return (unsigned char) c;
00042     }
00043 }
00044 
00045 /*************************************************************************/
00046 
00053 int tolower(char c)
00054 {
00055     if (isupper(c)) {
00056         return (unsigned char) c + ('a' - 'A');
00057     } else {
00058         return (unsigned char) c;
00059     }
00060 }
00061 
00062 /*************************************************************************/
00063 
00068 void binary_to_hex(unsigned char *bin, char *hex, int length)
00069 {
00070     static const char trans[] = "0123456789ABCDEF";
00071     int i;
00072 
00073     for (i = 0; i < length; i++) {
00074         hex[i << 1] = trans[bin[i] >> 4];
00075         hex[(i << 1) + 1] = trans[bin[i] & 0xf];
00076     }
00077 
00078     hex[i << 1] = '\0';
00079 }
00080 
00081 
00082 /*************************************************************************/
00083 
00092 char *strscpy(char *d, const char *s, size_t len)
00093 {
00094     char *d_orig = d;
00095 
00096     if (!len) {
00097         return d;
00098     }
00099     while (--len && (*d++ = *s++));
00100     *d = '\0';
00101     return d_orig;
00102 }
00103 
00104 /*************************************************************************/
00105 
00114 char *stristr(char *s1, char *s2)
00115 {
00116     register char *s = s1, *d = s2;
00117 
00118     while (*s1) {
00119         if (tolower(*s1) == tolower(*d)) {
00120             s1++;
00121             d++;
00122             if (*d == 0)
00123                 return s;
00124         } else {
00125             s = ++s1;
00126             d = s2;
00127         }
00128     }
00129     return NULL;
00130 }
00131 
00132 /*************************************************************************/
00133 
00145 char *strnrepl(char *s, int32 size, const char *old, const char *new)
00146 {
00147     char *ptr = s;
00148     int32 left = strlen(s);
00149     int32 avail = size - (left + 1);
00150     int32 oldlen = strlen(old);
00151     int32 newlen = strlen(new);
00152     int32 diff = newlen - oldlen;
00153 
00154     while (left >= oldlen) {
00155         if (strncmp(ptr, old, oldlen) != 0) {
00156             left--;
00157             ptr++;
00158             continue;
00159         }
00160         if (diff > avail)
00161             break;
00162         if (diff != 0)
00163             memmove(ptr + oldlen + diff, ptr + oldlen, left + 1);
00164         strncpy(ptr, new, newlen);
00165         ptr += newlen;
00166         left -= oldlen;
00167     }
00168     return s;
00169 }
00170 
00171 /*************************************************************************/
00172 
00181 char *merge_args(int argc, char **argv)
00182 {
00183     int i;
00184     static char s[4096];
00185     char *t;
00186 
00187     t = s;
00188     for (i = 0; i < argc; i++)
00189         t += snprintf(t, sizeof(s) - (t - s), "%s%s", *argv++,
00190                       (i < argc - 1) ? " " : "");
00191     return s;
00192 }
00193 
00194 /*************************************************************************/
00195 
00205 static int do_match_wild(const char *pattern, const char *str, int docase)
00206 {
00207     char c;
00208     const char *s;
00209 
00210     if (!str || !*str || !pattern || !*pattern) {
00211         return 0;
00212     }
00213 
00214     /* This WILL eventually terminate: either by *pattern == 0, or by a
00215      * trailing '*'. */
00216 
00217     for (;;) {
00218         switch (c = *pattern++) {
00219         case 0:
00220             if (!*str)
00221                 return 1;
00222             return 0;
00223         case '?':
00224             if (!*str)
00225                 return 0;
00226             str++;
00227             break;
00228         case '*':
00229             if (!*pattern)
00230                 return 1;       /* trailing '*' matches everything else */
00231             s = str;
00232             while (*s) {
00233                 if ((docase ? (*s == *pattern)
00234                      : (tolower(*s) == tolower(*pattern)))
00235                     && do_match_wild(pattern, s, docase))
00236                     return 1;
00237                 s++;
00238             }
00239             break;
00240         default:
00241             if (docase ? (*str++ != c) : (tolower(*str++) != tolower(c)))
00242                 return 0;
00243             break;
00244         }                       /* switch */
00245     }
00246 }
00247 
00248 /*************************************************************************/
00249 
00256 int match_wild(const char *pattern, const char *str)
00257 {
00258     return do_match_wild(pattern, str, 1);
00259 }
00260 
00261 /*************************************************************************/
00262 
00269 int match_wild_nocase(const char *pattern, const char *str)
00270 {
00271     return do_match_wild(pattern, str, 0);
00272 }
00273 
00274 /*************************************************************************/
00275 
00293 int process_numlist(const char *numstr, int *count_ret,
00294                     range_callback_t callback, User * u, ...)
00295 {
00296     int n1, n2, i;
00297     int res = 0, retval = 0, count = 0;
00298     va_list args, preserve;
00299 
00300     if (!numstr || !*numstr) {
00301         return -1;
00302     }
00303 
00304     va_start(args, u);
00305 
00306     /*
00307      * This algorithm ignores invalid characters, ignores a dash
00308      * when it precedes a comma, and ignores everything from the
00309      * end of a valid number or range to the next comma or null.
00310      */
00311     for (;;) {
00312         n1 = n2 = strtol(numstr, (char **) &numstr, 10);
00313         numstr += strcspn(numstr, "0123456789,-");
00314         if (*numstr == '-') {
00315             numstr++;
00316             numstr += strcspn(numstr, "0123456789,");
00317             if (isdigit(*numstr)) {
00318                 n2 = strtol(numstr, (char **) &numstr, 10);
00319                 numstr += strcspn(numstr, "0123456789,-");
00320             }
00321         }
00322         for (i = n1; i <= n2 && i >= 0; i++) {
00323             VA_COPY(preserve, args);
00324             res = callback(u, i, preserve);
00325             va_end(preserve);
00326             count++;
00327             if (res < 0)
00328                 break;
00329             retval += res;
00330             if (count >= 32767) {
00331                 if (count_ret)
00332                     *count_ret = count;
00333                 return retval;
00334             }
00335         }
00336         if (res < -1)
00337             break;
00338         numstr += strcspn(numstr, ",");
00339         if (*numstr)
00340             numstr++;
00341         else
00342             break;
00343     }
00344     if (count_ret)
00345         *count_ret = count;
00346 
00347     va_end(args);
00348 
00349     return retval;
00350 }
00351 
00352 /*************************************************************************/
00353 
00365 int dotime(const char *s)
00366 {
00367     int amount;
00368 
00369     if (!s || !*s) {
00370         return -1;
00371     }
00372 
00373     amount = strtol(s, (char **) &s, 10);
00374     if (*s) {
00375         switch (*s) {
00376         case 's':
00377             return amount;
00378         case 'm':
00379             return amount * 60;
00380         case 'h':
00381             return amount * 3600;
00382         case 'd':
00383             return amount * 86400;
00384         default:
00385             return -1;
00386         }
00387     } else {
00388         return amount;
00389     }
00390 }
00391 
00392 /*************************************************************************/
00393 
00403 char *duration(NickAlias * na, char *buf, int bufsize, time_t seconds)
00404 {
00405     int days = 0, hours = 0, minutes = 0;
00406     int need_comma = 0;
00407 
00408     char buf2[64], *end;
00409     char *comma = getstring(na, COMMA_SPACE);
00410 
00411     /* We first calculate everything */
00412     days = seconds / 86400;
00413     seconds -= (days * 86400);
00414     hours = seconds / 3600;
00415     seconds -= (hours * 3600);
00416     minutes = seconds / 60;
00417 
00418     if (!days && !hours && !minutes) {
00419         snprintf(buf, bufsize,
00420                  getstring(na,
00421                            (seconds <=
00422                             1 ? DURATION_SECOND : DURATION_SECONDS)),
00423                  seconds);
00424     } else {
00425         end = buf;
00426         if (days) {
00427             snprintf(buf2, sizeof(buf2),
00428                      getstring(na,
00429                                (days == 1 ? DURATION_DAY : DURATION_DAYS)),
00430                      days);
00431             end += snprintf(end, bufsize - (end - buf), "%s", buf2);
00432             need_comma = 1;
00433         }
00434         if (hours) {
00435             snprintf(buf2, sizeof(buf2),
00436                      getstring(na,
00437                                (hours ==
00438                                 1 ? DURATION_HOUR : DURATION_HOURS)),
00439                      hours);
00440             end +=
00441                 snprintf(end, bufsize - (end - buf), "%s%s",
00442                          (need_comma ? comma : ""), buf2);
00443             need_comma = 1;
00444         }
00445         if (minutes) {
00446             snprintf(buf2, sizeof(buf2),
00447                      getstring(na,
00448                                (minutes ==
00449                                 1 ? DURATION_MINUTE : DURATION_MINUTES)),
00450                      minutes);
00451             end +=
00452                 snprintf(end, bufsize - (end - buf), "%s%s",
00453                          (need_comma ? comma : ""), buf2);
00454             need_comma = 1;
00455         }
00456     }
00457 
00458     return buf;
00459 }
00460 
00461 /*************************************************************************/
00462 
00471 char *expire_left(NickAlias * na, char *buf, int len, time_t expires)
00472 {
00473     time_t now = time(NULL);
00474 
00475     if (!expires) {
00476         strncpy(buf, getstring(na, NO_EXPIRE), len);
00477     } else if (expires <= now) {
00478         strncpy(buf, getstring(na, EXPIRES_SOON), len);
00479     } else {
00480         time_t diff = expires - now + 59;
00481 
00482         if (diff >= 86400) {
00483             int days = diff / 86400;
00484             snprintf(buf, len,
00485                      getstring(na, (days == 1) ? EXPIRES_1D : EXPIRES_D),
00486                      days);
00487         } else {
00488             if (diff <= 3600) {
00489                 int minutes = diff / 60;
00490                 snprintf(buf, len,
00491                          getstring(na,
00492                                    (minutes ==
00493                                     1) ? EXPIRES_1M : EXPIRES_M), minutes);
00494             } else {
00495                 int hours = diff / 3600, minutes;
00496                 diff -= (hours * 3600);
00497                 minutes = diff / 60;
00498                 snprintf(buf, len,
00499                          getstring(na,
00500                                    ((hours == 1
00501                                      && minutes ==
00502                                      1) ? EXPIRES_1H1M : ((hours == 1
00503                                                            && minutes !=
00504                                                            1) ? EXPIRES_1HM
00505                                                           : ((hours != 1
00506                                                               && minutes ==
00507                                                               1) ?
00508                                                              EXPIRES_H1M :
00509                                                              EXPIRES_HM)))),
00510                          hours, minutes);
00511             }
00512         }
00513     }
00514 
00515     return buf;
00516 }
00517 
00518 
00519 /*************************************************************************/
00520 
00530 int doValidHost(const char *host, int type)
00531 {
00532     int idx = 0;
00533     int len = 0;
00534     int sec_len = 0;
00535     int dots = 1;
00536     if (type != 1 && type != 2) {
00537         return 0;
00538     }
00539     if (!host) {
00540         return 0;
00541     }
00542 
00543     len = strlen(host);
00544 
00545     if (len > HOSTMAX) {
00546         return 0;
00547     }
00548 
00549     switch (type) {
00550     case 1:
00551         for (idx = 0; idx < len; idx++) {
00552             if (isdigit(host[idx])) {
00553                 if (sec_len < 3) {
00554                     sec_len++;
00555                 } else {
00556                     return 0;
00557                 }
00558             } else {
00559                 if (idx == 0) {
00560                     return 0;
00561                 }               /* cant start with a non-digit */
00562                 if (host[idx] != '.') {
00563                     return 0;
00564                 }               /* only . is a valid non-digit */
00565                 if (sec_len > 3) {
00566                     return 0;
00567                 }               /* sections cant be more than 3 digits */
00568                 sec_len = 0;
00569                 dots++;
00570             }
00571         }
00572         if (dots != 4) {
00573             return 0;
00574         }
00575         break;
00576     case 2:
00577         dots = 0;
00578         for (idx = 0; idx < len; idx++) {
00579             if (!isalnum(host[idx])) {
00580                 if (idx == 0) {
00581                     return 0;
00582                 }
00583                 if ((host[idx] != '.') && (host[idx] != '-')) {
00584                     return 0;
00585                 }
00586                 if (host[idx] == '.') {
00587                     dots++;
00588                 }
00589             }
00590         }
00591         if (host[len - 1] == '.') {
00592             return 0;
00593         }
00598         if (dots == 0) {
00599             return 0;
00600         }
00601 
00602         break;
00603     }
00604     return 1;
00605 }
00606 
00607 /*************************************************************************/
00608 
00615 int isValidHost(const char *host, int type)
00616 {
00617     int status = 0;
00618     if (type == 3) {
00619         if (!(status = doValidHost(host, 1))) {
00620             status = doValidHost(host, 2);
00621         }
00622     } else {
00623         status = doValidHost(host, type);
00624     }
00625     return status;
00626 }
00627 
00628 /*************************************************************************/
00629 
00635 int isvalidchar(const char c)
00636 {
00637     if (((c >= 'A') && (c <= 'Z')) ||
00638         ((c >= 'a') && (c <= 'z')) ||
00639         ((c >= '0') && (c <= '9')) || (c == '.') || (c == '-'))
00640         return 1;
00641     else
00642         return 0;
00643 }
00644 
00645 
00646 /*************************************************************************/
00647 
00655 char *myStrGetToken(const char *str, const char dilim, int token_number)
00656 {
00657     int len, idx, counter = 0, start_pos = 0;
00658     char *substring = NULL;
00659     if (!str) {
00660         return NULL;
00661     }
00662     len = strlen(str);
00663     for (idx = 0; idx <= len; idx++) {
00664         if ((str[idx] == dilim) || (idx == len)) {
00665             if (counter == token_number) {
00666                 substring = myStrSubString(str, start_pos, idx);
00667                 counter++;
00668             } else {
00669                 start_pos = idx + 1;
00670                 counter++;
00671             }
00672         }
00673     }
00674     return substring;
00675 }
00676 
00677 /*************************************************************************/
00678 
00686 char *myStrGetOnlyToken(const char *str, const char dilim,
00687                         int token_number)
00688 {
00689     int len, idx, counter = 0, start_pos = 0;
00690     char *substring = NULL;
00691     if (!str) {
00692         return NULL;
00693     }
00694     len = strlen(str);
00695     for (idx = 0; idx <= len; idx++) {
00696         if (str[idx] == dilim) {
00697             if (counter == token_number) {
00698                 if (str[idx] == '\r')
00699                     substring = myStrSubString(str, start_pos, idx - 1);
00700                 else
00701                     substring = myStrSubString(str, start_pos, idx);
00702                 counter++;
00703             } else {
00704                 start_pos = idx + 1;
00705                 counter++;
00706             }
00707         }
00708     }
00709     return substring;
00710 }
00711 
00712 /*************************************************************************/
00713 
00721 char *myStrGetTokenRemainder(const char *str, const char dilim,
00722                              int token_number)
00723 {
00724     int len, idx, counter = 0, start_pos = 0;
00725     char *substring = NULL;
00726     if (!str) {
00727         return NULL;
00728     }
00729     len = strlen(str);
00730 
00731     for (idx = 0; idx <= len; idx++) {
00732         if ((str[idx] == dilim) || (idx == len)) {
00733             if (counter == token_number) {
00734                 substring = myStrSubString(str, start_pos, len);
00735                 counter++;
00736             } else {
00737                 start_pos = idx + 1;
00738                 counter++;
00739             }
00740         }
00741     }
00742     return substring;
00743 }
00744 
00745 /*************************************************************************/
00746 
00754 char *myStrSubString(const char *src, int start, int end)
00755 {
00756     char *substring = NULL;
00757     int len, idx;
00758     if (!src) {
00759         return NULL;
00760     }
00761     len = strlen(src);
00762     if (((start >= 0) && (end <= len)) && (end > start)) {
00763         substring = (char *) malloc(sizeof(char) * ((end - start) + 1));
00764         for (idx = 0; idx <= end - start; idx++) {
00765             substring[idx] = src[start + idx];
00766         }
00767         substring[end - start] = '\0';
00768     }
00769     return substring;
00770 }
00771 
00772 /*************************************************************************/
00773 
00774 void protocol_debug(char *source, char *cmd, int argc, char **argv)
00775 {
00776     int i;
00777 
00778     if (protocoldebug) {
00779         if (source)
00780             alog("debug: Source %s", source);
00781         if (cmd)
00782             alog("debug: Token %s", cmd);
00783         if (argc) {
00784             for (i = 0; i < argc; i++) {
00785                 alog("debug: av[%d] = %s", i, argv[i]);
00786             }
00787         } else {
00788             alog("debug: av[0] = NULL");
00789         }
00790     }
00791     return;
00792 }
00793 
00794 /*************************************************************************/
00795 
00801 void doCleanBuffer(char *str)
00802 {
00803     char *in, *out;
00804     char ch;
00805 
00806     if (!str) {
00807         return;
00808     }
00809 
00810     in = str;
00811     out = str;
00812 
00813     while (issp(ch = *in++));
00814     if (ch != '\0')
00815         for (;;) {
00816             *out++ = ch;
00817             ch = *in++;
00818             if (ch == '\0')
00819                 break;
00820             if (!issp(ch))
00821                 continue;
00822             while (issp(ch = *in++));
00823             if (ch == '\0')
00824                 break;
00825             *out++ = ' ';
00826         }
00827     *out = ch;                  /* == '\0' */
00828 }
00829 
00830 /*************************************************************************/
00831 
00838 void EnforceQlinedNick(char *nick, char *killer)
00839 {
00840     User *u2;
00841 
00842     if ((u2 = finduser(nick))) {
00843         alog("Killed Q-lined nick: %s!%s@%s", u2->nick, u2->username,
00844              u2->host);
00845         kill_user(killer, u2->nick,
00846                   "This nick is reserved for Services. Please use a non Q-Lined nick.");
00847     }
00848 }
00849 
00850 /*************************************************************************/
00851 
00858 int nickIsServices(char *tempnick, int bot)
00859 {
00860     int found = 0;
00861     char *s, *nick;
00862 
00863     if (!tempnick) {
00864         return found;
00865     }
00866 
00867     nick = sstrdup(tempnick);
00868 
00869     s = strchr(nick, '@');
00870     if (s) {
00871         *s++ = 0;
00872         if (stricmp(s, ServerName) != 0) {
00873             free(nick);
00874             return found;
00875         }
00876     }
00877 
00878     if (s_NickServ && (stricmp(nick, s_NickServ) == 0))
00879         found++;
00880     else if (s_ChanServ && (stricmp(nick, s_ChanServ) == 0))
00881         found++;
00882     else if (s_HostServ && (stricmp(nick, s_HostServ) == 0))
00883         found++;
00884     else if (s_MemoServ && (stricmp(nick, s_MemoServ) == 0))
00885         found++;
00886     else if (s_BotServ && (stricmp(nick, s_BotServ) == 0))
00887         found++;
00888     else if (s_HelpServ && (stricmp(nick, s_HelpServ) == 0))
00889         found++;
00890     else if (s_OperServ && (stricmp(nick, s_OperServ) == 0))
00891         found++;
00892     else if (s_DevNull && (stricmp(nick, s_DevNull) == 0))
00893         found++;
00894     else if (s_GlobalNoticer && (stricmp(nick, s_GlobalNoticer) == 0))
00895         found++;
00896     else if (s_NickServAlias && (stricmp(nick, s_NickServAlias) == 0))
00897         found++;
00898     else if (s_ChanServAlias && (stricmp(nick, s_ChanServAlias) == 0))
00899         found++;
00900     else if (s_MemoServAlias && (stricmp(nick, s_MemoServAlias) == 0))
00901         found++;
00902     else if (s_BotServAlias && (stricmp(nick, s_BotServAlias) == 0))
00903         found++;
00904     else if (s_HelpServAlias && (stricmp(nick, s_HelpServAlias) == 0))
00905         found++;
00906     else if (s_OperServAlias && (stricmp(nick, s_OperServAlias) == 0))
00907         found++;
00908     else if (s_DevNullAlias && (stricmp(nick, s_DevNullAlias) == 0))
00909         found++;
00910     else if (s_HostServAlias && (stricmp(nick, s_HostServAlias) == 0))
00911         found++;
00912     else if (s_GlobalNoticerAlias
00913              && (stricmp(nick, s_GlobalNoticerAlias) == 0))
00914         found++;
00915     else if (s_BotServ && bot) {
00916         BotInfo *bi;
00917         int i;
00918         for (i = 0; i < 256; i++) {
00919             for (bi = botlists[i]; bi; bi = bi->next) {
00920                 if (stricmp(nick, bi->nick) == 0) {
00921                     found++;
00922                     continue;
00923                 }
00924             }
00925         }
00926     }
00927 
00928     /* Somehow, something tells me we should free this :) -GD */
00929     free(nick);
00930 
00931     return found;
00932 }
00933 
00934 /*************************************************************************/
00935 
00940 static void arc4_init(void)
00941 {
00942     int n;
00943     for (n = 0; n < 256; n++)
00944         rs.s[n] = n;
00945     rs.i = 0;
00946     rs.j = 0;
00947 }
00948 
00949 /*************************************************************************/
00950 
00957 static void arc4_addrandom(void *dat, int datlen)
00958 {
00959     int n;
00960     u_int8_t si;
00961 
00962     rs.i--;
00963     for (n = 0; n < 256; n++) {
00964         rs.i = (rs.i + 1);
00965         si = rs.s[rs.i];
00966         rs.j = (rs.j + si + ((unsigned char *) dat)[n % datlen]);
00967         rs.s[rs.i] = rs.s[rs.j];
00968         rs.s[rs.j] = si;
00969     }
00970 }
00971 
00972 /*************************************************************************/
00973 
00978 void rand_init(void)
00979 {
00980     int n;
00981 #ifndef _WIN32
00982     int fd;
00983 #endif
00984     struct {
00985 #ifdef USE_MYSQL
00986         int sqlrand;
00987 #endif
00988 #ifndef _WIN32
00989         struct timeval nowt;    /* time */
00990         char rnd[32];           /* /dev/urandom */
00991 #else
00992         MEMORYSTATUS mstat;     /* memory status */
00993         struct _timeb nowt;     /* time */
00994 #endif
00995     } rdat;
00996 
00997     arc4_init();
00998 
00999     /* Grab "random" MYSQL data */
01000 #ifdef USE_MYSQL
01001     rdat.sqlrand = mysql_rand();
01002 #endif
01003 
01004     /* Grab OS specific "random" data */
01005 #ifndef _WIN32
01006     /* unix/bsd: time */
01007     gettimeofday(&rdat.nowt, NULL);
01008     /* unix/bsd: /dev/urandom */
01009     fd = open("/dev/urandom", O_RDONLY);
01010     if (fd) {
01011         n = read(fd, &rdat.rnd, sizeof(rdat.rnd));
01012         close(fd);
01013     }
01014 #else
01015     /* win32: time */
01016     _ftime(&rdat.nowt);
01017     /* win32: memory status */
01018     GlobalMemoryStatus(&rdat.mstat);
01019 #endif
01020 
01021     arc4_addrandom(&rdat, sizeof(rdat));
01022 }
01023 
01024 /*************************************************************************/
01025 
01030 void add_entropy_userkeys(void)
01031 {
01032     arc4_addrandom(&UserKey1, sizeof(UserKey1));
01033     arc4_addrandom(&UserKey2, sizeof(UserKey2));
01034     arc4_addrandom(&UserKey3, sizeof(UserKey3));
01035     /* UserKey3 is also used in mysql_rand() */
01036 }
01037 
01038 /*************************************************************************/
01039 
01044 unsigned char getrandom8(void)
01045 {
01046     unsigned char si, sj;
01047 
01048     rs.i = (rs.i + 1);
01049     si = rs.s[rs.i];
01050     rs.j = (rs.j + si);
01051     sj = rs.s[rs.j];
01052     rs.s[rs.i] = sj;
01053     rs.s[rs.j] = si;
01054     return (rs.s[(si + sj) & 0xff]);
01055 }
01056 
01057 /*************************************************************************/
01058 
01063 u_int16_t getrandom16(void)
01064 {
01065     u_int16_t val;
01066 
01067     val = getrandom8() << 8;
01068     val |= getrandom8();
01069     return val;
01070 }
01071 
01072 /*************************************************************************/
01073 
01078 u_int32_t getrandom32(void)
01079 {
01080     u_int32_t val;
01081 
01082     val = getrandom8() << 24;
01083     val |= getrandom8() << 16;
01084     val |= getrandom8() << 8;
01085     val |= getrandom8();
01086     return val;
01087 }
01088 
01089 /*************************************************************************/
01090 
01097 char *send_token(char *token1, char *token2)
01098 {
01099     if (UseTokens && ircd->token && ircdcap->token) {
01100         return token2;
01101     } else {
01102         return token1;
01103     }
01104 }
01105 
01106 /*************************************************************************/
01107 
01114 int myNumToken(const char *str, const char dilim)
01115 {
01116     int len, idx, counter = 0, start_pos = 0;
01117     if (!str) {
01118         return 0;
01119     }
01120     len = strlen(str);
01121     for (idx = 0; idx <= len; idx++) {
01122         if ((str[idx] == dilim) || (idx == len)) {
01123             start_pos = idx + 1;
01124             counter++;
01125         }
01126     }
01127     return counter;
01128 }
01129 
01130 /*************************************************************************/
01131 
01137 char *host_resolve(char *host)
01138 {
01139     struct hostent *hentp = NULL;
01140     uint32 ip = INADDR_NONE;
01141     char ipbuf[16];
01142     char *ipreturn;
01143     struct in_addr addr;
01144 
01145     ipreturn = NULL;
01146 
01147     hentp = gethostbyname(host);
01148 
01149     if (hentp) {
01150         memcpy(&ip, hentp->h_addr, sizeof(hentp->h_length));
01151         addr.s_addr = ip;
01152         ntoa(addr, ipbuf, sizeof(ipbuf));
01153         ipreturn = sstrdup(ipbuf);
01154         if (debug) {
01155             alog("debug: resolved %s to %s", host, ipbuf);
01156         }
01157         return ipreturn;
01158     } else {
01159         return ipreturn;
01160     }
01161 }
01162 
01163 /*************************************************************************/
01164 
01172 char *str_signed(unsigned char *str)
01173 {
01174     char *nstr;
01175 
01176     nstr = (char *) str;
01177     while (*str) {
01178         *nstr = (char) *str;
01179         str++;
01180         nstr++;
01181     }
01182 
01183     return nstr;
01184 }
01185 
01191 char *stripModePrefix(const char *str)
01192 {
01193     if (str && ((*str == '+') || (*str == '-'))) {
01194         return sstrdup(str + 1);
01195     }
01196     return NULL;
01197 }
01198 
01199 /* Equivalent to inet_ntoa */
01200 
01201 void ntoa(struct in_addr addr, char *ipaddr, int len)
01202 {
01203     unsigned char *bytes = (unsigned char *) &addr.s_addr;
01204     snprintf(ipaddr, len, "%u.%u.%u.%u", bytes[0], bytes[1], bytes[2],
01205              bytes[3]);
01206 }
01207 
01214 char **buildStringList(char *src, int *number)
01215 {
01216     char *s;
01217     int i = 0;
01218     char **list = NULL;
01219 
01220     if (src) {
01221         s = strtok(src, " ");
01222         do {
01223             if (s) {
01224                 i++;
01225                 list = realloc(list, sizeof(char *) * i);
01226                 list[i - 1] = sstrdup(s);
01227             }
01228         } while ((s = strtok(NULL, " ")));
01229     }
01230     *number = i;                /* always zero it, even if we have no setters */
01231     return list;
01232 }
01233 
01234 /*
01235 * strlcat and strlcpy were ripped from openssh 2.5.1p2
01236 * They had the following Copyright info:
01237 *
01238 *
01239 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
01240 * All rights reserved.
01241 *
01242 * Redistribution and use in source and binary forms, with or without
01243 * modification, are permitted provided that the following conditions
01244 * are met:
01245 * 1. Redistributions of source code must retain the above copyright
01246 *    notice, this list of conditions and the following disclaimer.
01247 * 2. Redistributions in binary form must reproduce the above copyright
01248 *    notice, this list of conditions and the following disclaimer in the
01249 *    documentation and/or other materials provided with the distribution.
01250 * 3. The name of the author may not be used to endorse or promote products
01251 *    derived from this software without specific prior written permission.
01252 *
01253 * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
01254 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
01255 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
01256 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
01257 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
01258 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
01259 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
01260 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
01261 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
01262 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
01263 */
01264 
01265 #ifndef HAVE_STRLCAT
01266 size_t strlcat(char *dst, const char *src, size_t siz)
01267 {
01268     char *d = dst;
01269     const char *s = src;
01270     size_t n = siz, dlen;
01271 
01272     while (n-- != 0 && *d != '\0')
01273         d++;
01274 
01275     dlen = d - dst;
01276     n = siz - dlen;
01277 
01278     if (n == 0)
01279         return (dlen + strlen(s));
01280 
01281     while (*s != '\0') {
01282         if (n != 1) {
01283             *d++ = *s;
01284             n--;
01285         }
01286 
01287         s++;
01288     }
01289 
01290     *d = '\0';
01291     return dlen + (s - src);    /* count does not include NUL */
01292 }
01293 #endif
01294 
01295 #ifndef HAVE_STRLCPY
01296 size_t strlcpy(char *dst, const char *src, size_t siz)
01297 {
01298     char *d = dst;
01299     const char *s = src;
01300     size_t n = siz;
01301 
01302     /* Copy as many bytes as will fit */
01303     if (n != 0 && --n != 0) {
01304         do {
01305             if ((*d++ = *s++) == 0)
01306                 break;
01307         }
01308         while (--n != 0);
01309     }
01310 
01311     /* Not enough room in dst, add NUL and traverse rest of src */
01312     if (n == 0) {
01313         if (siz != 0)
01314             *d = '\0';          /* NUL-terminate dst */
01315         while (*s++);
01316     }
01317 
01318     return s - src - 1;         /* count does not include NUL */
01319 }
01320 #endif
01321 
01322 
01323 
01324 
01325 #ifdef _WIN32
01326 char *GetWindowsVersion(void)
01327 {
01328     OSVERSIONINFOEX osvi;
01329     BOOL bOsVersionInfoEx;
01330     char buf[BUFSIZE];
01331     char *extra;
01332     char *cputype;
01333     SYSTEM_INFO si;
01334 
01335     ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
01336     ZeroMemory(&si, sizeof(SYSTEM_INFO));
01337     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
01338 
01339     if (!(bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *) & osvi))) {
01340         osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
01341         if (!GetVersionEx((OSVERSIONINFO *) & osvi)) {
01342             return sstrdup("");
01343         }
01344     }
01345     GetSystemInfo(&si);
01346 
01347     /* Determine CPU type 32 or 64 */
01348     if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 ) {
01349        cputype = sstrdup(" 64-bit");
01350     } else if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL ) {
01351        cputype = sstrdup(" 32-bit");
01352     }    else if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_IA64 ) {
01353        cputype = sstrdup(" Itanium 64-bit");
01354     } else {
01355                 cputype = sstrdup(" ");
01356     }
01357 
01358     switch (osvi.dwPlatformId) {
01359         /* test for the Windows NT product family. */
01360     case VER_PLATFORM_WIN32_NT:
01361         /* Windows Vista or Windows Server 2008 */
01362         if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0) {
01363             if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) {
01364                 extra = sstrdup("Enterprise Edition");
01365             } else if (osvi.wSuiteMask & VER_SUITE_DATACENTER) {
01366                 extra = sstrdup("Datacenter Edition");
01367             } else if (osvi.wSuiteMask & VER_SUITE_PERSONAL) {
01368                 extra = sstrdup("Home Premium/Basic");
01369             } else {
01370                 extra = sstrdup(" ");
01371             }
01372             if (osvi.wProductType & VER_NT_WORKSTATION) {
01373                     snprintf(buf, sizeof(buf), "Microsoft Windows Vista %s%s",
01374                              cputype, extra);
01375             } else {
01376                     snprintf(buf, sizeof(buf), "Microsoft Windows Server 2008 %s%s",
01377                              cputype, extra);
01378             }
01379             free(extra);
01380         }
01381         /* Windows 2003 or Windows XP Pro 64 */
01382         if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) {
01383             if (osvi.wSuiteMask & VER_SUITE_DATACENTER) {
01384                 extra = sstrdup("Datacenter Edition");
01385             } else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) {
01386                 extra = sstrdup("Enterprise Edition");
01387             } else if (osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER) {
01388                 extra = sstrdup("Compute Cluster Edition");
01389             } else if (osvi.wSuiteMask == VER_SUITE_BLADE) {
01390                 extra = sstrdup("Web Edition");
01391             } else {
01392                 extra = sstrdup("Standard Edition");
01393             }
01394             if ( osvi.wProductType & VER_NT_WORKSTATION && si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
01395                     snprintf(buf, sizeof(buf), "Windows XP Professional x64 Edition %s",
01396                              extra);
01397             } else {
01398                     snprintf(buf, sizeof(buf),
01399                              "Microsoft Windows Server 2003 Family %s%s", cputype, extra);
01400             }
01401             free(extra);
01402         }
01403         if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) {
01404             if (osvi.wSuiteMask & VER_SUITE_EMBEDDEDNT) {
01405                 extra = sstrdup("Embedded");
01406             } else if (osvi.wSuiteMask & VER_SUITE_PERSONAL) {
01407                 extra = sstrdup("Home Edition");
01408             } else {
01409                 extra = sstrdup(" ");
01410             }
01411             snprintf(buf, sizeof(buf), "Microsoft Windows XP %s", extra);
01412             free(extra);
01413         }
01414         if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) {
01415             if (osvi.wSuiteMask & VER_SUITE_DATACENTER) {
01416                 extra = sstrdup("Datacenter Server");
01417             } else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) {
01418                 extra = sstrdup("Advanced Server");
01419             } else {
01420                 extra = sstrdup("Server");
01421             }
01422             snprintf(buf, sizeof(buf), "Microsoft Windows 2000 %s", extra);
01423             free(extra);
01424         }
01425         if (osvi.dwMajorVersion <= 4) {
01426             if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) {
01427                 extra = sstrdup("Server 4.0, Enterprise Edition");
01428             } else {
01429                 extra = sstrdup("Server 4.0");
01430             }
01431             snprintf(buf, sizeof(buf), "Microsoft Windows NT %s", extra);
01432             free(extra);
01433         }
01434     case VER_PLATFORM_WIN32_WINDOWS:
01435         if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0) {
01436             if (osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B') {
01437                 extra = sstrdup("OSR2");
01438             } else {
01439                 extra = sstrdup(" ");
01440             }
01441             snprintf(buf, sizeof(buf), "Microsoft Windows 95 %s", extra);
01442             free(extra);
01443         }
01444         if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) {
01445             if (osvi.szCSDVersion[1] == 'A') {
01446                 extra = sstrdup("SE");
01447             } else {
01448                 extra = sstrdup(" ");
01449             }
01450             snprintf(buf, sizeof(buf), "Microsoft Windows 98 %s", extra);
01451             free(extra);
01452         }
01453         if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) {
01454             snprintf(buf, sizeof(buf),
01455                      "Microsoft Windows Millennium Edition");
01456         }
01457     }
01458     free(cputype);
01459     return sstrdup(buf);
01460 }
01461 
01462 int SupportedWindowsVersion(void)
01463 {
01464     OSVERSIONINFOEX osvi;
01465     BOOL bOsVersionInfoEx;
01466 
01467     ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
01468     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
01469 
01470     if (!(bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *) & osvi))) {
01471         osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
01472         if (!GetVersionEx((OSVERSIONINFO *) & osvi)) {
01473             return 0;
01474         }
01475     }
01476 
01477     switch (osvi.dwPlatformId) {
01478         /* test for the Windows NT product family. */
01479     case VER_PLATFORM_WIN32_NT:
01480         /* win nt4 */
01481         if (osvi.dwMajorVersion <= 4) {
01482             return 0;
01483         }
01484         /* the rest */
01485         return 1;
01486         /* win95 win98 winME */
01487     case VER_PLATFORM_WIN32_WINDOWS:
01488         return 0;
01489     }
01490     return 0;
01491 }
01492 
01493 #endif
01494 
01495 
01496 /*************************************************************************/
01497 /* This 2 functions were originally found in Bahamut */
01498 
01504 uint32 cidr_to_netmask(uint16 cidr)
01505 {
01506     if (cidr == 0)
01507         return 0;
01508 
01509     return (0xFFFFFFFF - (1 << (32 - cidr)) + 1);
01510 }
01511 
01517 uint16 netmask_to_cidr(uint32 mask)
01518 {
01519     int tmp = 0;
01520 
01521     while (!(mask & (1 << tmp)) && (tmp < 32))
01522         tmp++;
01523 
01524     return (32 - tmp);
01525 }
01526 
01527 /*************************************************************************/
01528 
01534 int str_is_wildcard(const char *str)
01535 {
01536     while (*str) {
01537         if ((*str == '*') || (*str == '?'))
01538             return 1;
01539         str++;
01540     }
01541 
01542     return 0;
01543 }
01544 
01550 int str_is_pure_wildcard(const char *str)
01551 {
01552     while (*str) {
01553         if (*str != '*')
01554             return 0;
01555         str++;
01556     }
01557 
01558     return 1;
01559 }
01560 
01561 /*************************************************************************/
01562 
01568 uint32 str_is_ip(char *str)
01569 {
01570     int i;
01571     int octets[4] = { -1, -1, -1, -1 };
01572     char *s = str;
01573     uint32 ip;
01574 
01575     for (i = 0; i < 4; i++) {
01576         octets[i] = strtol(s, &s, 10);
01577         /* Bail out if the octet is invalid or wrongly terminated */
01578         if ((octets[i] < 0) || (octets[i] > 255)
01579             || ((i < 3) && (*s != '.')))
01580             return 0;
01581         if (i < 3)
01582             s++;
01583     }
01584 
01585     /* Fill the IP - the dirty way */
01586     ip = octets[3];
01587     ip += octets[2] * 256;
01588     ip += octets[1] * 65536;
01589     ip += octets[0] * 16777216;
01590 
01591     return ip;
01592 }
01593 
01594 /*************************************************************************/
01595 
01605