home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Web / Utilities / wwwcount-2.3 / parse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-02  |  41.8 KB  |  1,848 lines

  1. #include "combine.h"
  2. #include "count.h"
  3. #include "cdebug.h"
  4.  
  5. #ifdef SYS_WIN32
  6. #include "configNT.h"
  7. #else
  8. #include "config.h"
  9. #endif
  10.  
  11.  
  12. /*
  13.  *  ParseAuthorizationList() -   parses the authorization list
  14.  *
  15.  *  RCS:
  16.  *      $Revision: 2.3 $
  17.  *      $Date: 1996/05/03 02:20:22 $
  18.  *
  19.  *  Security:
  20.  *      Unclassified
  21.  *
  22.  *  Description:
  23.  *      text
  24.  *
  25.  *  Input Parameters:
  26.  *      type    identifier  description
  27.  *
  28.  *      text
  29.  *
  30.  *  Output Parameters:
  31.  *      type    identifier  description
  32.  *
  33.  *      text
  34.  *
  35.  *  Return Values:
  36.  *      value   description
  37.  *
  38.  *  Side Effects:
  39.  *      text
  40.  *
  41.  *  Limitations and Comments:
  42.  *      text
  43.  *
  44.  *  Development History:
  45.  *      who                 when        why
  46.  *      muquit@semcor.com   05-Jun-95   first cut
  47.  */
  48.  
  49. int ParseConfig ()
  50. {
  51.     FILE
  52.         *fp;
  53.  
  54.     int
  55.         i;
  56.  
  57.     char
  58.         buf[MaxLineLength+1];
  59.  
  60.     i=0;
  61.  
  62.     *buf='\0';
  63.     (void) sprintf(buf,"%s/%s",ConfigDir,ConfigFile);
  64.     fp = fopen(buf, "r");
  65.     if (fp == (FILE *) NULL)
  66.     {
  67.         return (ConfigOpenFailed);
  68.     }
  69.  
  70.     /*
  71.     ** first block: automatic file creation. If the block contains 1,
  72.     ** automatic file creation is allowed. if 0, not allowed.
  73.     ** automatic file creation is a bad thing, but some sites may want
  74.     ** it because they are running their server behind a firewall and
  75.     ** they trust their users
  76.     ** BLOCK 1
  77.     */
  78.  
  79.     *buf='\0';
  80.     (void) GetLine(fp, buf);
  81.     if (strcmp(buf, "{") != 0)
  82.     {
  83.         (void) fclose ((FILE *) fp);
  84.         return(NoAutofcBlock);
  85.     }
  86.     while (True)
  87.     {
  88.         if (!GetLine (fp, buf))
  89.         {
  90.             (void) fclose ((FILE *) fp);
  91.              return (UnpexpectedEof);                       
  92.         }
  93.         if (strcmp(buf, "}") == 0)
  94.             break;
  95.         RemoveTrailingSp (buf);
  96.         Gauto_file_creation=atoi(buf);
  97.     }
  98.  
  99.     /*
  100.     ** strict mode block
  101.     ** BLOCK 2
  102.     */
  103.     *buf='\0';
  104.     (void) GetLine(fp, buf);
  105.     if (strcmp(buf, "{") != 0)
  106.     {
  107.         (void) fclose ((FILE *) fp);
  108.         return(NoStrictBlock);
  109.     }
  110.     while (True)
  111.     {
  112.         if (!GetLine (fp, buf))
  113.         {
  114.             (void) fclose ((FILE *) fp);
  115.              return (UnpexpectedEof);                       
  116.         }
  117.         if (strcmp(buf, "}") == 0)
  118.             break;
  119.         RemoveTrailingSp (buf);
  120.         Gstrict_mode=atoi(buf);
  121.     }
  122.  
  123.     /*
  124.     ** rgb coloname lookup 
  125.     ** BLOCK 3
  126.     */
  127.     *buf='\0';
  128.     (void) GetLine(fp, buf);
  129.     if (strcmp(buf, "{") != 0)
  130.     {
  131.         (void) fclose ((FILE *) fp);
  132.         return(NoRgbMappingBlock);
  133.     }
  134.     while (True)
  135.     {
  136.         if (!GetLine (fp, buf))
  137.         {
  138.             (void) fclose ((FILE *) fp);
  139.              return (UnpexpectedEof);                       
  140.         }
  141.         if (strcmp(buf, "}") == 0)
  142.             break;
  143.         RemoveTrailingSp (buf);
  144.         GrgbMappingIsError=atoi(buf);
  145.     }
  146.  
  147.     /*
  148.     ** ignore count block
  149.     ** BLOCK 4
  150.     */
  151.     *buf='\0';
  152.     (void) GetLine (fp, buf);
  153.     if (strcmp (buf, "{") != 0)
  154.     {
  155.         (void) fclose ((FILE *) fp);
  156.         return (NoIgnoreHostsBlock);
  157.     }
  158.  
  159.     while (True)
  160.     {
  161.         if (!GetLine (fp, buf))
  162.         {
  163.             (void) fclose ((FILE *) fp);
  164.             return (UnpexpectedEof);
  165.         }
  166.  
  167.         if (strcmp(buf, "}") == 0)
  168.             break;
  169.         RemoveTrailingSp (buf);
  170.         GignoreSite[Gsite++] = mystrdup (buf);
  171.     }
  172.  
  173.         if (Gsite > 0)
  174.         {
  175.             Debug2("Ignore Hosts:",0,0);
  176.         }
  177.         else
  178.         {
  179.             Debug2("Will count access from any host",0,0);
  180.         }
  181.         for (i=0; i < Gsite; i++)
  182.         {
  183.             Debug2("Site[%d] %s",i,GignoreSite[i]);
  184.         }
  185.  
  186. #ifdef ACCESS_AUTH
  187.     (void) GetLine (fp, buf);
  188.     if (strcmp(buf, "{") != 0)
  189.     {
  190.        (void) fclose ((FILE *) fp);
  191.         return (NoRefhBlock);
  192.     }
  193.     while (True)
  194.     {
  195.         if (!GetLine (fp, buf))
  196.         {
  197.             (void) fclose ((FILE *) fp);
  198.             return (UnpexpectedEof);
  199.         }
  200.         if (strcmp (buf, "}") == 0)
  201.             break;
  202.         RemoveTrailingSp (buf);
  203.         GrefererHost[Grhost++]= mystrdup(buf);
  204.  
  205.     }
  206.  
  207.         if (Grhost > 0)
  208.         {
  209.             Debug2("-Referer Hosts-",0,0);
  210.         }
  211.         else
  212.         {
  213.             Debug2("Grhost: %d", Grhost,0);
  214.         }
  215.         for (i=0; i < Grhost; i++)
  216.         {
  217.             Debug2("Referer[%d] %s",i,GrefererHost[i]);
  218.         }
  219.  
  220. #endif /* ACCESS_AUTH */
  221.     (void) fclose ((FILE *) fp);
  222.     return (0);
  223. }
  224.  
  225. #ifdef TEST
  226.  
  227. void main (argc, argv)
  228. int
  229.     argc;
  230. char
  231.     **argv;
  232. {
  233.     ParseAuthorizationList ();
  234. }
  235. #endif /* TEST */
  236.  
  237.  
  238. /*
  239.  *  GetLine () - reads a line from the passed file pointer and puts the
  240.  *               line in the passed array
  241.  *
  242.  *  RCS:
  243.  *      $Revision: 2.3 $
  244.  *      $Date: 1996/05/03 02:20:22 $
  245.  *
  246.  *  Security:
  247.  *      Unclassified
  248.  *
  249.  *  Description:
  250.  *      borrowed from wusage 2.3
  251.  *
  252.  *  Input Parameters:
  253.  *      type    identifier  description
  254.  *
  255.  *      text
  256.  *
  257.  *  Output Parameters:
  258.  *      type    identifier  description
  259.  *
  260.  *      text
  261.  *
  262.  *  Return Values:
  263.  *      value   description
  264.  *
  265.  *  Side Effects:
  266.  *      text
  267.  *
  268.  *  Limitations and Comments:
  269.  *      text
  270.  *
  271.  *  Development History:
  272.  *      who                 when        why
  273.  *      muquit@semcor.com   05-Jun-95   first cut
  274.  */
  275.  
  276. int GetLine (fp, string)
  277. FILE
  278.     *fp;
  279. char
  280.     *string;
  281. {
  282.     int
  283.         s,
  284.         i;
  285.  
  286.     int
  287.         length;
  288.  
  289.     char
  290.         *x;
  291.     while (!feof (fp))
  292.     {
  293.         x = fgets (string, 80, fp);
  294.         if (x == (char *) NULL)
  295.             return (0);
  296.  
  297.         if (*string == '#') /* a comment */
  298.             continue;
  299.  
  300.         if (string[(int) strlen(string)-1] == '\n')
  301.             string[(int) strlen(string)-1] = '\0'; /* NULL terminate*/
  302.  
  303.         if (*string == '\0')
  304.             continue;
  305.  
  306.         length = (int) strlen(string);
  307.         s=0;
  308.  
  309.         for (i=0; i < length; i++)
  310.         {
  311.             if (isspace (string[i]))
  312.                 s++;
  313.             else
  314.                 break;
  315.         }
  316.  
  317.         if (s)
  318.         {
  319.             char buf[81];
  320.             (void) strcpy (buf, string+s);
  321.             (void) strcpy(string,buf);
  322.         }
  323.  
  324.         length = (int) strlen(string);
  325.         for (i=(length-1); i >= 0; i--)
  326.         {
  327.             if (isspace(string[i]))
  328.                 string[i]='\0';
  329.             else
  330.                 break;
  331.         }
  332.         return (1);
  333.     }
  334.     return (0);
  335. }
  336.  
  337. /*
  338. ** from wusage 2.3
  339. */
  340. void RemoveTrailingSp (string)
  341. char
  342.     *string;
  343. {
  344.     while (True)
  345.     {
  346.         int
  347.             l;
  348.  
  349.         l = (int) strlen (string);
  350.         if (!l)
  351.             return;
  352.  
  353.         if (string[l-1] == ' ')
  354.             string[l-1] = '\0';
  355.         else
  356.             return;
  357.     }
  358. }
  359.  
  360. /*
  361. ** duplicate a string
  362. */
  363. char *mystrdup (string)
  364. char
  365.     *string;
  366. {
  367.     char
  368.         *tmp;
  369.  
  370.     if (string == (char *) NULL)
  371.         return ((char *) NULL);
  372.  
  373.     tmp = (char *) malloc ((int) strlen(string) + 1);
  374.  
  375.     if (tmp == (char *) NULL)
  376.         return ((char *) NULL);
  377.  
  378.     (void) strcpy(tmp, string);
  379.     return (tmp);
  380. }
  381.  
  382. /*
  383. ** check if the data file has correct ownership
  384. */
  385.  
  386. /*
  387. ** Return values
  388. ** 0 - nothing matches (group or owner)
  389. ** 1 - owner of the file and the owner found in query string matches
  390. ** 2 - memory allocation problem
  391. ** 3 - owner of the file and the owner found in query string matches but
  392. **     the group id of the child process of httpd and the group id of the
  393. **     file does not match
  394. */
  395.  
  396. #ifdef _USE_ME_PLEASE_
  397. int CheckOwner (owner,file)
  398. char
  399.     *owner;
  400. char
  401.     *file;
  402. {
  403.     char
  404.         *tmp;
  405.  
  406.     struct stat
  407.         statbuf;
  408.  
  409.     int
  410.         uid,
  411.         gid;
  412.  
  413.     struct passwd
  414.         *p;
  415.  
  416.     tmp = mystrdup(owner);
  417.     if (tmp == (char *) NULL)
  418.         return 2;
  419.  
  420.     while ((p=getpwent()) != NULL)
  421.     {
  422.         if (strcmp(tmp, p->pw_name) == 0)
  423.         {
  424.             uid = p->pw_uid;                        
  425.             stat(file, &statbuf);
  426.             if (uid == statbuf.st_uid)
  427.             {
  428.                 /*
  429.                 ** now check the group id of the child process of httpd
  430.                 ** and group id of the data file, they must match
  431.                 */
  432.                 gid = getgid();
  433.                 if (gid != statbuf.st_gid)
  434.                 {
  435.                     char
  436.                         buf[BUFSIZ];
  437.                     *buf = '\0';
  438.                     (void) sprintf (buf, "Group Id of the counter data file \"%s\" is %d, it should be %d, httpd's child processes run with group id %d",file,statbuf.st_gid,gid,gid);
  439.                 Warning(buf);
  440.                 (void) free ((char *) tmp);
  441.                     return 3;
  442.                 }
  443.                 (void) free ((char *) tmp);
  444.                 return (1);
  445.             }
  446.             else
  447.             {
  448.                 (void) free ((char *) tmp);
  449.                 return (0); 
  450.             }
  451.         } 
  452.     }
  453.  
  454.     (void) free ((char *) tmp);
  455.     return (0);
  456. }
  457. #endif /* _USE_ME_PLEASE */
  458. /*
  459.  *  ParseQueryString() - parses the QUERY_STRING for Count.cgi
  460.  *
  461.  *  RCS:
  462.  *      $Revision: 2.3 $
  463.  *      $Date: 1996/05/03 02:20:22 $
  464.  *
  465.  *  Security:
  466.  *      Unclassified
  467.  *
  468.  *  Description:
  469.  *      text
  470.  *
  471.  *  Input Parameters:
  472.  *      type    identifier  description
  473.  *
  474.  *      char        *qs
  475.  *      DigitInfo   *digit_info
  476.  *      FrameInfo   *frame_info
  477.  *
  478.  *  Output Parameters:
  479.  *      type    identifier  description
  480.  *
  481.  *      DigitInfo   *digit_info
  482.  *      FrameInfo   *frame_info
  483.  *
  484.  *  Return Values:
  485.  *      value   description
  486.  *      0   on success
  487.  *      1   on failure
  488.  *
  489.  *  Side Effects:
  490.  *      text
  491.  *
  492.  *  Limitations and Comments:
  493.  *      text
  494.  *
  495.  *  Development History:
  496.  *      who                 when        why
  497.  *      muquit@semcor.com   22-Aug-95   first cut
  498.  */
  499.  
  500. int ParseInteger(given,sets,min,max)
  501. char
  502.     *given;
  503. int
  504.     *sets;
  505. int
  506.     min,
  507.     max;
  508. {
  509.     if (sscanf(given, "%d", sets) == 1)
  510.     {
  511.         *sets = AbsoluteValue(*sets);
  512.         if (*sets >= min && ( max == 0 || *sets <= max ))
  513.             return(True);
  514.     }
  515.     return(False);
  516. }
  517.  
  518. int ParseDigitsString(given,sets,maxlen)
  519. char 
  520.     *given;
  521. char 
  522.     *sets;
  523. int 
  524.     maxlen;
  525. {
  526.     for ( ; *given != (char) 0; given++, sets++, maxlen-- )
  527.     {
  528.         if (isdigit(*given) && maxlen >= 0)
  529.             *sets = *given;
  530.         else
  531.             return(False);
  532.     }
  533.     return(True);
  534. }
  535.  
  536. int ParseOptionString(given,sets)
  537. char
  538.     *given;
  539. int
  540.     *sets;
  541. {
  542.    if (mystrcasecmp(given,"counter") == 0)
  543.    {
  544.         *sets=SHOW_COUNTER;
  545.         return (True);
  546.    } 
  547.    else if (mystrcasecmp(given,"clock") == 0)
  548.    {
  549.         *sets=SHOW_CLOCK;
  550.         return (True);
  551.    }
  552.    else if (mystrcasecmp(given,"date") == 0)
  553.    {
  554.         *sets=SHOW_DATE;
  555.         return (True);
  556.    }
  557.    else if (mystrcasecmp(given,"image") == 0)
  558.    {
  559.         *sets=SHOW_GIF_FILE;
  560.         return (True);
  561.    }
  562.    else
  563.         return (False);
  564.  
  565. return (False);
  566. }
  567.  
  568. int ParseDateFormat(given,sets)
  569. char
  570.     *given;
  571. int
  572.     *sets;
  573. {
  574.     if (mystrcasecmp(given,"MMDDYY") == 0)
  575.     {
  576.        *sets=DATE_MMDDYY;
  577.        return(True); 
  578.     }
  579.     else if (mystrcasecmp(given,"DDMMYY") == 0)
  580.     {
  581.        *sets=DATE_DDMMYY;
  582.        return(True); 
  583.     }
  584.     else if (mystrcasecmp(given,"YYMMDD") == 0)
  585.     {
  586.        *sets=DATE_YYMMDD;
  587.        return(True); 
  588.     }
  589.     else if (mystrcasecmp(given,"YYDDMM") == 0)
  590.     {
  591.        *sets=DATE_YYDDMM;
  592.        return(True); 
  593.     }
  594.     else if (mystrcasecmp(given,"MMYYDD") == 0)
  595.     {
  596.        *sets=DATE_MMYYDD;
  597.        return(True); 
  598.     }
  599.     else if (mystrcasecmp(given,"DDYYMM") == 0)
  600.     {
  601.        *sets=DATE_MMYYDD;
  602.        return(True); 
  603.     }
  604.     else
  605.         return (False);
  606.  
  607. return (False);
  608. }
  609.  
  610. int ParseBool(given,sets )
  611. char 
  612.     *given;
  613. int 
  614.     *sets;
  615. {
  616.     if ((int)strlen(given) != 1)
  617.         return(False);
  618.  
  619.     switch(*given)
  620.     {
  621.         case '1':
  622.         case 'T':
  623.         case 't':
  624.         case 'Y':
  625.         case 'y':
  626.             *sets = True;
  627.             break;
  628.         case '0':
  629.         case 'F':
  630.         case 'f':
  631.         case 'N':
  632.         case 'n':
  633.             *sets = False;
  634.             break;
  635.         default:
  636.             return(False);
  637.     }
  638.     return(True);
  639. }
  640.  
  641. #if __STDC__
  642. int ParseRGB(char *given,unsigned char *set_r,unsigned char *set_g,
  643.     unsigned char *set_b)
  644. #else
  645. int ParseRGB(given,set_r,set_g,set_b)
  646. char 
  647.     *given;
  648. unsigned char 
  649.     *set_r, 
  650.     *set_g, 
  651.     *set_b;
  652. #endif
  653. {
  654.     int
  655.         rc,
  656.         red, 
  657.         green, 
  658.         blue, 
  659.         items,
  660.         found = False;
  661.  
  662.     FILE 
  663.         *handle = NULL;
  664.  
  665.     char
  666.         rgbname[MaxLineLength],
  667.         fromfile[MaxLineLength],
  668.         *emsg = fromfile;                   /* Reuse space! */
  669.  
  670.     rc=True;
  671.     /*rc=sscanf(given, "%d;%d;%d",&red,&green,&blue);*/
  672.  
  673.     if ((sscanf(given, "%d;%d;%d",&red,&green,&blue) == 3) ||
  674.         (sscanf(given,"%02x%02x%02x",&red,&green,&blue) == 3) ||
  675.         (sscanf(given,"#%02x%02x%02x",&red,&green,&blue) == 3) ||
  676.         (sscanf(given,"%*02x%02x%*02x%02x%*02x%02x",&red,&green,&blue) == 6)||
  677.         (sscanf(given,"#%*02x%02x%*02x%02x%*02x%02x",&red,&green,&blue) == 6))
  678.     {
  679.         rc=True;
  680.     }
  681.     else
  682.         rc=False;
  683.  
  684.  
  685.     if (rc == False) 
  686.     {
  687.         handle=fopen(RgbMappingDict, "r");
  688.         if (handle != (FILE *) NULL)
  689.         {
  690.             while(fgets(fromfile, sizeof(fromfile), handle) )
  691.             {
  692.                 /*items=sscanf(fromfile,"%d %d %d %s %*s",
  693.                     &red,&green,&blue,rgbname);*/
  694.                 items=sscanf(fromfile,"%d %d %d %[^\n]\n",
  695.                     &red,&green,&blue,rgbname);
  696.                  if (items != 4)
  697.                     continue;
  698.                  if (mystrcasecmp(rgbname, given) == 0)
  699.                  {
  700.                     if ( Gdebug == True )
  701.                        fprintf(stderr, "Found \"%d %d %d %s\" in %s\n",
  702.                                red, green, blue, rgbname, RgbMappingDict);
  703.                         if (GrgbMappingIsError == 1)
  704.                         {
  705.                             sprintf(emsg, "Please specify \"%d;%d;%d\" instead of \"%s\" for color.", red, green, blue, rgbname);
  706.                             PrintHeader();
  707.                             StringImage(emsg);
  708.                         }
  709.                         else
  710.                         {
  711.                             found=True;
  712.                             break;
  713.                         }
  714.                    }
  715.             }
  716.             (void) fclose(handle);
  717.             if ( found == False )
  718.                 return(False);
  719.         }
  720.     }
  721.  
  722.     if ( red   < 0 ) red   = 0; else if ( red   > MaxRGB ) return(False);
  723.     if ( green < 0 ) green = 0; else if ( green > MaxRGB ) return(False);
  724.     if ( blue  < 0 ) blue  = 0; else if ( blue  > MaxRGB ) return(False);
  725.  
  726.     *set_r = (unsigned char) red;
  727.     *set_g = (unsigned char) green;
  728.     *set_b = (unsigned char) blue;
  729.     return(True);
  730. }
  731.  
  732. int ParseSize(given,set_w,set_h )
  733. char
  734.     *given;
  735. int 
  736.     *set_w, 
  737.     *set_h;
  738. {
  739.     int
  740.         rc;
  741.  
  742.     rc=sscanf(given, "%d;%d", set_w, set_h);
  743.  
  744.     if (rc != 2)
  745.         return(False);
  746.  
  747.     *set_w = AbsoluteValue(*set_w);
  748.     *set_h = AbsoluteValue(*set_h);
  749.     return(True);
  750. }
  751.  
  752. int ParseError(keyword, value, current_rc, blurb)
  753. char
  754.     *keyword,
  755.     *value;
  756. int
  757.     current_rc;
  758. char
  759.     *blurb;
  760. {
  761.     char 
  762.         emsg[MaxTextLength];
  763.  
  764.     sprintf(emsg, "Parameter \"%s=\" followed by %s value \"%s\"", 
  765.         keyword, blurb, value);
  766.  
  767.     PrintHeader();
  768.     StringImage(emsg);
  769.     current_rc++;
  770.     return(current_rc);
  771. }
  772.  
  773. int ParseQueryString(qs, digit_info, frame_info)
  774. char
  775.     *qs;
  776. DigitInfo
  777.     *digit_info;
  778. FrameInfo
  779.     *frame_info;
  780. {
  781.     char
  782.         emsg[MaxTextLength],
  783.         query_string[MaxTextLength];
  784.  
  785.     char
  786.         *keyword,
  787.         *value,
  788.         *p;
  789.  
  790.     int
  791.         dummy;
  792.  
  793.     int
  794.         rc=0;
  795.  
  796. #define MissingValue    DefaultThickness
  797.  
  798.     /*
  799.     ** default opaque color. 
  800.     */
  801.     digit_info->replace_color=False;
  802.     digit_info->opaque_red=(unsigned char) 0;
  803.     digit_info->opaque_green=(unsigned char) 255;
  804.     digit_info->opaque_blue=(unsigned char) 0;
  805.  
  806.     digit_info->pen_red=(unsigned char) 0;
  807.     digit_info->pen_green=(unsigned char) 255;
  808.     digit_info->pen_blue=(unsigned char) 255;
  809.  
  810.     frame_info->width=(unsigned int) MissingValue;
  811.     digit_info->alpha=(unsigned int) MissingValue;
  812.     digit_info->width=(unsigned int) 15;
  813.     digit_info->height=(unsigned int) 20;
  814.     digit_info->maxdigits=(int) DefaultMaxDigits;
  815.     digit_info->leftpad=(unsigned int) DefaultLeftpad;
  816.     frame_info->matte_color.red=(unsigned char) Default_FrameRed;
  817.     frame_info->matte_color.green=(unsigned char) DefaultFrameGreen;
  818.     frame_info->matte_color.blue=(unsigned char) DefaultFrameBlue;
  819.     digit_info->alpha_red=(unsigned char) DefaultTransparentRed;
  820.     digit_info->alpha_green=(unsigned char) DefaultTransparentGreen;
  821.     digit_info->alpha_blue=(unsigned char) DefaultTransparentBlue;
  822.     digit_info->st=(unsigned int) DefaultStartCount;
  823.     digit_info->show=(unsigned int) DefaultShowCount;
  824.     digit_info->increment_counter=(unsigned int) True;
  825.     digit_info->negate=False;
  826.     digit_info->rotate=False;
  827.     digit_info->rotate_degrees=270;
  828.     (void) strcpy(digit_info->datafile,DefaultDatafile);
  829.     (void) strcpy(digit_info->ddhead,DefaultDigitsStyle);
  830.     *digit_info->literal = '\0';
  831.     digit_info->display_type=SHOW_COUNTER;
  832.     *digit_info->time_z='\0';
  833.     digit_info->date_format=DATE_MMDDYY;
  834.     digit_info->time_format=12;
  835.     digit_info->use_strip=True;
  836.     digit_info->comma=False;
  837.     digit_info->nsegment=15;
  838.     *digit_info->gif_file='\0';
  839.  
  840.     (void) strcpy(query_string,qs);
  841.     p = query_string;
  842.  
  843.     Debug2("Parsing \"%s\"",p,0);
  844.  
  845.     while((keyword=mystrtok(p, "=")) != (char *) NULL)
  846.     {
  847.         p = (char *) NULL;
  848.         value=mystrtok(p,ParamDelimiters);
  849.         if (value == (char *) NULL)
  850.         {
  851.             (void) sprintf(emsg,
  852.                 "Parameter \"%s=\" requires a value\n", keyword);
  853.             PrintHeader();
  854.             StringImage(emsg);
  855.             rc++;
  856.             break;
  857.         }
  858.  
  859.         Debug2("Keyword={%s}; value={%s}",keyword,value);
  860.  
  861.         /********************************************************************
  862.         * Use of "mystrcasecmp()" is slow but fast to implement.  Will fix.
  863.         * Error return does not occur until after entire query string is
  864.         * parsed; this allows all errors to be shown to user in first pass.
  865.         * Hence "rc" is incremented with each error found.
  866.         ********************************************************************/
  867.         if (mystrcasecmp(keyword,"ft") == 0)
  868.         {
  869.             if (!ParseInteger(value,&dummy,0,255))
  870.                 rc = ParseError(keyword,value,rc,
  871.                     "badly specified frame thickness");
  872.             else
  873.                 frame_info->width= (unsigned int) dummy;
  874.         }
  875.         else if (mystrcasecmp(keyword,"frgb") == 0)
  876.         {
  877.             if ( ! ParseRGB(value,
  878.                 &(frame_info->matte_color.red),
  879.                 &(frame_info->matte_color.green),
  880.                 &(frame_info->matte_color.blue)))
  881.                 rc = ParseError(keyword,value,rc,"badly specified RGB");
  882.             if ( frame_info->width == MissingValue )
  883.                 frame_info->width= (unsigned int) FRGB_ImpliedFt;
  884.  
  885.         }
  886.         else if (mystrcasecmp(keyword,"chcolor") == 0)
  887.         {
  888.             if (!ParseBool(value, &dummy))
  889.                 rc = ParseError(keyword,value,rc,"non-Boolean");
  890.             else
  891.                 digit_info->replace_color=(unsigned int) dummy;
  892.         }
  893.         else if (mystrcasecmp(keyword,"srgb") == 0)
  894.         {
  895.             if (!ParseRGB(value,
  896.                 &(digit_info->opaque_red),
  897.                 &(digit_info->opaque_green),
  898.                 &(digit_info->opaque_blue)))
  899.                 rc=ParseError(keyword,value,rc,
  900.                     "badly specified source RGB");
  901.         }
  902.         else if (mystrcasecmp(keyword,"prgb") == 0)
  903.         {
  904.             if (!ParseRGB(value,
  905.                 &(digit_info->pen_red),
  906.                 &(digit_info->pen_green),
  907.                 &(digit_info->pen_blue)))
  908.                 rc=ParseError(keyword,value,rc,
  909.                     "badly specified pen RGB");
  910.             else
  911.                 digit_info->replace_color=True;
  912.         }
  913.         else if (mystrcasecmp(keyword,"tr") == 0)
  914.         {
  915.             if (!ParseBool(value,&dummy))
  916.                 rc = ParseError(keyword,value,rc,"non-Boolean");
  917.             else
  918.                 digit_info->alpha=(unsigned int) dummy;
  919.         }
  920.         else if (mystrcasecmp(keyword, "trgb") == 0)
  921.         {
  922.             if ( ! ParseRGB(value,
  923.                 &(digit_info->alpha_red),
  924.                 &(digit_info->alpha_green),
  925.                 &(digit_info->alpha_blue)))
  926.                 rc = ParseError(keyword,value,rc,"badly specified RGB");
  927.             if ( digit_info->alpha == MissingValue )
  928.                 digit_info->alpha = (unsigned int) TRGBImpliedTr;
  929.         }
  930.         else if (mystrcasecmp(keyword,"md") == 0)
  931.         {
  932.             if (!ParseInteger(value,&(digit_info->maxdigits),5,10))
  933.                 rc = ParseError(keyword,value,rc,"bad max digits");
  934.         }
  935.         else if (mystrcasecmp(keyword,"pad") == 0)
  936.         {
  937.             if (!ParseBool(value, &dummy))
  938.                 rc = ParseError(keyword,value,rc,"non-Boolean");
  939.             else
  940.                 digit_info->leftpad=(unsigned int) dummy;
  941.         }
  942.         else if (mystrcasecmp(keyword,"dd") == 0)
  943.         {
  944.             (void) strcpy(digit_info->ddhead,value);
  945.         }
  946.         else if (mystrcasecmp(keyword,"st") == 0)
  947.         {
  948.             if (!ParseInteger(value, &dummy, 1,999999999))
  949.                 rc = ParseError(keyword,value,rc,"bad starting");
  950.             else
  951.                 digit_info->st=(unsigned int) dummy;
  952.         }
  953.         else if (mystrcasecmp( keyword, "sh") == 0)
  954.         {
  955.             if (!ParseBool(value, &dummy))
  956.                 rc = ParseError(keyword,value,rc,"non-Boolean");
  957.             else
  958.                 digit_info->show=(unsigned int) dummy;
  959.         }
  960.         else if (mystrcasecmp(keyword,"istrip") == 0)
  961.         {
  962.             if (!ParseBool(value, &dummy))
  963.                rc = ParseError(keyword,value,rc,"non-Boolean");
  964.             else
  965.                digit_info->use_strip=(unsigned int) dummy;
  966.  
  967.         }
  968.         else if (mystrcasecmp(keyword,"comma") == 0)
  969.         {
  970.             if (!ParseBool(value, &dummy))
  971.                rc = ParseError(keyword,value,rc,"non-Boolean");
  972.             else
  973.                digit_info->comma=(unsigned int) dummy;
  974.         }
  975.         else if (mystrcasecmp(keyword,"nsegment") == 0)
  976.         {
  977.             if (!ParseInteger(value, &(digit_info->nsegment), 1,999999999))
  978.                 rc = ParseError(keyword,value,rc,"bad starting");
  979.         }
  980.         else if (mystrcasecmp(keyword,"df") == 0)
  981.         {
  982.             (void) strcpy(digit_info->datafile,value);
  983.         }
  984.         else if (mystrcasecmp( keyword,"incr") == 0)
  985.         {
  986.             if (!ParseBool(value, &dummy))
  987.                 rc = ParseError(keyword,value,rc,"non-Boolean");
  988.             else
  989.                 digit_info->increment_counter=(unsigned int) dummy;
  990.         }
  991.         else if (mystrcasecmp( keyword,"negate") == 0)
  992.         {
  993.             if (!ParseBool(value, &dummy))
  994.                 rc = ParseError(keyword,value,rc,"non-Boolean");
  995.             else
  996.                 digit_info->negate=(unsigned int) dummy;
  997.         }
  998.         else if (mystrcasecmp( keyword,"wxh") == 0)
  999.         {
  1000.             /*
  1001.             ** do nothing, this keyword is here just for backward
  1002.             ** compatibility with Count 1.5. in the current version
  1003.             ** we determine digit dimensions automatically
  1004.             */
  1005.         }
  1006.         else if (mystrcasecmp( keyword,"rotate") == 0)
  1007.         {
  1008.             if (!ParseBool(value, &dummy))
  1009.                 rc = ParseError(keyword,value,rc,"non-Boolean");
  1010.             else
  1011.                 digit_info->rotate=(unsigned int) dummy;
  1012.         }
  1013.         else if (mystrcasecmp(keyword,"degrees") == 0)
  1014.         {
  1015.             if (!ParseInteger(value,&(digit_info->rotate_degrees),90,360))
  1016.                 rc = ParseError(keyword,value,rc,
  1017.                     "badly specified rotation angle");
  1018.             else
  1019.                 digit_info->rotate=True;
  1020.         }
  1021.         else if (mystrcasecmp(keyword,"lit") == 0)
  1022.         {
  1023.      /*if ( ! ParseDigitsString(value, digit_info->literal,MaxTextLength))*/
  1024.            if (!ParseLiteralString(value,digit_info->literal,100))
  1025.                 rc = ParseError(keyword,value,rc,"un-supported or oversized");
  1026.         }
  1027.         else if (mystrcasecmp(keyword,"display") == 0)
  1028.         {
  1029.             if (!ParseOptionString(value,&(digit_info->display_type)))
  1030.                 rc=ParseError(keyword,value,rc,"unknown");
  1031.         }
  1032.         else if (mystrcasecmp(keyword,"image") == 0)
  1033.         {
  1034.             digit_info->display_type=SHOW_GIF_FILE;
  1035.             (void) strncpy(digit_info->gif_file,value,100);
  1036.         }
  1037.         else if (mystrcasecmp(keyword,"dformat") == 0)
  1038.         {
  1039.             if (!ParseDateFormat(value,&(digit_info->date_format)))
  1040.                 rc=ParseError(keyword,value,rc,"invalid");
  1041.         }
  1042.         else if (mystrcasecmp(keyword,"tformat") == 0)
  1043.         {
  1044.             if (!ParseInteger(value,&(digit_info->time_format),12,24))
  1045.                 rc=ParseError(keyword,value,rc,
  1046.                     "badly specified time format, (use 12 or 24)");
  1047.         }
  1048.         else if (mystrcasecmp(keyword,"script") == 0) /* for cgiwrap*/
  1049.         {
  1050.         }
  1051.         else if (mystrcasecmp(keyword,"user") == 0) /*for cgiwrap*/
  1052.         {
  1053.         }
  1054.         else if (mystrcasecmp(keyword,"timezone") == 0)
  1055.         {
  1056.             (void) strncpy(digit_info->time_z,value,49);
  1057.         }
  1058.         else 
  1059.         {
  1060.             sprintf(emsg, "Bad keyword \"%s\"", keyword);
  1061.         PrintHeader();
  1062.         StringImage(emsg);
  1063.         rc++;
  1064.         }
  1065.     }
  1066.  
  1067.     if ( digit_info->alpha == MissingValue )
  1068.         digit_info->alpha = (unsigned char) DefaultTransparency;
  1069.  
  1070.     if ( frame_info->width == MissingValue )
  1071.         frame_info->width= (unsigned char) DefaultThickness;
  1072.  
  1073.     return(rc);
  1074. }
  1075.  
  1076. /*
  1077. ** get current time
  1078. */
  1079.  
  1080. char *GetTime ()
  1081. {
  1082.     time_t
  1083.         tm;
  1084.  
  1085.     char
  1086.         *times;
  1087.  
  1088.     tm = time (NULL);
  1089.     times = ctime(&tm);
  1090.     times[(int) strlen(times)-1] = '\0';
  1091.     return (times);
  1092. }
  1093.  
  1094. void Warning (message)
  1095. char
  1096.     *message;
  1097. {
  1098.     char
  1099.         *times;
  1100.     FILE
  1101.         *fp= (FILE *) NULL;
  1102.     char
  1103.         buf[1024];
  1104.  
  1105.     *buf='\0';
  1106.     (void) sprintf(buf,"%s/%s",LogDir,LogFile);
  1107.     times = GetTime();
  1108.     fp = fopen(buf, "a");
  1109.  
  1110.     if (fp == (FILE *) NULL)
  1111.     {
  1112.         (void) fprintf (stderr,"[%s] Count %s: Could not open CountLog file %s/%s\n ",times, Version, LogDir,LogFile);
  1113.         fp = stderr;
  1114.     }
  1115.         (void) fprintf (fp,"[%s] Count %s: %s\n", 
  1116.             times, Version,message);
  1117.     if (fp != stderr)
  1118.         (void) fclose (fp);
  1119. }
  1120.  
  1121. /*
  1122.  *  GetRemoteReferer - returns the remote referer
  1123.  *
  1124.  *  RCS:
  1125.  *      $Revision: 2.3 $
  1126.  *      $Date: 1996/05/03 02:20:22 $
  1127.  *
  1128.  *  Security:
  1129.  *      Unclassified
  1130.  *
  1131.  *  Description:
  1132.  *      text
  1133.  *
  1134.  *  Input Parameters:
  1135.  *      type    identifier  description
  1136.  *
  1137.  *      char    *host       remote referer HTML
  1138.  *
  1139.  *
  1140.  *  Output Parameters:
  1141.  *      type    identifier  description
  1142.  *
  1143.  *      char    *rem_host   retuns the host
  1144.  *
  1145.  *  Return Values:
  1146.  *      value   description
  1147.  *
  1148.  *  Side Effects:
  1149.  *      text
  1150.  *
  1151.  *  Limitations and Comments:
  1152.  *      text
  1153.  *
  1154.  *  Development History:
  1155.  *      who                 when        why
  1156.  *      muquit@semcor.com   12-Aug-95   first cut
  1157.  */
  1158.  
  1159. #include <stdio.h>
  1160. #include <string.h>
  1161.  
  1162. void GetRemoteReferer (host, rem_host)
  1163. char
  1164.     *host;
  1165. char
  1166.     *rem_host;
  1167. {
  1168.     register char
  1169.         *p,
  1170.         *q;
  1171.  
  1172.     int
  1173.         x;
  1174.  
  1175.     *rem_host = '\0';
  1176.     q=rem_host;
  1177.  
  1178.     for (p=host; *p != '\0'; p++)
  1179.     {
  1180.         if (*p == '/')
  1181.         {
  1182.             p += 2;
  1183.             break;
  1184.         }
  1185.     }
  1186.     while ((*p != '/') && (*p != '\0'))
  1187.         *q++ = *p++;
  1188.  
  1189.     *q = '\0';
  1190.  
  1191.     /*
  1192.     ** randerso@bite.db.uth.tmc.edu added the following lines of code
  1193.     ** to account for port numbers at the end of a url
  1194.     */
  1195.  
  1196.     x=0;
  1197.     while ((x < (int) strlen(rem_host)) && (rem_host[x] != ':'))
  1198.         x++;
  1199.     rem_host[x]='\0';
  1200. }
  1201.  
  1202. #ifdef SYS_UNIX
  1203. void SetLock (fd)
  1204. int
  1205.     fd;
  1206. {
  1207. #ifdef HAVE_FLOCK
  1208.     (void) flock(fd,LOCK_EX);
  1209. #else
  1210.     lseek(fd,0L,0);
  1211.     (void) lockf(fd,F_LOCK,0L);
  1212. #endif
  1213. }
  1214.  
  1215. void UnsetLock (fd)
  1216. int
  1217.     fd;
  1218. {
  1219. #ifdef HAVE_FLOCK
  1220.     (void) flock(fd,LOCK_UN);
  1221. #else
  1222.     lseek(fd,0L,0);
  1223.     (void) lockf(fd,F_ULOCK,0L);
  1224. #endif
  1225. }
  1226. #endif  /* SYS_UNIX */
  1227.  
  1228. int CheckDirs()
  1229. {
  1230.     if ((strcmp(ConfigDir,DigitDir) == 0) ||
  1231.         (strcmp(ConfigDir,DataDir) == 0) ||
  1232.         (strcmp(ConfigDir,LogDir) == 0) ||
  1233.         (strcmp(ConfigDir,LogDir) == 0) ||
  1234.         (strcmp(DigitDir,DataDir) == 0) ||
  1235.         (strcmp(DigitDir,LogDir) == 0) ||
  1236.         (strcmp(DataDir,LogDir) == 0))
  1237.     return (1);
  1238. return (0);
  1239. }
  1240.  
  1241. #ifdef USE_ME
  1242. /*
  1243.  *  CheckRemoteIP - checks if remote host in the ignore list
  1244.  *
  1245.  *  RCS:
  1246.  *      $Revision: 2.3 $
  1247.  *      $Date: 1996/05/03 02:20:22 $
  1248.  *
  1249.  *  Security:
  1250.  *      Unclassified
  1251.  *
  1252.  *  Description:
  1253.  *      text
  1254.  *
  1255.  *  Input Parameters:
  1256.  *      type    identifier  description
  1257.  *
  1258.  *      text
  1259.  *
  1260.  *  Output Parameters:
  1261.  *      type    identifier  description
  1262.  *
  1263.  *      text
  1264.  *
  1265.  *  Return Values:
  1266.  *      value   description
  1267.  *
  1268.  *      True if the remote IP should be ignored (a match)
  1269.  *      False remote IP should be counted
  1270.  *
  1271.  *  Side Effects:
  1272.  *      text
  1273.  *
  1274.  *  Limitations and Comments:
  1275.  *      text
  1276.  *
  1277.  *  Development History:
  1278.  *      who                 when        why
  1279.  *      muquit@semcor.com   13-Sep-95   -
  1280.  */
  1281.  
  1282. unsigned int CheckRemoteIP(remote_ip,ip_ign)
  1283. char
  1284.     *remote_ip,
  1285.     *ip_ign;
  1286. {
  1287.     char
  1288.         tmp[10],
  1289.         buf[100],
  1290.         buf2[100];
  1291.  
  1292.     int
  1293.         x,
  1294.         y,
  1295.         z,
  1296.         w,
  1297.         xx,
  1298.         yy,
  1299.         zz,
  1300.         ww;
  1301.  
  1302.     int
  1303.         rc;
  1304.  
  1305.     *tmp='\0';
  1306.     *buf='\0';
  1307.     *buf2='\0';
  1308.  
  1309.     /*
  1310.     ** REMOTE_ADDR
  1311.     */
  1312.  
  1313.     (void) strcpy(buf,remote_ip);
  1314.     rc=sscanf(buf,"%d.%d.%d.%d",&xx,&yy,&zz,&ww);
  1315.     if (rc != 4)
  1316.         return(False);
  1317.  
  1318.     /*
  1319.     ** IP from conf file, we'll compare the remote IP with this one.
  1320.     ** we'll check for wildcard in the IP from conf file as well
  1321.     ** we'll check for all 3 classes of network
  1322.     */
  1323.  
  1324.     rc=sscanf(ip_ign,"%d.%d.%d.%d",&x,&y,&z,&w);
  1325.     if (rc != 4) /* possible wildcard */
  1326.     {
  1327.         /*
  1328.         ** check wildcard for a Class C network
  1329.         */
  1330.         if ((x >= 192) && (x <= 223))
  1331.         {
  1332.             /*
  1333.             ** we'r concerned with 4th octet
  1334.             */
  1335.             rc=sscanf(ip_ign,"%d.%d.%d.%s",&x,&y,&z,tmp);
  1336.             if (rc != 4) /* screwed up entry, don't ignore*/
  1337.                 return (False);
  1338.             if (strcmp(tmp,"*") == 0)
  1339.             {
  1340.                 if ((x == xx) &&
  1341.                     (y == yy) &&
  1342.                     (z == zz))
  1343.                 {
  1344.                     return (True);
  1345.                 }
  1346.             }
  1347.             else
  1348.                 return (False);
  1349.         }
  1350.         else if ((x >= 128) && (x <= 191))
  1351.         {
  1352.             /*
  1353.             ** check wildcard for class B network
  1354.             ** we'll check the 3rd octet for wildcard
  1355.             */
  1356.             (void) fprintf (stderr," Class B\n");
  1357.             rc=sscanf(ip_ign,"%d.%d.%s",&x,&y,tmp);
  1358.             (void) fprintf (stderr," rc: %d\n",rc);
  1359.             (void) fprintf (stderr," tmp:%s\n",tmp);
  1360.             if (rc != 3)
  1361.                 return (False);
  1362.  
  1363.             if ((strcmp(tmp,"*") == 0) ||
  1364.                 (strcmp(tmp,"*.*") == 0))
  1365.             {
  1366.                 (void) fprintf (stderr," xx,yy:%d,%d\n",xx,yy);
  1367.                 if ((x == xx) &&
  1368.                     (y == yy))
  1369.                 {
  1370.                     return (True);
  1371.                 }
  1372.                 else
  1373.                     return (False);
  1374.             }
  1375.         }
  1376.         else /* x < 128, got to be a Class A network */
  1377.         {
  1378.             /*
  1379.             ** we'll check the 2nd octet for wildcard
  1380.             */
  1381.             rc=sscanf(ip_ign,"%d.%s",&x,tmp);
  1382.             if (rc != 2)
  1383.                 return (False);
  1384.  
  1385.             if ((strcmp(tmp,"*") == 0) ||
  1386.                 (strcmp(tmp,"*.*") == 0) ||
  1387.                 (strcmp(tmp,"*.*.*") == 0))
  1388.             {
  1389.                 if (x == xx)
  1390.                     return (True);
  1391.                  else
  1392.                     return (False);
  1393.             }
  1394.         }
  1395.     }
  1396.     else
  1397.     {
  1398.         /*
  1399.         ** compare directly
  1400.         */
  1401.         if (strcmp(buf,ip_ign) == 0)
  1402.             return (True);
  1403.     }
  1404.  
  1405. return (False);
  1406. }
  1407.  
  1408. #endif /* USE_ME*/
  1409.  
  1410. /*
  1411.  * Copyright (c) 1988, 1993
  1412.  *    The Regents of the University of California.  All rights reserved.
  1413.  *
  1414.  * Redistribution and use in source and binary forms, with or without
  1415.  * modification, are permitted provided that the following conditions
  1416.  * are met:
  1417.  * 1. Redistributions of source code must retain the above copyright
  1418.  *    notice, this list of conditions and the following disclaimer.
  1419.  * 2. Redistributions in binary form must reproduce the above copyright
  1420.  *    notice, this list of conditions and the following disclaimer in the
  1421.  *    documentation and/or other materials provided with the distribution.
  1422.  * 3. All advertising materials mentioning features or use of this software
  1423.  *    must display the following acknowledgement:
  1424.  *    This product includes software developed by the University of
  1425.  *    California, Berkeley and its contributors.
  1426.  * 4. Neither the name of the University nor the names of its contributors
  1427.  *    may be used to endorse or promote products derived from this software
  1428.  *    without specific prior written permission.
  1429.  *
  1430.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  1431.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  1432.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  1433.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  1434.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  1435.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  1436.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  1437.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  1438.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  1439.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  1440.  * SUCH DAMAGE.
  1441.  */
  1442.  
  1443. /*
  1444. ** I'm renaming it to mystrtok() in order to avoid conflict with the
  1445. ** system which might have it
  1446. ** I also formatted to my coding style
  1447. ** 10/08/95, muquit@semcor.com
  1448. */
  1449.  
  1450. char *mystrtok(s, delim)
  1451. char
  1452.     *s;
  1453. char
  1454.     *delim;
  1455. {
  1456.     register char
  1457.         *spanp;
  1458.  
  1459.     register int
  1460.         c,
  1461.         sc;
  1462.  
  1463.     char
  1464.         *tok;
  1465.  
  1466.     static char
  1467.         *last;
  1468.  
  1469.  
  1470.     if (s == (char *) NULL && (s = last) == (char *) NULL)
  1471.         return ((char *) NULL);
  1472.  
  1473.      /*
  1474.      ** Skip (span) leading delimiters (s += strspn(s, delim), sort of).
  1475.      */
  1476. cont:
  1477.     c = *s++;
  1478.     for (spanp = (char *)delim; (sc = *spanp++) != 0;) 
  1479.     {
  1480.         if (c == sc)
  1481.             goto cont;
  1482.     }
  1483.  
  1484.     if (c == 0) 
  1485.     {        /* no non-delimiter characters */
  1486.         last = (char *) NULL;
  1487.         return ((char *)NULL);
  1488.     }
  1489.     tok = s - 1;
  1490.  
  1491.     /*
  1492.      * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
  1493.      * Note that delim must have one NUL; we stop if we see that, too.
  1494.      */
  1495.  
  1496.     for (;;) 
  1497.     {
  1498.         c = *s++;
  1499.         spanp = (char *)delim;
  1500.         do 
  1501.         {
  1502.             if ((sc = *spanp++) == c) 
  1503.             {
  1504.                 if (c == 0)
  1505.                     s = (char *) NULL;
  1506.                 else
  1507.                     s[-1] = '\0';
  1508.                 last = s;
  1509.                 return (tok);
  1510.             }
  1511.         } while (sc != 0);
  1512.     }
  1513.       /* NOTREACHED */
  1514. }
  1515.  
  1516.  
  1517. /*
  1518. ** found somewhere in the net
  1519. ** muquit@semcor.com
  1520. */
  1521. int mystrcasecmp(a,b)
  1522. char
  1523.     *a,
  1524.     *b;
  1525. {    
  1526.     register char
  1527.         ac,
  1528.         bc;
  1529.  
  1530.     for(;;)
  1531.     {
  1532.         ac = *a++;
  1533.         bc = *b++;
  1534.  
  1535.         if(ac == 0)
  1536.         {
  1537.             if(bc == 0)
  1538.                 return 0;
  1539.             else
  1540.                 return -1;
  1541.         }
  1542.         else
  1543.         { 
  1544.             if(bc == 0)
  1545.                 return 1;
  1546.             else 
  1547.             {
  1548.                 if(ac != bc)
  1549.                 {
  1550.                     if(islower(ac)) ac = toupper(ac);
  1551.                     if(islower(bc)) bc = toupper(bc);
  1552.                     if( ac != bc )
  1553.                         return ac - bc;
  1554.                 }
  1555.             }
  1556.         }
  1557.     }
  1558. }
  1559.  
  1560. /*
  1561.  * the different -- and hopefully self-contained -- version of
  1562.  * CheckRemoteIP. Main difference is that ignore host block may
  1563.  * contain two IP address fields. First is then IP network address
  1564.  * and second is the netmask to be applied for comparision.  
  1565.  *
  1566.  * Davorin Bengez (Davorin.Bengez@science.hr), Jan 11. 1996.
  1567.  */
  1568.  
  1569. unsigned int CheckRemoteIP(remote_ip, ip_ign)
  1570. char *remote_ip, *ip_ign;
  1571. {
  1572.     unsigned long my_inet_addr _Declare ((char *));
  1573.     unsigned long rem_ip, ignore_ip, ignore_mask;
  1574.     char addr_buf[20], mask_buf[20];
  1575.     int i;
  1576.  
  1577.     ignore_mask = 0xffffffffL;
  1578.  
  1579.     rem_ip = my_inet_addr(remote_ip);
  1580.     if(rem_ip == (unsigned long)-1) return(False);
  1581.  
  1582.     /*
  1583.      * if ip_ign has TWO ip-look-alike fields, second field is netmask
  1584.      */
  1585.  
  1586.     if((i = sscanf(ip_ign, "%s %s", addr_buf, mask_buf)) < 1)
  1587. return(False);
  1588.  
  1589.     ignore_ip = my_inet_addr(addr_buf);
  1590.     if(ignore_ip == (unsigned long)-1) return(False);
  1591.  
  1592.     /*
  1593.      * try to convert the mask to something usable and fail if it
  1594.      * is not the proper IP netmask...
  1595.      */
  1596.  
  1597.     if(i == 2) {
  1598.         ignore_mask = my_inet_addr(mask_buf);
  1599.         if(ignore_mask == (unsigned long)-1) return(False);
  1600.     }
  1601.  
  1602.     /*
  1603.      * ...and finally, compare the masked addresses...
  1604.      */
  1605.   
  1606.     if((rem_ip & ignore_mask) == (ignore_ip & ignore_mask))
  1607.         return(True);
  1608.     else
  1609.         return(False);
  1610. }
  1611.  
  1612. /*
  1613.  * and a version of inet_addr - not to link all the network services
  1614.  * just because of this one...
  1615.  */
  1616.  
  1617. unsigned long my_inet_addr(s)
  1618. char *s;
  1619. {
  1620.     unsigned long n;
  1621.     int atoi();
  1622.     int i;
  1623.  
  1624.     n = 0;
  1625.  
  1626.     for(i = 24; i >= 0; i -= 8) {
  1627.         n |= (unsigned long)atoi(s) << i;
  1628.         if((s = strchr(s,'.')) == (char *)NULL)
  1629.             break;
  1630.         ++s;
  1631.     }
  1632.     return(n);
  1633. }
  1634.  
  1635. #ifndef HAVE_MKTIME
  1636. /*
  1637.  * $Author: muquit $
  1638.  * $Date: 1996/05/03 02:20:22 $
  1639.  * $Id: parse.c,v 2.3 1996/05/03 02:20:22 muquit Exp muquit $
  1640.  * $Source: /usr2/sparc/muquit/mysrc/tmp/wwwcount2.3/RCS/parse.c,v $
  1641.  *
  1642.  * Grr.. on EP/IX I have no mktime(2) routine so I've had to roll my own.
  1643.  * Original work 7-Apr-95 by Reg Quinton <reggers@julian.uwo.ca>
  1644. */
  1645.  
  1646.  
  1647. /* this is awfully nasty, the epoch began in 1970 UTC and 1968 was
  1648.    the preceding leap year. This converts a time structure to the
  1649.    number of seconds since the leap year. But assumes I have all
  1650.    sorts of good values which might not be there and doesn't do
  1651.    any fancy work wrt. time zones (assumes date given is same
  1652.    timezone and EST/EDT offset) which obviously isn't true. */
  1653.  
  1654. time_t netMktime(v)
  1655. struct tm *v;
  1656. {
  1657. struct    tm    *tm;
  1658.     int    leap;
  1659.     time_t    n;
  1660.  
  1661.     leap= (((v)->tm_year) % 4) ? 0 : 1;
  1662.  
  1663.     switch ((v)->tm_mon) {
  1664.     case 0:    /* Jan */
  1665.         (v)->tm_yday=(v)->tm_mday - 1;
  1666.         break;;
  1667.     case 1: /* Feb */
  1668.         (v)->tm_yday=31 + (v)->tm_mday - 1;
  1669.         break;;
  1670.     case 2: /* Mar */
  1671.         (v)->tm_yday=59 + (v)->tm_mday - 1 + leap;
  1672.         break;;
  1673.     case 3: /* Apr */
  1674.         (v)->tm_yday=90 + (v)->tm_mday - 1 + leap;
  1675.         break;;
  1676.     case 4: /* May */
  1677.         (v)->tm_yday=120 + (v)->tm_mday - 1 + leap;
  1678.         break;;
  1679.     case 5: /* Jun */
  1680.         (v)->tm_yday=151 + (v)->tm_mday - 1 + leap;
  1681.         break;;
  1682.     case 6: /* Jul */
  1683.         (v)->tm_yday=181 + (v)->tm_mday - 1 + leap;
  1684.         break;;
  1685.     case 7: /* Aug */
  1686.         (v)->tm_yday=212 + (v)->tm_mday - 1 + leap;
  1687.         break;;
  1688.     case 8: /* Sep */
  1689.         (v)->tm_yday=243 + (v)->tm_mday - 1 + leap;
  1690.         break;;
  1691.     case 9: /* Oct */
  1692.         (v)->tm_yday=273 + (v)->tm_mday - 1 + leap;
  1693.         break;;
  1694.     case 10: /* Nov */
  1695.         (v)->tm_yday=304 + (v)->tm_mday - 1 + leap;
  1696.         break;;
  1697.     case 11: /* Dec */
  1698.         (v)->tm_yday=334 + (v)->tm_mday - 1 + leap;
  1699.         break;;
  1700.     }
  1701.  
  1702.     /* n is the time value GMT, I need an offset */
  1703.  
  1704.     n=(((((((((((v)->tm_year) - 70) * 365 + 
  1705.                           (((v)->tm_year) - 68) / 4)  + 
  1706.                            ((v)->tm_yday)) * 24 ) +
  1707.                            ((v)->tm_hour)) * 60 ) + 
  1708.                            ((v)->tm_min))  * 60 ) + 
  1709.                            ((v)->tm_sec) );
  1710.  
  1711.     /* find the GMT offset and take it off, this fails
  1712.        real bad at the time the timezone changes */
  1713.  
  1714.     tm=localtime(&n);    return(n-tm->tm_gmtoff);
  1715. }
  1716.  
  1717. #endif /* !HAVE_MKTIME */
  1718.  
  1719. /*
  1720.  *  checkTimezone - parses the GMT+-hhmm and returns the time in seconds
  1721.  *
  1722.  *  RCS:
  1723.  *      $Revision: 2.3 $
  1724.  *      $Date: 1996/05/03 02:20:22 $
  1725.  *
  1726.  *  Security:
  1727.  *      Unclassified
  1728.  *
  1729.  *  Description:
  1730.  *      This funcions parses a string like GMT+-hhmm and returns the time
  1731.  *      in seconds.
  1732.  *
  1733.  *  Input Parameters:
  1734.  *      type    identifier  description
  1735.  *
  1736.  *      char    str[]
  1737.  *          str holds a string like GMT+-hhmm
  1738.  *
  1739.  *  Output Parameters:
  1740.  *      type    identifier  description
  1741.  *
  1742.  *      text
  1743.  *
  1744.  *  Return Values:
  1745.  *      value   description
  1746.  *      int     diff
  1747.  *          hhmm is converted to seconds before returning. the value will
  1748.  *          be positive or negative based on GMT+ or GMT-
  1749.  *
  1750.  *  Side Effects:
  1751.  *      text
  1752.  *
  1753.  *  Limitations and Comments:
  1754.  *      text
  1755.  *
  1756.  *  Development History:
  1757.  *      who                 when        why
  1758.  *      muquit@semcor.com   26-Mar-96   first cut
  1759.  */
  1760.  
  1761.  
  1762. long checkTimezone(str)
  1763. char
  1764.     str[];
  1765. {
  1766.     int
  1767.         hr,
  1768.         min;
  1769.     int
  1770.         d;
  1771.     int
  1772.         counter=0;
  1773.  
  1774.     char
  1775.         buf[10];
  1776.  
  1777.     long
  1778.         diff=0L;
  1779.  
  1780.     int
  1781.         i;
  1782.  
  1783.     *buf='\0';
  1784.     hr=0;
  1785.     min=0;
  1786.     
  1787.  
  1788.     if (*str != '\0')
  1789.     {
  1790.         if (strlen(str) == 8)
  1791.         {
  1792.             if ((str[3] == '-') || (str[3] == '+'))
  1793.             {
  1794.                 (void) strcpy(buf,&str[4]);   
  1795.                 for (i=0; i < strlen(buf); i++)
  1796.                 {
  1797.                     d=buf[i];
  1798.                     if ((d >= '0') && (d <= '9'))
  1799.                     {
  1800.                         if (counter < 2)
  1801.                             hr=hr*10 +(d-'0');
  1802.                         else
  1803.                             min=min*10+(d-'0');
  1804.                         counter++;
  1805.                     }
  1806.                 }
  1807.                 diff=(hr*3600)+min*60;
  1808.                 if (str[3] == '-')
  1809.                     diff = -(diff);
  1810.             }
  1811.         }
  1812.     }
  1813.     return (diff);
  1814. }
  1815.  
  1816. /*
  1817. ** parse literal string
  1818. ** 04/23/96
  1819. */
  1820. int ParseLiteralString(given,sets,maxlen)
  1821. char
  1822.     *given;
  1823. char
  1824.     *sets;
  1825. int
  1826.     maxlen;
  1827. {
  1828.     for (; *given != (char) 0; given++, sets++,maxlen--)
  1829.     {
  1830.         if (((isdigit(*given) ||
  1831.              (*given == ':')  ||
  1832.              (*given == ',')  ||
  1833.              (*given == '-')  ||
  1834.              (*given == 'a')  ||
  1835.              (*given == 'A')  ||
  1836.              (*given == 'p')  ||
  1837.              (*given == 'P')) &&
  1838.             (maxlen >= 0)))
  1839.         {
  1840.             *sets=*given;
  1841.         }
  1842.         else
  1843.             return (False);
  1844.     }
  1845.     return (True);
  1846. }
  1847.  
  1848.