home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1997 May / PCO_5_97.ISO / FilesBBS / OS2 / WWWCNT15.ARJ / WWWCNT15 / WWWCNT15.ZIP / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-13  |  19.6 KB  |  847 lines

  1. /*
  2.  *  WWW document access counter
  3.  *
  4.  *  RCS:
  5.  *      $Revision: 1.3 $
  6.  *      $Date: 1995/07/16 17:02:55 $
  7.  *
  8.  *  Security:
  9.  *      Unclassified
  10.  *
  11.  *  Description:
  12.  *     main routine for WWW homepage access counter
  13.  *  
  14.  *  Input Parameters:
  15.  *      type    identifier  description
  16.  *
  17.  *      N/A
  18.  *
  19.  *  Output Parameters:
  20.  *      type    identifier  description
  21.  *
  22.  *      N/A
  23.  *
  24.  *  Return Values:
  25.  *      value   description
  26.  *
  27.  *  Side Effects:
  28.  *      None
  29.  *
  30.  *  Limitations and Comments:
  31.  *      None
  32.  *
  33.  *  Development History:
  34.  *      who                 when        why
  35.  *      muquit@semcor.com   10-Apr-95   first cut
  36.  *      muquit@semcor.com   06-07-95    release 1.2
  37.  *      muquit@semcor.com   07-13-95    release 1.3
  38.  */
  39.  
  40. #define __Main__
  41. #include "combine.h"
  42. #include "count.h"
  43. #include "config.h"
  44.  
  45. static char *ImagePrefix[]=
  46. {
  47.     "zero", "one", "two", "three", "four", "five", 
  48.     "six", "seven", "eight", "nine",
  49. };
  50.  
  51. char ConfigDir[512];
  52. char ConfigFile[512];
  53. char DigitDir[512];
  54. char DataDir[512];
  55. char LogDir[512];
  56. char LogFile[512];
  57.  
  58. void main (argc, argv)
  59. int
  60.     argc;
  61. char
  62.     **argv;
  63.  
  64. {
  65.     int
  66.         rc = 0;
  67.  
  68.     unsigned int
  69.         ignore_site=False;
  70.  
  71.     register int
  72.         i;
  73.  
  74.     char
  75.         *remote_ip,
  76.         *query_string;
  77.  
  78.     int
  79.         n;
  80.  
  81.     int
  82.         counter_length;
  83.  
  84.     int
  85.         left_pad;
  86.  
  87.     char
  88.         filename[MaxTextLength];
  89.  
  90.     char
  91.         tmpbuf[MaxTextLength];
  92.  
  93.     char
  94.         digitbuf[MaxTextLength];
  95.  
  96.     int
  97.         fd;
  98.  
  99.     char
  100.         format[10],
  101.         buf[50];
  102.  
  103.     int
  104.         count,
  105.         counter;
  106.  
  107.     char
  108.         Limit[50];
  109.  
  110.     int
  111.         LimitDigits;
  112.  
  113.     int
  114.         tagdigit;
  115.  
  116.     int
  117.         MaxDigits=10;
  118.  
  119.     DigitInfo
  120.         digit_info;
  121.  
  122.     FrameInfo
  123.         frame_info;
  124.  
  125.     register char
  126.         *p;
  127.  
  128.  
  129.     unsigned int
  130.         use_st;
  131. #ifdef ACCESS_AUTH
  132.     char
  133.         *rem_refh;
  134. #endif
  135.  
  136.     _fsetmode(stdout, "b");
  137.     setmode(1, O_BINARY);
  138.  
  139. /*
  140. **---------initialize globals------Starts---
  141. */
  142.     GetDirs();
  143.     for (i=0; i < MaxSites; i++)
  144.     {
  145.         GrefererHost[i] = (char *) NULL;
  146.         GignoreSite[i] = (char *) NULL;
  147.     }
  148.     Grhost=0;
  149.     Gsite=0;
  150.     Gdebug=False;
  151. /*
  152. **---------initialize globals------Ends---
  153. */
  154.     count=1;
  155.     *format='\0';
  156.     *Limit = '\0';
  157.     *buf='\0';
  158.     *filename = '\0';
  159.     *digitbuf='\0';
  160.     *tmpbuf = '\0';
  161.     counter = 0;
  162.     tagdigit=9;
  163.     left_pad=MaxDigits;
  164.     use_st=False;
  165.  
  166.     /*
  167.     ** parse command line, this is only used for testing at commandline
  168.     ** no command line flag is allowed in the web page while calling
  169.     ** the program
  170.     */
  171.  
  172.     for (i=1; i < argc; i++)
  173.     {
  174.         if (!strncmp(argv[i],"-debug",(int)strlen("-debug")))
  175.         {
  176.             Gdebug=True;
  177.             break;
  178.         }
  179.     }
  180.  
  181.     if (Gdebug == True)
  182.     {
  183.     (void) fprintf (stderr,"[%s] Count %s: --Debug Starts\n", 
  184.         GetTime(), Version);
  185. #ifdef USE_LOCK
  186.     (void) fprintf (stderr," datafile locking is enabled\n");
  187. #else
  188.     (void) fprintf (stderr," datafile locking is disabled\n");
  189. #endif /*USE_LOCK*/
  190.     }
  191.  
  192.     rc=CheckDirs();
  193.     if (rc == 1)
  194.     {
  195.         *tmpbuf='\0';
  196.         (void) sprintf(tmpbuf,"ConfigDir,DigitDir,DataDir,LogDir must differ");
  197.         Warning(tmpbuf);
  198.         PrintHeader();
  199.         StringImage(tmpbuf);
  200.         exit(1);
  201.     }
  202.  
  203.     /*
  204.     ** parse the authorization list
  205.     */
  206.     rc = ParseAuthorizationList ();
  207.  
  208.     switch (rc)
  209.     {
  210.         case ConfigOpenFailed:
  211.         {
  212.             *tmpbuf='\0';
  213.             (void) sprintf (tmpbuf, 
  214.                 "Faliled to open configuration file: \"%s/%s\"",
  215.                     ConfigDir,ConfigFile);
  216.             Warning (tmpbuf);
  217.             PrintHeader ();
  218.             StringImage (tmpbuf);
  219.             exit(1);
  220.             break;
  221.         }
  222.  
  223.         case NoIgnoreHostsBlock:
  224.         {
  225.             *tmpbuf='\0';
  226.             (void) sprintf (tmpbuf,
  227.                 "No IgnoreHosts Block in the configuration file: \"%s/%s\"",
  228.                     ConfigDir,ConfigFile);
  229.  
  230.             Warning(tmpbuf);
  231.             PrintHeader ();;
  232.             StringImage(tmpbuf);
  233.             exit(1);
  234.         }
  235.  
  236.         case NoRefhBlock:
  237.         {
  238.             *tmpbuf='\0';
  239.             (void) sprintf(tmpbuf,"Compiled with -DACCESS_AUTH,but no such block in configuration file!");
  240.             Warning(tmpbuf);
  241.             PrintHeader ();;
  242.             StringImage(tmpbuf);
  243.             exit(1);
  244.         }
  245.  
  246.         case UnpexpectedEof:
  247.         {
  248.             *tmpbuf='\0';
  249.             (void) sprintf (tmpbuf, 
  250.             "Unexpected EOF in configuration file: \"%s/%s\"",
  251.                 ConfigDir,ConfigFile);
  252.             Warning(tmpbuf);
  253.             PrintHeader ();
  254.             StringImage(tmpbuf);
  255.             exit(1);
  256.         }
  257.  
  258.     } /* switch (rc) */
  259.  
  260.  
  261.     if (Gdebug == True)
  262.         (void) fprintf (stderr," Gsite: %d\n", Gsite);
  263.  
  264. #ifdef ACCESS_AUTH
  265.     /*
  266.     ** check if the referer is a remote host or not. refere should
  267.     ** be the local host.
  268.     */
  269.  
  270.     rem_refh = getenv("HTTP_REFERER");
  271.     if (rem_refh != (char *) NULL)
  272.     {
  273.         char
  274.             http_ref[1024],
  275.             Rhost[1024];
  276.         *http_ref = '\0';
  277.         *Rhost = '\0';
  278.         /*
  279.         ** this will be same as your host when accessed from your
  280.         ** page. if the host is anything else, it is an unauthorized
  281.         ** access. handle it.
  282.         */
  283.         (void) strcpy (http_ref, rem_refh);
  284.         GetRemoteReferer(http_ref, Rhost);
  285.  
  286.         if (Gdebug == True)
  287.         {
  288.             (void) fprintf (stderr," Grhost:%d\n",Grhost);
  289.             (void) fprintf (stderr," Rhost: %s\n",Rhost);
  290.         }
  291.         if (*Rhost != '\0')
  292.         {
  293.             if (Grhost > 0)
  294.             {
  295.                 for (i=0; i < Grhost; i++)
  296.                 {
  297.                     rc=strcmp(Rhost,GrefererHost[i]);
  298.                     if (rc == 0)
  299.                         break;
  300.                 }
  301.             }
  302.             if (rc != 0)
  303.             {
  304.                 *tmpbuf='\0';
  305.                 (void) sprintf(tmpbuf,"Unauthorized Access denied to host: %s",Rhost);
  306.                 Warning(tmpbuf);                    
  307.                 PrintHeader();
  308.                 StringImage(tmpbuf);
  309.                 exit(1);
  310.             }
  311.         }
  312.     }
  313.  
  314. #endif /* ACCESS_AUTH */
  315.     /*
  316.     ** get the user name from query string
  317.     */
  318.     query_string = getenv("QUERY_STRING");
  319.  
  320.     if (query_string == (char *) NULL)
  321.     {
  322.         *tmpbuf='\0';
  323.         (void) sprintf(tmpbuf,"%s","Empty QUERY_STRING!");
  324.         Warning(tmpbuf);
  325.         PrintHeader ();
  326.         StringImage(tmpbuf);
  327.         exit(1);
  328.     }
  329.  
  330.     rc=ParseQueryString(query_string,&digit_info,&frame_info);
  331.  
  332.     if (rc)
  333.     {
  334.         if (Gdebug == True)
  335.             (void) fprintf (stderr," rc from ParseQueryString()=%d\n",rc);
  336.  
  337.         *tmpbuf='\0';
  338.         (void) sprintf(tmpbuf,"%s: %s","Incorrect QUERY_STRING",query_string);
  339.         Warning(tmpbuf);
  340.         PrintHeader ();
  341.         StringImage(tmpbuf);
  342.         exit(1);
  343.     }
  344.  
  345.     if (digit_info.leftpad == True)
  346.     {
  347.         MaxDigits=digit_info.maxdigits;
  348.  
  349.         if ((MaxDigits < 5) || (MaxDigits > 10))
  350.         {
  351.             Warning("Maxdigits (md) must be >= 5 and <= 10");
  352.             PrintHeader ();
  353.             StringImage("Maxdigits (md) must be >= 5 and <= 10");
  354.             exit(1);
  355.         }
  356.     }
  357.  
  358.     if (checkfilename (digit_info.datafile) != 0)
  359.     {
  360.         *tmpbuf='\0';
  361.         (void) sprintf (tmpbuf,
  362.             "Counter datafile \"%s\" invalid!", digit_info.datafile);
  363.         Warning(tmpbuf);
  364.         PrintHeader ();
  365.         StringImage(tmpbuf);
  366.         exit(1);
  367.     }
  368.  
  369.     (void) strcpy(filename, DataDir);
  370.     (void) strcat(filename, "/");
  371.     (void) strcat (filename, digit_info.datafile);
  372.  
  373.     /*
  374.     ** check if the counter file exists or not
  375.     */
  376. #ifndef ALLOW_FILE_CREATION
  377.     if (CheckFile (filename) != 0)
  378.     {
  379.         *tmpbuf='\0';
  380.         (void) sprintf (tmpbuf,
  381.             "Counter datafile \"%s\" must be created first!", filename);
  382.         Warning(tmpbuf);
  383.         PrintHeader ();
  384.         StringImage (tmpbuf);
  385.         exit(1);
  386.     }
  387. #endif
  388.  
  389.     /*
  390.     ** get frameinfo
  391.     */
  392.  
  393.     if (frame_info.width > 1)
  394.         digit_info.Frame=True;
  395.     else
  396.         digit_info.Frame=False;
  397.     /*
  398.     ** get the IP address of the connected machine to check if we need
  399.     ** to increment the counter
  400.     */
  401.     remote_ip = getenv("REMOTE_ADDR");
  402.     if (remote_ip == (char *) NULL)
  403.     {
  404.         /*
  405.         ** put a dummy here
  406.         */
  407.         remote_ip = "dummy_ip";
  408.     }
  409.     else
  410.     {
  411.         for (i=0; i < Gsite; i++)
  412.         {
  413.             ignore_site=CheckRemoteIP(remote_ip,GignoreSite[i]);
  414.             if (ignore_site == True)
  415.             {
  416.                 break;
  417.             }
  418.         }
  419.     }
  420.  
  421.     /*
  422.     ** initialize Limit array
  423.     */
  424.  
  425.  
  426.     if (Gdebug == True)
  427.         (void) fprintf (stderr," MsxDigits=%d\n", MaxDigits);
  428.  
  429.     (void) sprintf (Limit, "%d", tagdigit);
  430.  
  431.     for (i=0; i < MaxDigits-1; i++)
  432.         (void) sprintf (Limit, "%s%d", Limit,tagdigit);
  433.  
  434.     LimitDigits = atoi (Limit);
  435.  
  436.     if (Gdebug == True)
  437.         (void) fprintf (stderr," Limit: %s\n", Limit);
  438.  
  439. #ifdef ALLOW_FILE_CREATION
  440.     if (CheckFile (filename) != 0)
  441.         use_st=True;
  442. #endif
  443.     fd = open (filename, O_RDWR | O_CREAT,0644);
  444.     if (fd < 0)
  445.     {
  446.         *tmpbuf='\0';
  447. #ifdef ALLOW_FILE_CREATION
  448.         if (CheckFile (filename) != 0)
  449.             (void) sprintf(tmpbuf,
  450.                 "Could not create data file: \"%s\"",filename);
  451.         else
  452.             (void) sprintf (tmpbuf,
  453.                 "Could not write to counter file: \"%s\"", filename);
  454. #else
  455.         (void) sprintf (tmpbuf,
  456.             "Could not write to counter file: \"%s\"", filename);
  457. #endif /* ALLOW_FILE_CREATION */
  458.  
  459.         Warning(tmpbuf);
  460.         PrintHeader ();
  461.         StringImage(tmpbuf);
  462.         exit(1);
  463.     }
  464.  
  465. #ifdef USE_LOCK
  466.     SetLock(fd);
  467. #endif
  468.     /*
  469.     ** try to read from the file
  470.     */
  471.  
  472.     lseek(fd,0L,0);
  473.     n = read(fd, buf, MaxDigits);
  474.  
  475.     if (n > 0)
  476.     {
  477.  
  478.  
  479.         /*
  480.         ** check if the datafile is edited, NULL terminate at first non-digit
  481.         */
  482.         for (i=0; i < n; i++)
  483.         {
  484.             if (!isdigit(buf[i]))
  485.             {
  486.                 buf[i]='\0';
  487.                 break;
  488.             }
  489.         }
  490.         if (i == n)
  491.             buf[n]='\0';
  492.  
  493.         if (*buf == '\0')
  494.             counter=0;
  495.         else
  496.             counter = atoi(buf);
  497.         *buf='\0';
  498.         (void) sprintf(buf,"%d",counter);
  499.         
  500.         if (Gdebug == True)
  501.             (void) fprintf (stderr," Counter before increment: %d\n", counter);
  502.  
  503.         if (counter == 0)
  504.             counter_length = 1;
  505.         else
  506.  
  507.         if (counter >= LimitDigits)
  508.             counter= LimitDigits;
  509.         if (counter != LimitDigits)
  510.             counter++;
  511.          (void) sprintf(buf, "%d", counter);
  512.          counter_length = (int) strlen(buf);
  513.         
  514.         if (Gdebug == True)
  515.             (void) fprintf (stderr," Counter after increment: %d\n", counter);
  516.  
  517.         if (ignore_site  == False)
  518.         {
  519.             lseek(fd,0L,0);
  520.             (void) write(fd, buf, (int)strlen(buf));
  521.             (void) close (fd); /*unlocks as well */
  522.         }
  523.     }
  524.     else
  525.     {
  526.  
  527.         if (Gdebug == True)
  528.         {
  529.             (void) fprintf (stderr," n < 0\n");
  530.             (void) fprintf (stderr," Counter before increment: %d\n", counter);
  531.         }
  532.  
  533.         if (use_st == True)
  534.         {
  535.             counter=digit_info.st;
  536.             (void) sprintf(buf, "%d", counter);
  537.         }
  538.         else
  539.         {
  540.             counter++;
  541.             (void) sprintf(buf, "%d", counter);
  542.         }
  543.         if (Gdebug == True)
  544.             (void) fprintf (stderr," Counter after increment: %d\n", counter);
  545.  
  546.         lseek(fd,0L,0);
  547.         write (fd, buf, (int) strlen(buf));
  548.         (void) close (fd);
  549.         counter_length = (int) strlen(buf);
  550.     }
  551.  
  552. #ifdef USE_LOCK
  553.     UnsetLock(fd);
  554. #endif
  555.  
  556.     if (digit_info.show == False)
  557.     {
  558.         Image
  559.             *image;
  560.  
  561.         image=CreateBaseImage(1,1,0,0,0,DirectClass);
  562.         if (image == (Image *) NULL)
  563.         {
  564.             PrintHeader();
  565.             StringImage("Failed to create 1x1 GIF image");
  566.             exit(1);
  567.         }
  568.  
  569.         AlphaImage(image,0,0,0);
  570.         PrintHeader();
  571.         (void) WriteGIFImage (image, (char *)NULL);
  572.         DestroyAnyImageStruct (&image);
  573.         exit(0);
  574.     }
  575.  
  576.     if (Gdebug == True)
  577.     {
  578.         if (counter == LimitDigits)
  579.             (void) fprintf (stderr," Counter reached it's limit!\n");
  580.     }
  581.  
  582. if (digit_info.leftpad == False)
  583. {
  584.     (void)sprintf(digitbuf,"%s/%s/%s.gif",
  585.         DigitDir,digit_info.ddhead,ImagePrefix[(int)*buf-'0']);
  586.  
  587.     for(p=buf+1; *p!='\0'; p++)
  588.     {
  589.         count++;
  590.         (void) sprintf(digitbuf, "%s %s/%s/%s.gif",
  591.             digitbuf,DigitDir,digit_info.ddhead, 
  592.             ImagePrefix[(int)*p-'0']);
  593.     }
  594.     MaxDigits=count;
  595. }
  596. else
  597. {
  598.     if (counter_length < MaxDigits)
  599.         left_pad = MaxDigits - counter_length;
  600.     if (Gdebug == True)
  601.     {
  602.         (void) fprintf (stderr," MaxDigits: %d\n",MaxDigits);
  603.         (void) fprintf (stderr," left_pad: %d\n", left_pad);
  604.     }
  605.  
  606.     if ((left_pad < MaxDigits) && (left_pad != 0))
  607.     {
  608.         (void) sprintf(digitbuf, "%s/%s/%s.gif", 
  609.             DigitDir,digit_info.ddhead,ImagePrefix[0]);
  610.         for (i=1; i < left_pad; i++)
  611.         {
  612.             count++;
  613.             (void) sprintf(digitbuf,"%s %s/%s/%s.gif", 
  614.                 digitbuf, DigitDir,digit_info.ddhead,ImagePrefix[0]);
  615.  
  616.         }
  617.  
  618.         for (p=buf; *p != '\0'; p++)
  619.         {
  620.             count++;
  621.             (void) sprintf(digitbuf, "%s %s/%s/%s.gif",
  622.                 digitbuf,DigitDir,digit_info.ddhead,
  623.                 ImagePrefix[(int)*p-'0']);
  624.         }
  625.         MaxDigits=count;
  626.     }
  627.     else    /* MaxDigits*/
  628.     {
  629.         (void) fprintf (stderr," We'r in MaxDigits\n");
  630.  
  631.         for (p=buf; *p != '\0'; p++)
  632.         {
  633.             (void) sprintf(digitbuf, "%s %s/%s/%s.gif",
  634.                 digitbuf,DigitDir,digit_info.ddhead,
  635.                 ImagePrefix[(int)*p-'0']);
  636.         }
  637.     }
  638.  
  639.     if (Gdebug == True)
  640.     {
  641.         (void) fprintf (stderr," digitbuf: %s\n", digitbuf);
  642.         (void) fprintf (stderr," MsxDigits=%d\n", MaxDigits);
  643.     }
  644. }
  645.     /*
  646.     ** now combine the digits and create one GIF file
  647.     */
  648.  
  649.     digit_info.maxdigits=MaxDigits;
  650.     WriteCounterImage(digitbuf, &digit_info,&frame_info);
  651.     if (Gdebug == True)
  652.     {
  653.         (void) fprintf (stderr,"[%s] Count %s: --Debug Ends\n", 
  654.             GetTime(), Version);
  655.         (void) fprintf (stderr," MsxDigits=%d\n", MaxDigits);
  656.     }
  657.  
  658. }
  659.  
  660. /*
  661.  * checkfilename:
  662.  * - check to see if a path was specified - return 1 if so, 0 otherwise
  663.  * it might not be foolproof, but I can't come up with
  664.  * any other ways to specify paths.
  665.  * by carsten@group.com (07/27/95)
  666.  */
  667.  
  668. int checkfilename(str)
  669. char
  670.     *str;
  671. {
  672.     while (*str)
  673.     {
  674.         if (*str == '/' || *str == '~')
  675.             return 1;
  676.         str ++;
  677.     }
  678.     return 0;
  679. }
  680.  
  681. /*
  682. ** check if the counter file exists
  683. */
  684.  
  685. int CheckFile (filename)
  686. char
  687.     *filename;
  688. {
  689.     int
  690.         rc=0;
  691.  
  692.     rc = access (filename, F_OK);
  693.     return rc;
  694. }
  695.  
  696. /*
  697. ** something went wrong..write the built in GIF image to stdout
  698. */
  699.  
  700. void SendErrorImage (bits, length)
  701. unsigned char
  702.     *bits;
  703. int
  704.     length;
  705. {
  706.     register unsigned char
  707.         *p;
  708.  
  709.     register int
  710.         i;
  711.  
  712.     p = bits;
  713.     for (i=0; i < length; i++)
  714.     {
  715.         (void) fputc((char) *p, stdout);
  716.         (void) fflush (stdout);
  717.         p++;
  718.     }
  719. }
  720.  
  721. void PrintHeader ()
  722. {
  723.     if (Gdebug == False)
  724.     {
  725.         (void) fprintf (stdout,
  726.             "Content-type: image/gif%c%c",LF,LF);
  727.         (void) fflush (stdout);
  728.     }
  729.     return;
  730. }
  731.  
  732. /*
  733. ** now combine the digits and create one single GIF image
  734. */
  735. void WriteCounterImage (files,digit_info,frame_info)
  736. char
  737.     *files;
  738. DigitInfo
  739.     *digit_info;
  740. FrameInfo
  741.     *frame_info;
  742. {
  743.     Image
  744.         *framed_image,
  745.         *image;
  746.  
  747.     image = CombineImages(files,
  748.         digit_info->maxdigits*digit_info->width,digit_info->height);
  749.  
  750.     if (image != (Image *) NULL)
  751.     {
  752.         if (digit_info->Frame == True)
  753.         {
  754.             RGB
  755.                color,  
  756.                matte_color;
  757.  
  758.             matte_color.red=frame_info->matte_color.red;
  759.             matte_color.green=frame_info->matte_color.green;
  760.             matte_color.blue=frame_info->matte_color.blue;
  761.              
  762.             frame_info->height=frame_info->width;
  763.             frame_info->outer_bevel=(frame_info->width >> 2)+1;
  764.             frame_info->inner_bevel=frame_info->outer_bevel;
  765.             frame_info->x=frame_info->width;
  766.             frame_info->y=frame_info->height;
  767.             frame_info->width=image->columns+(frame_info->width << 1);
  768.             frame_info->height=image->rows+(frame_info->height << 1);
  769.             frame_info->matte_color=matte_color;
  770.  
  771.             XModulate(&color,matte_color.red,matte_color.green,
  772.                 matte_color.blue, HighlightModulate);
  773.             frame_info->highlight_color.red=color.red;
  774.             frame_info->highlight_color.green=color.green;
  775.             frame_info->highlight_color.blue=color.blue;
  776.  
  777.             XModulate(&color,matte_color.red,matte_color.green,
  778.                 matte_color.blue, ShadowModulate);
  779.             frame_info->shadow_color.red=color.red;
  780.             frame_info->shadow_color.green=color.green;
  781.             frame_info->shadow_color.green=color.green;
  782.  
  783.             framed_image=FrameImage(image,frame_info);
  784.             if (framed_image != (Image *) NULL)
  785.             {
  786.                 DestroyAnyImageStruct (&image);
  787.                 image=framed_image;
  788.             }
  789.  
  790.         }
  791.  
  792.         image->comments = (char *) malloc (1024*sizeof(char));
  793.         if (image->comments != (char *) NULL)
  794.         {
  795.             (void) sprintf(image->comments,"\n%s %s \n%s %s\n%s %s\n",
  796.                 "Count.cgi", Version, "By", Author, "URL:", Url);
  797.         }
  798.          if (digit_info->alpha == True)
  799.              AlphaImage(image,digit_info->alpha_red,digit_info->alpha_green,
  800.                 digit_info->alpha_blue);
  801.          PrintHeader ();
  802.         (void) WriteGIFImage (image, (char *)NULL);
  803.         DestroyAnyImageStruct (&image);
  804.     }
  805.     else
  806.     {
  807.         Warning("Failed to create digit images");
  808.         PrintHeader ();
  809.         StringImage("Failed! Check DigitDir in config.h or dd in QUERY_STRING");
  810.         exit(1);
  811.     }
  812. }
  813.  
  814. void GetDirs()
  815. {
  816.   char path[512], buffer[512], *ptr, *value;
  817.   FILE *cfg;
  818.  
  819.   _execname(path, sizeof(path));
  820.   ptr = strrchr(path, '.');
  821.   strcpy(ptr, ".cfg");
  822.  
  823.   if ((cfg = fopen(path, "r")) != NULL)
  824.   {
  825.     while (fgets(buffer, sizeof(buffer), cfg) != NULL)
  826.     {
  827.       ptr = strtok(buffer, " \t\n");
  828.       value = strtok(NULL, " \t\n");
  829.  
  830.       if (stricmp(ptr, "ConfigDir") == 0)
  831.     strcpy(ConfigDir, value);
  832.       else if (stricmp(ptr, "ConfigFile") == 0)
  833.     strcpy(ConfigFile, value);
  834.       else if (stricmp(ptr, "DigitDir") == 0)
  835.     strcpy(DigitDir, value);
  836.       else if (stricmp(ptr, "DataDir") == 0)
  837.     strcpy(DataDir, value);
  838.       else if (stricmp(ptr, "LogDir") == 0)
  839.     strcpy(LogDir, value);
  840.       else if (stricmp(ptr, "LogFile") == 0)
  841.     strcpy(LogFile, value);
  842.     }
  843.  
  844.     fclose(cfg);
  845.   }
  846. }
  847.