Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Class Members | File Members | Related Pages

stuff.c

Go to the documentation of this file.
00001 /* $Id: stuff.c,v 1.1.1.1 2003/07/04 02:57:11 Mysid Exp $ */
00002 
00003 /*
00004  * Copyright (c) 1996-1997 Chip Norkus
00005  * Copyright (c) 1997 Max Byrd
00006  * Copyright (c) 1997 Greg Poma
00007  * Copyright (c) 2001 James Hess
00008  * All rights reserved.
00009  *
00010  * Redistribution and use in source and binary forms, with or without
00011  * modification, are permitted provided that the following conditions
00012  * are met:
00013  * 1. Redistributions of source code must retain the above copyright
00014  *    notice, this list of conditions and the following disclaimer.
00015  * 2. Redistributions in binary form must reproduce the above copyright
00016  *    notice, this list of conditions and the following disclaimer in the
00017  *    documentation and/or other materials provided with the distribution.
00018  * 3. Neither the name of the authors nor the names of its contributors
00019  *    may be used to endorse or promote products derived from this software
00020  *    without specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
00023  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
00026  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00027  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00028  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00031  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00032  * SUCH DAMAGE.
00033  */
00034 
00042 #include "services.h"
00043 #include "hash.h"
00044 #include "nickserv.h"
00045 #include "log.h"
00046 
00073 void
00074 breakString(int numargs, char *string, char **args, char delimiter)
00075 {
00076     char *tmp = string;
00077     int x;
00078     numargs = 1;
00079     while (*tmp) {
00080         if (*tmp == delimiter) {
00081             *tmp = 0;
00082             tmp++;
00083             numargs++;
00084         } else
00085             tmp++;
00086     }
00087 
00088     x = 0;
00089     tmp = string;
00090     while (x < numargs) {
00091         strcpy(args[x], tmp);
00092         tmp = &string[strlen(string) + 1];
00093         x++;
00094     }
00095 }
00096 
00097 
00121 /*
00122  * Written By Douglas A. Lewis <dalewis@cs.Buffalo.EDU>
00123  *
00124  * The match procedure is public domain code (from ircII's reg.c)
00125  */
00126 
00127 #if 1
00128 int
00129 match(const char *mask, const char *string)
00130 {
00131         const char  *m = mask,
00132                 *n = string,
00133                 *ma = NULL,
00134                 *na = NULL,
00135                 *mp = NULL,
00136                 *np = NULL;
00137         int     just = 0,
00138                 pcount = 0,
00139                 acount = 0,
00140                 count = 0;
00141 
00142         for (;;)
00143         {
00144                 if (*m == '*')
00145                 {
00146                         ma = ++m;
00147                         na = n;
00148                         just = 1;
00149                         mp = NULL;
00150                         acount = count;
00151                 }
00152 #if 0 
00153                 else if (*m == '%')
00154                 {
00155                         mp = ++m;
00156                         np = n;
00157                         pcount = count;
00158                 }
00159 #endif
00160                 else if (*m == '?')
00161                 {
00162                         m++;
00163                         if (!*n++)
00164                                 return 1;
00165                 }
00166                 else
00167                 {
00168                         if (*m == '\\')
00169                         {
00170                                 m++;
00171                                 /* Quoting "nothing" is a bad thing */
00172                                 if (!*m)
00173                                         return 1;
00174                         }
00175                         if (!*m)
00176                         {
00177                                 /*
00178                                  * If we are out of both strings or we just
00179                                  * saw a wildcard, then we can say we have a
00180                                  * match
00181                                  */
00182                                 if (!*n)
00183                                         return 0;
00184                                 if (just)
00185                                         return 0;
00186                                 just = 0;
00187                                 goto not_matched;
00188                         }
00189                         /*
00190                          * We could check for *n == NULL at this point, but
00191                          * since it's more common to have a character there,
00192                          * check to see if they match first (m and n) and
00193                          * then if they don't match, THEN we can check for
00194                          * the NULL of n
00195                          */
00196                         just = 0;
00197                         if (tolower(*m) == tolower(*n))
00198                         {
00199                                 m++;
00200                                 if (*n == ' ')
00201                                         mp = NULL;
00202                                 count++;
00203                                 n++;
00204                         }
00205                         else
00206                         {
00207 
00208         not_matched:
00209 
00210                                 /*
00211                                  * If there are no more characters in the
00212                                  * string, but we still need to find another
00213                                  * character (*m != NULL), then it will be
00214                                  * impossible to match it
00215                                  */
00216                                 if (!*n)
00217                                         return 1;
00218                                 if (mp)
00219                                 {
00220                                         m = mp;
00221                                         if (*np == ' ')
00222                                         {
00223                                                 mp = NULL;
00224                                                 goto check_percent;
00225                                         }
00226                                         n = ++np;
00227                                         count = pcount;
00228                                 }
00229                                 else
00230         check_percent:
00231 
00232                                 if (ma)
00233                                 {
00234                                         m = ma;
00235                                         n = ++na;
00236                                         count = acount;
00237                                 }
00238                                 else
00239                                         return 1;
00240                         }
00241                 }
00242         }
00243 }
00244 
00245 #endif
00246 
00250 void
00251 strtolower(char *str)
00252 {
00253     char *s;
00254 
00255     s = str;
00256 
00257     while (*s) {
00258         *s = tolower(*s);
00259         s++;
00260     }
00261 }
00262 
00263 char *
00264 sfgets(char *str, int len, FILE * fp)
00265 {
00266     if (!fgets(str, len, fp))
00267         return NULL;
00268     else {
00269         if (str[0])
00270             str[strlen(str) - 1] = 0;
00271         return str;
00272     }
00273 }
00274 
00285 char *
00286 xorit(char *tocrypt)
00287 {
00288     char uncrypted[60];
00289     u_int i = 0;
00290 
00291     bzero(uncrypted, 60);
00292     strncpyzt(uncrypted, tocrypt, 59);
00293     for (; i < strlen(uncrypted); i++) {
00294         uncrypted[i] ^= 0x1B;
00295         if (uncrypted[i] == ' ' || uncrypted[i] == '\n')
00296             uncrypted[i] ^= 0x1B;
00297     }
00298     strcpy(tocrypt, uncrypted);
00299     return tocrypt;
00300 }
00301 
00317 void
00318 parse_str(char **args, int argc, int startarg, char *workingstring, size_t sz)
00319 {
00320     int i, len, len2;
00321 
00322     len = 0;
00323     workingstring[0] = '\0';
00324 
00325     for (i = startarg; i < argc; i++) {
00326         if (!args[i])
00327             break;
00328         len2 = strlen(args[i]);
00329 
00330         if ((len + len2 + ((i < (argc - 1)) ? 1 : 0 )) > (sz - 1))
00331             break;
00332 
00333         strcat(workingstring, args[i]);
00334         len += len2;
00335 
00336         if ((i + 1) < argc) {
00337             strcat(workingstring, " ");
00338             len++;
00339         }
00340     }
00341 }
00342 
00354 void
00355 mask(char *user, char *host, int type, char *where)
00356 {
00357     char *blah2 = NULL;
00358 
00359     if (!strchr(host, (int)'.')) {
00360         if (!type) {
00361             sprintf(where, "%.*s@%.*s", USERLEN, user, HOSTLEN,
00362                     host);
00363             return;
00364         } else {
00365             sprintf(where, "*%.*s@%.*s", USERLEN, user, HOSTLEN,
00366                     host);
00367             return;
00368         }
00369     }
00370 
00371     blah2 = index(host, '.');
00372 
00373     /*
00374      * make sure there's more than one '.' in the name 
00375      */
00376     if (strlen(blah2) > 4) {
00377         if (inet_addr(host) != INADDR_NONE) {
00378             blah2 = host;
00379             blah2 = rindex(blah2, '.');
00380             blah2[1] = '*';
00381             blah2[2] = '\0';
00382         } else {
00383             host = index(host, '.');
00384             host -= 1;
00385             host[0] = '*';
00386         }
00387     }
00388     if (!type)
00389         sprintf(where, "%.*s@%.*s", USERLEN, user, HOSTLEN, host);
00390     else
00391         sprintf(where, "*%.*s@%.*s", USERLEN, user, HOSTLEN, host);
00392 }
00393 
00403 void *
00404 oalloc(size_t size)
00405 {
00406     void *alloctmp = 0;
00407 
00408     if (size < 1) {
00409         fprintf(stderr,
00410                 "\noalloc: Error, requested size is less than 1\n");
00411         /* Soft shutdown, with database safe, as there is a coding error */
00412         sshutdown(0);
00413     }
00414 
00415     alloctmp = calloc(size, 1);
00416 
00417     if (alloctmp == NULL) {
00418         fprintf(stderr,
00419                 "\noalloc: Error allocating memory, terminating services\n");
00420         /*
00421          * Hard shutdown, with the databases not being resaved 
00422          * (as they could be corrupted) 
00423          */
00424         sshutdown(-1);
00425     }
00426 
00427     return alloctmp;
00428 }
00429 
00430 
00440 char *
00441 flagstring(int flags, const char *bits[])
00442 {
00443     static char buf[MAXBUF] = "";
00444     int i = 0;
00445 
00446     if (!bits)
00447         return NULL;
00448 
00449     buf[0] = 0;
00450     for (i = 0; i < 32 && bits[i]; i++) {
00451         if (flags & (1 << i)) {
00452             if (*buf)
00453                 strcat(buf, " ");
00454             strcat(buf, bits[i]);
00455         }
00456     }
00457     return buf;
00458 }
00459 
00466 int
00467 flagbit(char *name, const char *bits[])
00468 {
00469     int i = 0;
00470 
00471     if (!name || !bits)
00472         return -1;
00473     for (i = 0; i < 32 && bits[i] && *bits[i]; i++)
00474         if (!strcasecmp(name, bits[i]))
00475             return i;
00476     return -1;
00477 }
00478 
00479 void
00480 tzapply(char *to)
00481 {
00482     int i = 0;
00483     if (!to || *to == ':' || *to == '\0' || strlen(to) != 3)
00484         return;
00485     for (i = 0; to[i]; i++)
00486         if (!isalpha(to[i]))
00487             return;
00488     setenv("TZ", to, 1);
00489     tzset();
00490 }
00491 
00492 #if HOSTLEN <= 63
00493 #warning HOSTLEN <= 63
00494 #endif
00495 #define HOSTMAX (HOSTLEN + 1)
00496 
00502 char *
00503 tokenEncode(char *str)
00504 {
00505     static char strn[HOSTMAX + 255];
00506     unsigned char *p;
00507     unsigned long m, v;
00508 
00509     for (p = (unsigned char *)str, m = 0, v = 0x55555; *p; p++)
00510         v = (31 * v) + (*p);
00511     sprintf(strn, "%x", (unsigned int)v);
00512     return strn;
00513 }
00514 
00520 char *
00521 genHostMask(char *host)
00522 {
00523     char tok1[USERLEN + HOSTMAX + 255];
00524     char tok2[USERLEN + HOSTMAX + 255], *p, *q;
00525     static char fin[USERLEN + HOSTMAX + 255];
00526     char fintmp[USERLEN + HOSTMAX + 255];
00527     int i, fIp = TRUE;
00528 
00529     if (!host || !strchr(host, '.')
00530         || strlen(host) >
00531         (USERLEN + HOSTMAX + 200)) return (host ? host :
00532          const_cast<char *>(""));
00533     for (i = 0; host[i]; i++)
00534         if ((host[i] < '0' || host[i] > '9') && host[i] != '.') {
00535             fIp = FALSE;
00536             fIp = FALSE;
00537         }
00538 
00539     *tok1 = *tok2 = '\0';
00540 
00541     /* It's an ipv4 address in quad-octet dot notation: last two tokens are encoded */
00542     if (fIp && strlen(host) <= 15) {
00543         if ((p = strrchr(host, '.'))) {
00544             *p = '\0';
00545             strcpy(tok1, host);
00546             strcpy(tok2, p + 1);
00547             *p = '.';
00548         }
00549         if ((p = strrchr(tok1, '.'))) {
00550             strcpy(fintmp, tokenEncode(p + 1));
00551             *p = '\0';
00552         }
00553         sprintf(fin, "%s.%s.%s.imsk", tokenEncode(tok2), fintmp, tok1);
00554         return fin;
00555     }
00556 
00557     /* It's a resolved hostname, hash the first token */
00558     if ((p = strchr(host, '.'))) {
00559         *p = '\0';
00560         strcpy(tok1, host);
00561         strcpy(fin, p + 1);
00562         *p = '.';
00563     }
00564 
00565     /* Then separately hash the domain */
00566     if ((p = strrchr(fin, '.'))) {
00567         --p;
00568         while (p > fin && *(p - 1) != '.')
00569             p--;
00570     }
00571     if (p && (q = strrchr(fin, '.'))) {
00572         i = (unsigned char)*p;
00573         *p = '\0';
00574         *q = '\0';
00575         strcat(tok2, fin);
00576         *p = (unsigned char)i;
00577         if (*p == '.')
00578             strcat(tok2, tokenEncode(p + 1));
00579         else
00580             strcat(tok2, tokenEncode(p));
00581         *q = '.';
00582         strcat(tok2, q);
00583     } else
00584         strcpy(tok2, fin);
00585     strcpy(tok1, tokenEncode(tok1));
00586     snprintf(fin, HOSTLEN, "%s.%s.hmsk", tok1, tok2);
00587 
00588     return fin;
00589 }
00590 
00596 char *
00597 str_dup(const char *input)
00598 {
00599     char *buf;
00600     int len;
00601 
00602     for (buf = (const_cast<char *>(input)); *buf; buf++);
00603     buf = static_cast <char *>((oalloc(1 + (len = (buf - input)))));
00604     return static_cast <char *>(memcpy(buf, input, len + 1));
00605 }
00606 
00613 char *
00614 strn_dup(const char *input, int max)
00615 {
00616     char *buf;
00617     int len;
00618 
00619     for (buf = (const_cast<char *>(input));
00620          *buf && ((buf - input) < max); buf++);
00621     len = buf - input;
00622     buf = static_cast<char *>(oalloc(1 + len));
00623     buf[len] = '\0';
00624     return (char *)memcpy(buf, input, len);
00625 }
00626 
00631 MaskData *
00632 make_mask()
00633 {
00634     MaskData *mask = (MaskData *) oalloc(sizeof(MaskData));
00635     mask->nick = mask->user = mask->host = (char *)0;
00636 
00637     return mask;
00638 }
00639 
00645 void
00646 free_mask(MaskData *mask)
00647 {
00648     if (mask->nick)
00649         FREE(mask->nick);
00650     if (mask->user)
00651         FREE(mask->user);
00652     if (mask->host)
00653         FREE(mask->host);
00654     FREE(mask);
00655 }
00656 
00663 int
00664 split_userhost(const char *input_host, MaskData *data)
00665 {
00666     extern FILE *corelog;
00667     char *host, *p, *p2;
00668     char *tmpp, *lastp;
00669 #define IrcStr(point) ((!*(point)) ? "*" : (point))
00670 
00671     if (!input_host || !data) {
00672         logDump(corelog, "split_userhost: Null pointer (host=%p,data=%p)",
00673                 input_host, data);
00674         fflush(corelog);
00675 
00676         if (data)
00677             data->nick = data->user = data->host = NULL;
00678         return -1;
00679     }
00680 
00681     host = str_dup(input_host);
00682 
00683     for (p = host; *p && *p != '!' && *p != '@'; p++);
00684 
00685     if (!*p) {
00686         data->nick = strn_dup(IrcStr(host), NICKLEN);
00687         data->user = str_dup("*");
00688         data->host = str_dup("*");
00689         FREE(host);
00690         return 0;
00691     }
00692 
00693     if (*p == '@') {
00694         for (tmpp = p + 1, lastp = NULL; *tmpp; tmpp++)
00695             if (*tmpp == '@')
00696                 lastp = tmpp;
00697         if (lastp && *lastp == *p)
00698             p = lastp;
00699         *p = '\0';
00700         data->nick = str_dup("*");
00701         data->user = strn_dup(IrcStr(host), USERLEN);
00702         data->host = strn_dup(IrcStr(p + 1), HOSTLEN);
00703         FREE(host);
00704         return 0;
00705     }
00706 
00707     if (*p == '!') {
00708         for (tmpp = p + 1, lastp = NULL; *tmpp && *tmpp != '@'; tmpp++)
00709             if (*tmpp == '!')
00710                 lastp = tmpp;
00711         if (lastp && *lastp == *p)
00712             p = lastp;
00713 
00714         for (p2 = p + 1; *p2 && *p2 != '@'; p2++);
00715         if (*p2 == '@') {
00716             *p = *p2 = '\0';
00717             data->nick = strn_dup(IrcStr(host), NICKLEN);
00718             data->user = strn_dup(IrcStr(p + 1), USERLEN);
00719             data->host = strn_dup(IrcStr(p2 + 1), HOSTLEN);
00720             FREE(host);
00721             return 0;
00722         } else {
00723             *p = '\0';
00724             data->nick = strn_dup(IrcStr(host), NICKLEN);
00725             data->user = strn_dup(IrcStr(p + 1), USERLEN);
00726             data->host = str_dup("*");
00727             FREE(host);
00728             return 0;
00729         }
00730     }
00731 
00732     FREE(host);
00733     return -1;
00734 }
00735 
00736 
00744 void AppendBuffer(char **buf, const char *add)
00745 {
00746      char *newbuf, *x;
00747 
00748      /* x = newbuf = new char[ ((buf && *buf ? strlen(*buf) : 0)) + strlen(add) + 4]; */
00749 
00750      x = newbuf = (char *)oalloc(((*buf ? strlen(*buf) : 0)) + strlen(add) + 4);
00751      if (!newbuf) return;
00752      if (*buf)
00753      {
00754        bzero( newbuf, (*buf ? strlen( *buf ):0) + strlen(add) + 2 );
00755        memcpy( newbuf, *buf, strlen(*buf) );
00756        x = newbuf + strlen(*buf);
00757      } else x = newbuf;
00758      strcpy(x, add); /* this is ok */
00759      if (*buf) {
00760          FREE(*buf);
00761      }
00762      *buf = newbuf;
00763      return;
00764 }
00765 
00766 
00774 void SetDynBuffer(char **buf, const char *newStr)
00775 {
00776     char *newbuf, *x;
00777 
00778     if (newStr) {
00779         x = newbuf = (char *)oalloc(strlen(newStr) + 1);
00780         if (!newbuf)
00781             return;
00782         strcpy(x, newStr);
00783     }
00784     else
00785         newbuf = NULL;
00786 
00787     if (*buf)
00788         FREE(*buf);
00789     *buf = newbuf;
00790     return;
00791 }
00792 
00793 /* --------------------------------------------------------------------- */
00794 /* Registration Identifiers */
00795 
00796 void RegId::SetNext(RegId &topCounter)
00797 {
00798     a = topCounter.a;
00799     b = topCounter.b;
00800         
00801     if (b == IDVAL_MAX) {
00802         if (topCounter.a == IDVAL_MAX) {
00803             logDump(corelog, "::Out of nick IDs at (%d, %d)::",
00804                                 topCounter.a, topCounter.b);
00805             sSend("WALLOPS :Error! Out of nick IDs at (%d, %d)::",
00806                                 topCounter.a, topCounter.b);
00807                     sshutdown(-1);
00808         }
00809         topCounter.a++;
00810         topCounter.b = 0;
00811     }
00812     else
00813         topCounter.b++;
00814 }
00815 
00816 
00817 void RegId::SetDirect(RegId &topCounter, IdVal aVal, IdVal bVal)
00818 {
00819     a = aVal;
00820     b = bVal;
00821 
00822     if (topCounter.a < aVal)
00823         topCounter.a = aVal;
00824     if (topCounter.a <= aVal && topCounter.b <= bVal) {
00825         if (topCounter.b == IDVAL_MAX)
00826         {
00827             topCounter.a = aVal+1;
00828             topCounter.b = 0;
00829         }
00830         else
00831             topCounter.b = bVal+1;
00832     }
00833 }
00834 
00835 RegNickList *RegId::getNickItem()
00836 {
00837     RegNickIdMap *ptrMap;
00838 
00839     ptrMap = getIdMap();
00840 
00841     if (!ptrMap || !ptrMap->nick)
00842         return NULL;
00843     return ptrMap->nick;
00844 }
00845 
00846 const char *RegId::getNick()
00847 {
00848     RegNickList *ptrNick;
00849 
00850     ptrNick = getNickItem();
00851 
00852     if (ptrNick == NULL) {
00853         if (a == 0)
00854         {
00855             switch(b)
00856             {
00857                 case 1: return NETWORK;
00858                 case 2: return "*";
00859 
00860                 default:;
00861             }
00862         }
00863         return NULL;
00864     }
00865     return ptrNick->nick;
00866 }
00867 
00868 const char *RegId::getChan()
00869 {
00870     abort(); return NULL;
00871 }
00872 
00873 /*HashKeyVal RegId::getHashKey() const
00874 {
00875     HashKeyVal x = (a ^ 27);
00876 
00877     x += (b * IDVAL_MAX);
00878 
00879     return x;
00880 }*/
00881 
00882 RegNickIdMap *RegId::getIdMap()
00883 {
00884     HashKeyVal hashEnt;
00885     RegNickIdMap *mapPtr;
00886 
00887     hashEnt = this->getHashKey() % IDHASHSIZE;
00888 
00889     mapPtr = LIST_FIRST(&RegNickIdHash[hashEnt]);
00890 
00891     while( mapPtr )
00892     {
00893 
00894         if ((*mapPtr).id == (*this))
00895             return mapPtr;
00896         mapPtr = LIST_NEXT(mapPtr, id_lst);
00897     }
00898 
00899     return NULL;
00900 }
00901 
00902 /* Encode a URL -Mysid*/
00903 
00904 char *urlEncode(const char *in)
00905 {
00906     static char* out = 0;
00907     int i, x = 0, l = 0;
00908 
00909     if (in == 0) return 0;
00910 
00911     if (out)
00912         FREE(out);
00913 
00914     for(i = 0; in[i]; i++)
00915     {
00916         if (isalnum(in[i]))
00917             l++;
00918         else
00919             l+=3;
00920     }
00921 
00922     out = (char *) oalloc(l + 1);
00923     for(i = 0; in[i]; i++)
00924     {
00925         if (isalnum(in[i]))
00926             out[x++] = in[i];
00927         else {
00928             l+=3;
00929             out[x++] = '%';
00930             x += sprintf(out + x, "%.2X", in[i]);
00931         }
00932     }
00933     return out;
00934 }
00935 
00936 void rshift_argv(char **args, int x, int numargs)
00937 {
00938         int i;
00939 
00940         for (i = 0; i < (numargs - x); i++)
00941                 args[i] = args[i + x];
00942         args[numargs - x] = NULL;
00943 }
00944 
00945 /* --------------------------------------------------------------------- */
00946 
00947 /* $Id: stuff.c,v 1.1.1.1 2003/07/04 02:57:11 Mysid Exp $ */

Generated at Sat Oct 25 20:56:10 2003 for Services using Doxygen.
Services Copyr. 1996-2001 Chip Norkus, Max Byrd, Greg Poma, Michael Graff, James Hess, Dafydd James. All rights reserved See LICENSE for licensing information.