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

  1. /*
  2.  *  WWW document access counter
  3.  *
  4.  *  RCS:
  5.  *      $Revision: 2.3 $
  6.  *      $Date: 1996/05/03 02:20:22 $
  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 "cdebug.h"
  42. #include "combine.h"
  43. #include "count.h"
  44.  
  45.  
  46. #ifdef SYS_WIN32
  47. #include "configNT.h"
  48. #else
  49. #include "config.h"
  50. #endif
  51.  
  52. static char *ImagePrefix[]=
  53. {
  54.     "zero", "one", "two", "three", "four", "five", 
  55.     "six", "seven", "eight", "nine",
  56. };
  57.  
  58.  
  59. void main (argc, argv)
  60. int
  61.     argc;
  62. char
  63.     **argv;
  64.  
  65. {
  66.     int
  67.         rc = 0;
  68.  
  69.     unsigned int
  70.         ignore_site=False;
  71.  
  72.     register int
  73.         i;
  74.  
  75.     char
  76.         *browser_type,
  77.         *remote_ip,
  78.         *query_string;
  79.  
  80.     int
  81.         n;
  82.  
  83.     int
  84.         counter_length;
  85.  
  86.     int
  87.         left_pad;
  88.  
  89.     char
  90.         filename[MaxTextLength];
  91.  
  92.     char
  93.         tmpbuf[MaxTextLength];
  94.  
  95.     char
  96.         digitbuf[MaxTextLength];
  97.  
  98.     int
  99.         fd;
  100.  
  101.     char
  102.         format[10],
  103.         buf[50];
  104.  
  105.     int
  106.         count,
  107.         counter;
  108.  
  109.     int
  110.         tagdigit;
  111.  
  112.     int
  113.         MaxDigits=10;
  114.  
  115.     DigitInfo
  116.         digit_info;
  117.  
  118.     FrameInfo
  119.         frame_info;
  120.  
  121.     unsigned int
  122.         use_st;
  123.     
  124.     int
  125.         min_dig1,
  126.         min_dig2;
  127.  
  128.     int
  129.         mon_dig1,
  130.         mon_dig2,
  131.         day_dig1,
  132.         day_dig2,
  133.         year_dig1,
  134.         year_dig2;
  135.  
  136.      char
  137.         hour[10],
  138.         min[10],
  139.         ampm[10];
  140.  
  141.     int
  142.         display_what;
  143.  
  144.     unsigned int
  145.         untrusted_browser=False;
  146.  
  147.  
  148. #ifdef ACCESS_AUTH
  149.     char
  150.         *rem_refh;
  151. #endif
  152.  
  153. /*
  154. **---------initialize globals------Starts---
  155. */
  156.     for (i=0; i < MaxSites; i++)
  157.     {
  158.         GrefererHost[i] = (char *) NULL;
  159.         GignoreSite[i] = (char *) NULL;
  160.     }
  161.     Grhost=0;
  162.     Gsite=0;
  163.     Gdebug=False;
  164.     Gauto_file_creation=0;
  165.     Gstrict_mode=1;
  166.     GrgbMappingIsError=1;
  167. /*
  168. **---------initialize globals------Ends---
  169. */
  170.     count=1;
  171.     *hour='\0';
  172.     *min='\0';
  173.     *ampm='\0';
  174.     *format='\0';
  175.     *buf='\0';
  176.     *filename = '\0';
  177.     *digitbuf='\0';
  178.     *tmpbuf = '\0';
  179.     counter = 0;
  180.     tagdigit=9;
  181.     left_pad=MaxDigits;
  182.     use_st=False;
  183.     display_what=SHOW_COUNTER;
  184.     remote_ip=(char *) NULL;
  185.  
  186.     /*
  187.     ** parse command line, this is only used for testing at commandline
  188.     ** no command line flag is allowed in the web page while calling
  189.     ** the program
  190.     */
  191.  
  192.     for (i=1; i < argc; i++)
  193.     {
  194.         if (!strncmp(argv[i],"-debug",(int)strlen("-debug")))
  195.         {
  196.             Gdebug=True;
  197.             break;
  198.         }
  199.     }
  200.  
  201.     Debug2("[%s] Count %s: --Debug--",GetTime(),Version);
  202.  
  203. #ifdef TEST_RRR
  204.     /*************REMOVE****************/
  205.     env_test=getenv("PATH_INFO");
  206.     if (env_test == (char *) NULL)
  207.     {
  208.         (void) strcpy(tmpbuf,"PATH_INFO is NULL");
  209.     }
  210.     else
  211.     {
  212.         (void) sprintf(tmpbuf,"PATH_INFO is=%s\n",env_test);
  213.     }
  214.     Warning(tmpbuf);
  215.  
  216.     env_test=getenv("PATH_TRANSLATED");
  217.     if (env_test == (char *) NULL)
  218.     {
  219.         (void) strcpy(tmpbuf,"PATH_TRANSLATED is NULL");
  220.     }
  221.     else
  222.     {
  223.         (void) sprintf(tmpbuf,"PATH_TRANSLATED=%s\n",env_test);
  224.     }
  225.     Warning(tmpbuf);
  226.     /*************REMOVE****************/
  227. #endif
  228.     rc=CheckDirs();
  229.     if (rc == 1)
  230.     {
  231.         *tmpbuf='\0';
  232.         (void) sprintf(tmpbuf,"ConfigDir,DigitDir,DataDir,LogDir must differ");
  233.         Warning(tmpbuf);
  234.         PrintHeader();
  235.         StringImage(tmpbuf);
  236.         exit(1);
  237.     }
  238.  
  239.     /*
  240.     ** parse the authorization list
  241.     */
  242.     rc = ParseConfig ();
  243.  
  244.     switch (rc)
  245.     {
  246.         case ConfigOpenFailed:
  247.         {
  248.             *tmpbuf='\0';
  249.             (void) sprintf (tmpbuf, 
  250.                 "Faliled to open configuration file: \"%s/%s\"",
  251.                     ConfigDir,ConfigFile);
  252.             Warning (tmpbuf);
  253.             PrintHeader ();
  254.             StringImage (tmpbuf);
  255.             exit(1);
  256.             break;
  257.         }
  258.  
  259.         case NoAutofcBlock:
  260.         {
  261.             *tmpbuf='\0';
  262.             (void) sprintf (tmpbuf,
  263.                 "No auto file creation block in conf file: \"%s/%s\"",
  264.                     ConfigDir,ConfigFile);
  265.             Warning(tmpbuf);
  266.             PrintHeader ();
  267.             StringImage(tmpbuf);
  268.             exit(1);
  269.             break;
  270.         }
  271.  
  272.         case NoStrictBlock:
  273.         {
  274.             *tmpbuf='\0';
  275.             (void) sprintf (tmpbuf,
  276.                 "No Strict mode block in conf file: \"%s/%s\"",
  277.                     ConfigDir,ConfigFile);
  278.             Warning(tmpbuf);
  279.             PrintHeader ();
  280.             StringImage(tmpbuf);
  281.             exit(1);
  282.             break;
  283.         }
  284.         case NoIgnoreHostsBlock:
  285.         {
  286.             *tmpbuf='\0';
  287.             (void) sprintf (tmpbuf,
  288.                 "No IgnoreHosts Block in the configuration file: \"%s/%s\"",
  289.                     ConfigDir,ConfigFile);
  290.  
  291.             Warning(tmpbuf);
  292.             PrintHeader ();
  293.             StringImage(tmpbuf);
  294.             exit(1);
  295.         }
  296.  
  297.         case NoRefhBlock:
  298.         {
  299.             *tmpbuf='\0';
  300.             (void) sprintf(tmpbuf,"Compiled with -DACCESS_AUTH,but no such block in configuration file!");
  301.             Warning(tmpbuf);
  302.             PrintHeader ();
  303.             StringImage(tmpbuf);
  304.             exit(1);
  305.         }
  306.  
  307.         case UnpexpectedEof:
  308.         {
  309.             *tmpbuf='\0';
  310.             (void) sprintf (tmpbuf, 
  311.             "Unexpected EOF in configuration file: \"%s/%s\"",
  312.                 ConfigDir,ConfigFile);
  313.             Warning(tmpbuf);
  314.             PrintHeader ();
  315.             StringImage(tmpbuf);
  316.             exit(1);
  317.         }
  318.  
  319.     } /* switch (rc) */
  320.  
  321.  
  322.         Debug2("Gsite: %d",Gsite,0);
  323.         Debug2("Gauto_file_creation= %d",Gauto_file_creation,0);
  324.         Debug2("Gstrict_mode= %d",Gstrict_mode,0);
  325.  
  326. #ifdef ACCESS_AUTH
  327.     /*
  328.     ** check if the referer is a remote host or not. refere should
  329.     ** be the local host.
  330.     */
  331.  
  332.     rem_refh = (char *) getenv("HTTP_REFERER");
  333.     if (rem_refh != (char *) NULL)
  334.     {
  335.         char
  336.             http_ref[1024],
  337.             Rhost[1024];
  338.         *http_ref = '\0';
  339.         *Rhost = '\0';
  340.         /*
  341.         ** this will be same as your host when accessed from your
  342.         ** page. if the host is anything else, it is an unauthorized
  343.         ** access. handle it.
  344.         */
  345.         *tmpbuf='\0';
  346.         (void) strcpy (http_ref, rem_refh);
  347.         GetRemoteReferer(http_ref, Rhost);
  348.  
  349.         /*
  350.             (void) sprintf(tmpbuf,"http_ref=%s",http_ref);
  351.             Warning(tmpbuf);
  352.         */
  353.  
  354.         Debug2("Grhost= %d",Grhost,0);
  355.         Debug2("Rhost= %s",Rhost,0);
  356.  
  357.         if (*Rhost != '\0')
  358.         {
  359.             if (Grhost > 0)
  360.             {
  361.                 for (i=0; i < Grhost; i++)
  362.                 {
  363.                     rc=mystrcasecmp(Rhost,GrefererHost[i]);
  364.                     if (rc == 0)
  365.                         break;
  366.                 }
  367.             }
  368.             if (rc != 0)
  369.             {
  370.                 *tmpbuf='\0';
  371.               (void) sprintf(tmpbuf,
  372.               "Host: \"%s\" is not in the auth block of the conf file",Rhost);
  373.                 Warning(tmpbuf);                    
  374.                 PrintHeader();
  375.                 StringImage(tmpbuf);
  376.                 exit(1);
  377.             }
  378.         }
  379.     }
  380.  
  381. #endif /* ACCESS_AUTH */
  382.     /*
  383.     ** get the user name from query string
  384.     */
  385.     query_string = (char *) getenv("QUERY_STRING");
  386.  
  387.     if (query_string == (char *) NULL)
  388.     {
  389.         *tmpbuf='\0';
  390.         (void) sprintf(tmpbuf,"%s","Empty QUERY_STRING!");
  391.         Warning(tmpbuf);
  392.         PrintHeader ();
  393.         StringImage(tmpbuf);
  394.         exit(1);
  395.     }
  396.  
  397.     rc=ParseQueryString(query_string,&digit_info,&frame_info);
  398.  
  399.     Debug2("\n",0,0);
  400.     Debug2("Parsed QUERY_STRING",0,0); 
  401.     Debug2(" ft=%d",frame_info.width,0);
  402.     Debug4(" rgb=%d,%d,%d", frame_info.matte_color.red,
  403.         frame_info.matte_color.green, frame_info.matte_color.blue,0);
  404.     Debug2(" tr=%d",digit_info.alpha,0);
  405.     Debug4(" trgb=%d,%d,%d",digit_info.alpha_red,
  406.         digit_info.alpha_green,digit_info.alpha_blue,0);
  407.     Debug2(" replace_color=%d",digit_info.replace_color,0);
  408.     Debug4(" srgb=%d,%d,%d",
  409.         digit_info.opaque_red,
  410.         digit_info.opaque_green,
  411.         digit_info.opaque_blue,
  412.         0);
  413.     Debug4(" prgb=%d,%d,%d",
  414.         digit_info.pen_red,
  415.         digit_info.pen_green,
  416.         digit_info.pen_blue,
  417.         0);
  418.     Debug2(" maxdigits=%d",digit_info.maxdigits,0);
  419.     Debug2(" wxh [ignored,exists for compatibity] =%dx%d", 
  420.         digit_info.width, digit_info.height);
  421.     Debug2(" md=%d", digit_info.maxdigits,0);
  422.     Debug2(" pad=%d", digit_info.leftpad,0);
  423.     Debug2(" ddhead=%s",digit_info.ddhead,0);
  424.     Debug2(" st=%d",digit_info.st,0);
  425.     Debug2(" sh=%d", digit_info.show,0);
  426.     Debug2(" df=%s",digit_info.datafile,0);
  427.     Debug2(" lit=%s",digit_info.literal,0);
  428.     Debug2(" incr=%d",digit_info.increment_counter,0);
  429.     Debug2(" negate=%d",digit_info.negate,0);
  430.     Debug2(" rotate=%d",digit_info.rotate,0);
  431.     Debug2(" degrees=%d",digit_info.rotate_degrees,0);
  432.     Debug2(" timezone=%s",digit_info.time_z,0);
  433.     Debug2(" timeformat=%d",digit_info.time_format,0);
  434.     Debug2(" istrip=%d",digit_info.use_strip,0);
  435.     Debug2(" image=%s", digit_info.gif_file,0);
  436.     Debug2(" parsed QS--\n",0,0);
  437.  
  438.     if (rc)
  439.     {
  440.         Debug2("rc from from ParseQueryString()=%d",rc,0);
  441.         exit(1);
  442.     }
  443.  
  444.     if (digit_info.leftpad == True)
  445.     {
  446.         MaxDigits=digit_info.maxdigits;
  447.  
  448.         if ((MaxDigits < 5) || (MaxDigits > 10))
  449.         {
  450.             Warning("Maxdigits (md) must be >= 5 and <= 10");
  451.             PrintHeader ();
  452.             StringImage("Maxdigits (md) must be >= 5 and <= 10");
  453.             exit(1);
  454.         }
  455.     }
  456.  
  457.     /*
  458.     ** now find out what we'r trying to display
  459.     */
  460.     display_what=digit_info.display_type;
  461.  
  462.     if (display_what == SHOW_COUNTER)
  463.     {
  464.         if (checkfilename (digit_info.datafile) != 0)
  465.         {
  466.             *tmpbuf='\0';
  467.             (void) sprintf(tmpbuf,"Illegal datafile path!");
  468.             Warning(tmpbuf);
  469.             PrintHeader ();
  470.             StringImage(tmpbuf);
  471.             exit(1);
  472.         }
  473.     }
  474.     /*
  475.     ** get frameinfo
  476.     */
  477.  
  478.     if (frame_info.width > 1)
  479.         digit_info.Frame=True;
  480.     else
  481.         digit_info.Frame=False;
  482.     /*
  483.     ** get the IP address of the connected machine to check if we need
  484.     ** to increment the counter
  485.     */
  486.     if (display_what == SHOW_COUNTER)
  487.     {
  488.         remote_ip = (char *) getenv("REMOTE_ADDR");
  489.         if (remote_ip == (char *) NULL)
  490.         {
  491.             /*
  492.             ** put a dummy here
  493.             */
  494.             remote_ip = "dummy_ip";
  495.         }
  496.         else
  497.         {
  498.             for (i=0; i < Gsite; i++)
  499.             {
  500.                 ignore_site=CheckRemoteIP(remote_ip,GignoreSite[i]);
  501.                 if (ignore_site == True)
  502.                 {
  503.                     Debug2("Not counting IP: %s",remote_ip,0);
  504.                     Debug2("GignoreSite[%d]:%s",i,GignoreSite[i]);
  505.                     break;
  506.                 }
  507.             }
  508.         }
  509.     }
  510.  
  511.     /*
  512.     ** initialize Limit array
  513.     */
  514.  
  515.  
  516.     if (display_what == SHOW_COUNTER)
  517.     {
  518.         Debug2("Maxdigits=%d",MaxDigits,0);
  519.     }
  520.  
  521. #ifdef ACCESS_AUTH 
  522.     if (Gstrict_mode == 1)
  523.     {
  524.         if (rem_refh == (char *) NULL)
  525.         {
  526.             untrusted_browser=True;
  527.         /*
  528.         ** no HTTP_REFERER env variable found.
  529.         ** display a literal string. this will make sure that even if
  530.         ** someone with a broken browser tries to access the counter
  531.         ** remotely, will not mess up the datafile. of course we'll
  532.         ** miss some counts. because anyone accesses the page with a 
  533.         ** broken browser like this will see a literal string
  534.         */
  535.             (void) strcpy(digit_info.literal,"888888");
  536.         /*
  537.         if (remote_ip != (char *) NULL)
  538.         {
  539.             (void) sprintf(tmpbuf,"No HTTP_REFERER supplied from %s",
  540.                 remote_ip);
  541.             Warning(tmpbuf);
  542.         }
  543.         */
  544.         /*
  545.         ** try to get the browser name, it will give us a good
  546.         ** feedback.
  547.         */
  548.             browser_type=(char *) getenv("HTTP_USER_AGENT");
  549.             if (browser_type != (char *) NULL)
  550.             {
  551.                 if (remote_ip != (char *) NULL)
  552.                 {
  553.                 *tmpbuf='\0';
  554.                 (void) sprintf(tmpbuf,"Untrusted browser %s",browser_type);
  555.                 Warning(tmpbuf);
  556.                 }
  557.             }
  558.         }
  559.     }   /* Gstrict_mode == 1 */
  560. #endif
  561.  
  562.     switch (display_what)
  563.     {
  564.  
  565.         case SHOW_CLOCK: /* act as a clock*/
  566.         {
  567.             time_t
  568.                 daytime,
  569.                 tm;
  570.  
  571.             struct tm
  572.                 *Tm=(struct tm *) NULL;
  573.  
  574.             long
  575.                 diff;   /* in seconds */
  576.  
  577.             if (untrusted_browser == False)
  578.             {
  579.                 tm=time(NULL);
  580.                 if (*digit_info.time_z != '\0')
  581.                 {
  582.                     /*
  583.                     ** no more TZ, 03/26/96
  584.                     */
  585.                     diff=checkTimezone(digit_info.time_z);
  586.  
  587.                     Tm=gmtime(&tm);
  588. #ifdef HAVE_MKTIME
  589.                     daytime=mktime(Tm);
  590. #else
  591.                     daytime=netMktime(Tm);
  592. #endif
  593.                     daytime += diff;
  594.                     Tm=localtime(&daytime);
  595.  
  596.                 }
  597.                 else
  598.                 {
  599.                     Debug2("No timezone",0,0);
  600.                     Tm=localtime(&tm);
  601.                 } 
  602.                 if (digit_info.time_format == 12)
  603.                 {
  604.                     if ((Tm)->tm_hour < 12)
  605.                         (void) strcpy(ampm,"A");
  606.                     else
  607.                         (void) strcpy(ampm,"P");
  608.         
  609.                     if ((Tm)->tm_hour > 12)
  610.                         (Tm)->tm_hour = (Tm)->tm_hour-12;
  611.   
  612.                     if ((Tm)->tm_hour == 0)  
  613.                         (Tm)->tm_hour=12;
  614.                 }
  615.             /*
  616.             ** take off strftime(), 1/13/95, muquit
  617.             */
  618.                 (void) sprintf(hour,"%d",(Tm)->tm_hour);
  619.              
  620.             /*
  621.             ** I like to keep leading zeros for minutes
  622.             */
  623.                 min_dig1=(Tm->tm_min - (Tm->tm_min % 10)) / 10;
  624.                 min_dig2=Tm->tm_min % 10;
  625.                 (void) sprintf(min,"%d%d",min_dig1,min_dig2);
  626.                 (void) sprintf(buf,"%s:%s%s",hour,min,ampm);
  627.             } 
  628.             else
  629.             {
  630.                (void) strcpy(buf,"888888");
  631.             }
  632.          
  633.             Debug2(" time buf= %s",buf,0);
  634.  
  635.             *digitbuf='\0';
  636.             (void) strcpy(digitbuf,buf);
  637.             WriteCounterImage(digitbuf, &digit_info,&frame_info);
  638.             
  639.             /*
  640.             ** we will not be here
  641.             */
  642.             exit(0);
  643.             break;
  644.         }
  645.  
  646.         case SHOW_DATE:
  647.         {
  648.             time_t
  649.                 daytime,
  650.                 tm;
  651.  
  652.             struct tm
  653.                 *Tm;
  654.  
  655.             long
  656.                 diff;   /* in seconds */
  657.  
  658.             if (untrusted_browser == False)
  659.             {
  660.                 tm=time(NULL);
  661.                 if (*digit_info.time_z != '\0')
  662.                 {
  663.  
  664.                     /*
  665.                     ** no more TZ, 03/26/96
  666.                     */
  667.                     diff=checkTimezone(digit_info.time_z);
  668.                     Tm=gmtime(&tm);
  669. #ifdef HAVE_MKTIME
  670.                     daytime=mktime(Tm);
  671. #else
  672.                     daytime=netMktime(Tm);
  673. #endif
  674.                     daytime += diff;
  675.                     Tm=localtime(&daytime);
  676.                 }
  677.                 else
  678.                 {
  679.                     Tm=localtime(&tm);
  680.                 }
  681.                 Tm->tm_mon++;
  682.  
  683.                 Debug2(" Inside SHOW_DATE",0,0);
  684.  
  685.                 /*
  686.                 ** padding, saw in xdaliclock
  687.                 */
  688.                 mon_dig1=(Tm->tm_mon-(Tm->tm_mon % 10)) / 10;
  689.                 mon_dig2=Tm->tm_mon % 10;
  690.  
  691.                 day_dig1=(Tm->tm_mday-(Tm->tm_mday % 10)) / 10;
  692.                 day_dig2=Tm->tm_mday % 10;
  693.  
  694.                 year_dig1=(Tm->tm_year-(Tm->tm_year % 10)) / 10;
  695.                 year_dig2=Tm->tm_year % 10;
  696.  
  697.  
  698.                 switch (digit_info.date_format)
  699.                 {
  700.                     case DATE_MMDDYY:
  701.                     default:
  702.                     {
  703.                         (void) sprintf(buf,"%d%d-%d%d-%d%d",
  704.                     mon_dig1,mon_dig2,day_dig1,day_dig2,year_dig1,year_dig2);
  705.                         break;
  706.                     }
  707.  
  708.                     case DATE_DDMMYY:
  709.                     {
  710.                         (void) sprintf(buf,"%d%d-%d%d-%d%d",
  711.                     day_dig1,day_dig2,mon_dig1,mon_dig2,year_dig1,year_dig2);
  712.                         break;
  713.                     }
  714.  
  715.                     case DATE_YYMMDD:
  716.                     {
  717.                         (void) sprintf(buf,"%d%d-%d%d-%d%d",
  718.                     year_dig1,year_dig2,mon_dig1,mon_dig2,day_dig1,day_dig2);
  719.                         break;
  720.                     }
  721.  
  722.                     case DATE_YYDDMM:
  723.                     {
  724.                         (void) sprintf(buf,"%d%d-%d%d-%d%d",
  725.                     year_dig1,year_dig2,day_dig1,day_dig2,mon_dig1,mon_dig2);
  726.                         break;
  727.                     }
  728.  
  729.                     case DATE_MMYYDD:
  730.                     {
  731.                         (void) sprintf(buf,"%d%d-%d%d-%d%d",
  732.                     mon_dig1,mon_dig2,year_dig1,year_dig2,day_dig1,day_dig2);
  733.                         break;
  734.                     }
  735.  
  736.                     case DATE_DDYYMM:
  737.                     {
  738.                         (void) sprintf(buf,"%d%d-%d%d-%d%d",
  739.                     day_dig1,day_dig2,year_dig1,year_dig2,mon_dig1,mon_dig2);
  740.                         break;
  741.                     }
  742.                 }
  743.  
  744.                 Debug2(" date buf=%s",buf,0);
  745.             }
  746.             else
  747.             {
  748.                 (void) strcpy(buf,"888888");
  749.             }
  750.  
  751.             (void) strcpy(digitbuf,buf);
  752.             WriteCounterImage (digitbuf, &digit_info,&frame_info);
  753.             /*
  754.             ** we won't be here
  755.             */
  756.             break;
  757.         }
  758.  
  759.         case SHOW_GIF_FILE:
  760.         {
  761.             if (*digit_info.gif_file == '\0')
  762.             {
  763.                 PrintHeader();
  764.                 StringImage("No GIF file specified to dispaly");
  765.                 exit(1);
  766.             }
  767.             (void) sprintf(digitbuf,"%s/%s/%s",
  768.                 DigitDir,digit_info.ddhead,digit_info.gif_file);
  769.             WriteCounterImage(digitbuf,&digit_info,&frame_info);
  770.             /*
  771.             ** we won't be here
  772.             */
  773.             break;
  774.         }
  775.         case SHOW_COUNTER:
  776.         default:
  777.         {
  778.  
  779.             if (digit_info.comma == True)
  780.                 digit_info.leftpad=False;
  781.             if ((int) strlen(digit_info.literal) > 0)
  782.             {
  783.                 /*
  784.                 ** only copy 10 digits, otherwise we take the risk
  785.                 ** of buffer overflow
  786.                 */
  787.                 if (strlen(digit_info.literal) > 10)
  788.                     (void) strncpy(buf, digit_info.literal,10);
  789.                 else
  790.                 {
  791.                     (void) strcpy(buf, digit_info.literal);
  792.                 }
  793.                 if (digit_info.comma == True)
  794.                     (void) sprintf(buf,"%d",atoi(buf));
  795.                 digit_info.leftpad=False;
  796.             }
  797.             else if (mystrcasecmp(digit_info.datafile,DfForRandom) == 0)
  798.             {
  799.                 srand(time(NULL));  /* Seed number generator */
  800.                 counter = rand();   /* My psychic prediction of counter value */
  801.  
  802.                 /*
  803.                 ** we do not want to overflow buffer
  804.                 */
  805.                 Debug2("random number=%d",counter,0);
  806.  
  807.                 *tmpbuf='\0';
  808.                 (void) sprintf(tmpbuf,"%d",counter);
  809.                 if (strlen(tmpbuf) > 10)
  810.                     (void) strncpy(buf,tmpbuf,10);
  811.                 else
  812.                     (void) strcpy(buf,tmpbuf);
  813.               Debug2("random number after bound checning=%s",buf,0);
  814.               digit_info.leftpad=False;
  815.             }
  816.             else
  817.             {
  818.  
  819.             (void) strcpy(filename, DataDir);
  820.             (void) strcat(filename, "/");
  821.             (void) strcat (filename, digit_info.datafile);
  822.  
  823.             /*
  824.             ** check if the counter file exists or not
  825.             */
  826.         if (Gauto_file_creation == 0)
  827.         {
  828.             if (CheckFile (filename) != 0)
  829.             {
  830.                 *tmpbuf='\0';
  831.                 (void) sprintf (tmpbuf,
  832.                     "Counter datafile \"%s\" must be created first!", filename);
  833.                 Warning(tmpbuf);
  834.                 PrintHeader ();
  835.                 StringImage (tmpbuf);
  836.                 exit(1);
  837.             }
  838.  
  839.         }
  840.         else
  841.         {
  842.             if (CheckFile (filename) != 0)
  843.                 use_st=True;
  844.         }
  845. #ifdef SYS_WIN32
  846.         fd=sopen(filename,_O_RDWR | _O_CREAT, _SH_DENYWR, _S_IREAD |_S_IWRITE);
  847. #else
  848.         fd = open (filename, O_RDWR | O_CREAT,0644);
  849. #endif
  850.         if (fd < 0)
  851.         {
  852.             *tmpbuf='\0';
  853.             if (Gauto_file_creation == 1)
  854.             {
  855.                 if (CheckFile (filename) != 0)
  856.                     (void) sprintf(tmpbuf,
  857.                     "Could not create data file: \"%s\"",filename);
  858.                 else
  859.                     (void) sprintf (tmpbuf,
  860.                     "Could not write to counter file: \"%s\"", filename);
  861.             }
  862.             else
  863.                 (void) sprintf (tmpbuf,
  864.                 "Could not write to counter file: \"%s\"", filename);
  865.  
  866.             Warning(tmpbuf);
  867.             PrintHeader ();
  868.             StringImage(tmpbuf);
  869.             exit(1);
  870.         }
  871.  
  872. #ifdef SYS_UNIX
  873.         SetLock(fd);
  874. #endif
  875.         /*
  876.         ** try to read from the file
  877.         */
  878.  
  879.         lseek(fd,0L,0);
  880.         /*        n = read(fd, buf, MaxDigits);*/
  881.         n = read(fd, buf, 10);
  882.  
  883.         if (n > 0)
  884.         {
  885.  
  886.  
  887.             /*
  888.             ** check if the datafile is edited, 
  889.             ** NULL terminate at first non-digit
  890.             */
  891.             for (i=0; i < n; i++)
  892.             {
  893.                 if (!isdigit(buf[i]))
  894.                 {
  895.                     buf[i]='\0';
  896.                     break;
  897.                 }
  898.             }
  899.             if (i == n)
  900.                 buf[n]='\0';
  901.  
  902.             Debug2("In buffer=%s",buf,0);
  903.  
  904.             if (*buf == '\0')
  905.                 counter=0;
  906.             else
  907.                 counter = atoi(buf);
  908.  
  909.             if (counter < 0)
  910.             {
  911.                 /*
  912.                 ** possibly we reached the limit, the digit didn't fit
  913.                 ** in an int
  914.                 */
  915.                 PrintHeader();
  916.                 StringImage("The digit did not fit in a signed int!");
  917.                 exit(1);
  918.             }
  919.  
  920.             *buf='\0';
  921.             (void) sprintf(buf,"%d",counter);
  922.         
  923.             Debug2(" before increment=%d",counter,0);
  924.             if (counter == 0)
  925.                 counter_length = 1;
  926.             else
  927.             {
  928.  
  929.                 if (digit_info.increment_counter == True)
  930.                     counter++;
  931.                 (void) sprintf(buf, "%d", counter);
  932.                 counter_length = (int) strlen(buf);
  933.             } 
  934.  
  935.             Debug2(" after increment=%d",counter,0);
  936.  
  937.             if (ignore_site  == False)
  938.             {
  939.                 lseek(fd,0L,0);
  940.                 (void) write(fd, buf, (int)strlen(buf));
  941.                 (void) close (fd); /*unlocks as well */
  942.             }
  943.         }
  944.         else
  945.         {
  946.             if (use_st == True)
  947.             {
  948.                 counter=digit_info.st;
  949.                 Debug2("counter=%d",counter,0);
  950.             }
  951.             Debug2(" n < 0",0,0);
  952.             Debug2(" before increment=%d",counter,0);
  953.  
  954.             if ( digit_info.increment_counter==True )
  955.                  counter++;
  956.  
  957.             (void) sprintf(buf, "%d", counter);
  958.             Debug2(" after increment=%d",counter,0);
  959.  
  960.             lseek(fd,0L,0);
  961.             write (fd, buf, (int) strlen(buf));
  962.             (void) close (fd);
  963.         }
  964.  
  965. #ifdef SYS_UNIX
  966.         UnsetLock(fd);
  967. #endif
  968.     }
  969.  
  970.     counter_length = (int) strlen(buf);
  971.  
  972.         if (digit_info.show == False)
  973.         {
  974.             Image
  975.                 *image;
  976.  
  977.             image=CreateBaseImage(1,1,0,0,0,DirectClass);
  978.             if (image == (Image *) NULL)
  979.             {
  980.                 PrintHeader();
  981.                 StringImage("Failed to create 1x1 GIF image");
  982.                 exit(1);
  983.             }
  984.  
  985.             AlphaImage(image,0,0,0);
  986.             PrintHeader();
  987.             (void) WriteGIFImage (image, (char *)NULL);
  988.             DestroyAnyImageStruct (&image);
  989.             exit(0);
  990.         }
  991.  
  992.        if (digit_info.leftpad == False)    /* no left padding */
  993.        {
  994.             (void) strcpy(digitbuf,buf);
  995.             WriteCounterImage(digitbuf,&digit_info,&frame_info);
  996.             /*
  997.             ** we will not be here, we'll exit from LoadDigits()
  998.             */
  999.         }
  1000.         else
  1001.         {
  1002.             if (counter_length < MaxDigits)
  1003.                 left_pad = MaxDigits - counter_length;
  1004.             else
  1005.                 left_pad=0;
  1006.  
  1007.             Debug2(" MaxDigits=%d",MaxDigits,0);
  1008.             Debug2(" left_pad=%d",left_pad,0);
  1009.  
  1010.               if ((left_pad < MaxDigits) && (left_pad != 0))
  1011.               {
  1012.  
  1013.                 (void) strcpy(digitbuf,"0");
  1014.                 for (i=1; i < left_pad; i++)
  1015.                 {
  1016.                     (void) sprintf(digitbuf,"%s0",digitbuf);
  1017.                 }
  1018.                 (void) sprintf(digitbuf,"%s%s",digitbuf,buf);
  1019.                 WriteCounterImage(digitbuf,&digit_info,&frame_info);
  1020.                 /*
  1021.                 ** we will not be here
  1022.                 */
  1023.               }
  1024.               else    /* MaxDigits*/
  1025.               {
  1026.  
  1027.                 Debug2(" We are in MaxDigits=%d",MaxDigits,0);
  1028.  
  1029.                 (void) strcpy(digitbuf,buf);
  1030.                     WriteCounterImage(digitbuf,&digit_info,&frame_info);
  1031.                 /*
  1032.                 ** we won't be here
  1033.                 */
  1034.                }
  1035.  
  1036.             }
  1037.             exit(0);
  1038.         } /* case SHOW_COUNTER*/
  1039.     }
  1040. }
  1041.  
  1042. /*
  1043.  * checkfilename:
  1044.  * - check to see if a path was specified - return 1 if so, 0 otherwise
  1045.  * it might not be foolproof, but I can't come up with
  1046.  * any other ways to specify paths.
  1047.  * by carsten@group.com (07/27/95)
  1048.  * ..\filename was not getting ignored on NT
  1049.  * reported by asolberg@pa.net>
  1050.  * fixed: 04/19/96
  1051.  */
  1052.  
  1053. int checkfilename(str)
  1054. char
  1055.     *str;
  1056. {
  1057.     while (*str)
  1058.     {
  1059.         if ((*str == '/') || 
  1060.             (*str == '\\') || 
  1061.             (*str == ':') ||
  1062.             (*str == '~'))
  1063.             return 1;
  1064.         str ++;
  1065.     }
  1066.     return 0;
  1067. }
  1068.  
  1069. /*
  1070. ** check if the counter file exists
  1071. */
  1072.  
  1073. int CheckFile (filename)
  1074. char
  1075.     *filename;
  1076. {
  1077.     int
  1078.         rc=0;
  1079.  
  1080.     rc = access (filename, F_OK);
  1081.     return rc;
  1082. }
  1083.  
  1084. /*
  1085. ** something went wrong..write the built in GIF image to stdout
  1086. */
  1087.  
  1088. void SendErrorImage (bits, length)
  1089. unsigned char
  1090.     *bits;
  1091. int
  1092.     length;
  1093. {
  1094.     register unsigned char
  1095.         *p;
  1096.  
  1097.     register int
  1098.         i;
  1099.  
  1100.     p = bits;
  1101.     for (i=0; i < length; i++)
  1102.     {
  1103.         (void) fputc((char) *p, stdout);
  1104.         (void) fflush (stdout);
  1105.         p++;
  1106.     }
  1107. }
  1108.  
  1109. void PrintHeader ()
  1110. {
  1111.     if (Gdebug == False)
  1112.     {
  1113.         (void) fprintf (stdout,
  1114.             "Content-type: image/gif%c%c",LF,LF);
  1115.         (void) fflush (stdout);
  1116.     }
  1117.     return;
  1118. }
  1119.  
  1120. void WriteCounterImage(digitbuf,digit_info,frame_info)
  1121. char
  1122.     *digitbuf;
  1123. DigitInfo
  1124.     *digit_info;
  1125. FrameInfo
  1126.     *frame_info;
  1127. {
  1128.    Image
  1129.         *image;
  1130.  
  1131.  
  1132.    if (digit_info->display_type == SHOW_GIF_FILE)
  1133.    {
  1134.        Debug2("Displaying GIF file=\"%s\"",digitbuf,0);
  1135.        image=ReadImage(digitbuf);
  1136.    }
  1137.    else
  1138.    {
  1139.         image=CombineImages(digitbuf,digit_info);
  1140.    }
  1141.  
  1142.    if (image != (Image *) NULL)
  1143.    {
  1144.         MogrifyImage(&image,digit_info,frame_info);
  1145.         PrintHeader();
  1146.         (void) WriteGIFImage (image, (char *)NULL);
  1147.    }
  1148.    else
  1149.    {
  1150.         PrintHeader();
  1151.         StringImage("Failed! Check DigitDir in config.h or dd in QUERY_STRING");
  1152.    }
  1153.  
  1154.  
  1155.    exit(1);
  1156. }
  1157.  
  1158. Image *CombineImages(digitbuf,digit_info)
  1159. char
  1160.     *digitbuf;
  1161. DigitInfo
  1162.     *digit_info;
  1163. {
  1164.     register char
  1165.         *p;
  1166.  
  1167.     char
  1168.         tmpbuf[MaxTextLength];
  1169.  
  1170.     int
  1171.         rc=0;
  1172.  
  1173.     unsigned int
  1174.         bwidth,
  1175.         bheight,
  1176.         gbW,
  1177.         gbH,
  1178.         base_width,
  1179.         base_height;
  1180.  
  1181.     Image
  1182.         *strip_image,
  1183.         *sub_image,
  1184.         *base_image;
  1185.  
  1186.     int
  1187.         nsegment,
  1188.         segment;
  1189.  
  1190.     int
  1191.         *seg_array=(int *) NULL;
  1192.  
  1193.     RectangleInfo
  1194.         rinfo;
  1195.     int
  1196.         n;
  1197.  
  1198.     int
  1199.         i;
  1200.     char
  1201.         *token;
  1202.  
  1203.     segment=0;
  1204.     bwidth=0;
  1205.     bheight=0;
  1206.     gbW=0;
  1207.     gbH=0;
  1208.     base_width=0;
  1209.     base_height=0;
  1210.     strip_image=(Image *) NULL;
  1211.  
  1212.     /*
  1213.     ** if comma is requesed, commaize (my new invented word!) the
  1214.     ** digit. also it's meaningness to left pad while commizing,
  1215.     ** therefore, don't left pad with zeros as well
  1216.     */
  1217.     if ((digit_info->display_type == (unsigned int) SHOW_COUNTER) &&
  1218.         (digit_info->comma == True))
  1219.     {
  1220.         Commaize(digitbuf);
  1221.         Debug2("after commaze=%s",digitbuf,0);
  1222.     }
  1223.     /*
  1224.     ** if image strip is not used, we'll handle it as usual
  1225.     */
  1226. if (digit_info->use_strip == False)
  1227. {
  1228.     for (p=digitbuf; *p != '\0'; p++)
  1229.     {
  1230.         *tmpbuf='\0';
  1231.         if(isdigit(*p))
  1232.             (void) sprintf(tmpbuf,"%s/%s/%s.gif",
  1233.                 DigitDir,digit_info->ddhead,ImagePrefix[(int)*p-'0']);
  1234.         else
  1235.         {
  1236.             if (*p == ':')
  1237.                 (void) sprintf(tmpbuf,"%s/%s/%s.gif",
  1238.                     DigitDir,digit_info->ddhead,"colon");
  1239.             else if ((*p == 'A') || (*p == 'a'))
  1240.                 (void) sprintf(tmpbuf,"%s/%s/%s.gif",
  1241.                     DigitDir,digit_info->ddhead,"am");
  1242.             else if ((*p == 'P') || (*p == 'p'))
  1243.                 (void) sprintf(tmpbuf,"%s/%s/%s.gif",
  1244.                     DigitDir,digit_info->ddhead,"pm");
  1245.             else if (*p == ',')
  1246.                 (void) sprintf(tmpbuf,"%s/%s/%s.gif",
  1247.                     DigitDir,digit_info->ddhead,"comma");
  1248.             else
  1249.                 if (*p == '-')
  1250.                 (void) sprintf(tmpbuf,"%s/%s/%s.gif",
  1251.                     DigitDir,digit_info->ddhead,"dash");
  1252.         }
  1253.         rc=GetGIFsize(tmpbuf,&gbW,&gbH);
  1254.         if (rc)
  1255.         {
  1256.             PrintHeader();
  1257.             StringImage("Unable to determine digit image size!");
  1258.             exit(1);
  1259.         }
  1260.         bwidth += gbW;
  1261.         if (gbH > bheight)
  1262.             bheight=gbH;
  1263.     }
  1264. }
  1265. else
  1266. {
  1267.     /*
  1268.     ** strip is in use. First of all, we will determine the with of the
  1269.     ** base image. The segments in the strip may be of varaible widths,
  1270.     ** we'll handle it
  1271.     */
  1272.     (void) sprintf(tmpbuf,"%s/%s/strip.gif",DigitDir,digit_info->ddhead);
  1273.     strip_image=ReadImage(tmpbuf);
  1274.     if (strip_image == (Image *) NULL)
  1275.     {
  1276.         PrintHeader();
  1277.         StringImage("Unable to read strip image!");
  1278.         exit(1);
  1279.     }
  1280.     if (strip_image->comments != (char *) NULL)
  1281.     {
  1282.         rc=sscanf(strip_image->comments,"%d",&nsegment);
  1283.         Debug2("segments=%d rc=%d",nsegment,rc);
  1284.         if (rc != 1)
  1285.         {
  1286.             PrintHeader();
  1287.             StringImage("No string segment info found in GIF comment ext.!");
  1288.             exit(1);
  1289.         }
  1290.  
  1291.         seg_array=(int *) malloc((nsegment+2)*sizeof(int));
  1292.         if (seg_array == (int *) NULL)
  1293.         {
  1294.             PrintHeader();
  1295.             StringImage("Memory Allocation Failed for seg_array!");
  1296.             exit(1);   
  1297.         }
  1298.         p=strip_image->comments;
  1299.         i=0;
  1300.         while ((token=mystrtok(p,":")) != (char *) NULL)
  1301.         {
  1302.             p=(char *) NULL;
  1303.             if (token != (char *) NULL)
  1304.                 seg_array[i]=atoi(token);
  1305.             i++;
  1306.         }
  1307.         /*
  1308.         ** the info about strip in the comment extension of the GIF image
  1309.         ** does not match. we'll abort
  1310.         ** btw, if the strip is created with my mkstrip program, the info
  1311.         ** should be correct. possibly someone is using a strip made by
  1312.         ** some other program. Tough luck!
  1313.         */
  1314.         if (i != (nsegment+2))
  1315.         {
  1316.             PrintHeader();
  1317.             StringImage("Strip info mismatch in GIF comment ext.!");
  1318.             exit(1);
  1319.         }
  1320.  
  1321.         for (p=digitbuf; *p != '\0'; p++)
  1322.         {
  1323.             if (isdigit(*p))
  1324.             {
  1325.                 n=(*p-'0');
  1326.                 bwidth += (seg_array[n+2]-seg_array[n+1]);
  1327.             }
  1328.             else
  1329.             {
  1330.                 if (*p == ':')
  1331.                 {
  1332.                     rinfo.x=seg_array[11];
  1333.                     bwidth += (seg_array[12]-seg_array[11]);
  1334.                 }
  1335.  
  1336.                 if ((*p == 'A') || (*p == 'a'))
  1337.                 {
  1338.                     rinfo.x=seg_array[12];
  1339.                     bwidth += (seg_array[13]-seg_array[12]);
  1340.                 }
  1341.                 if ((*p == 'P') || (*p == 'p'))
  1342.                 {
  1343.                     rinfo.x=seg_array[13];
  1344.                     bwidth += (seg_array[14]-seg_array[13]);
  1345.                 }
  1346.                 if (*p == ',')
  1347.                 {
  1348.                     rinfo.x=seg_array[14];
  1349.                     bwidth += (seg_array[15]-seg_array[14]);
  1350.                 }
  1351.                 if (*p == '-')
  1352.                 {
  1353.                     rinfo.x=seg_array[15];
  1354.                     bwidth += (seg_array[16]-seg_array[15]);
  1355.                 }
  1356.             }
  1357.         }
  1358.         bheight=strip_image->rows;
  1359.     }
  1360.     else
  1361.     {
  1362.         PrintHeader();
  1363.         StringImage("No info about strip found in GIF comment ext.!");
  1364.         exit(1);
  1365.     }
  1366. }
  1367.     base_image= CreateBaseImage (bwidth,bheight,0,0,0,DirectClass);
  1368.  
  1369.     if (base_image == (Image *) NULL)
  1370.     {
  1371.         PrintHeader();
  1372.         StringImage("Unable to create base image!");
  1373.         exit(1);
  1374.     }
  1375.  
  1376. if (digit_info->use_strip == False)
  1377. {
  1378.     for (p=digitbuf; *p != '\0'; p++)
  1379.     {
  1380.         *tmpbuf='\0';
  1381.         if(isdigit(*p))
  1382.             (void) sprintf(tmpbuf,"%s/%s/%s.gif",
  1383.                 DigitDir,digit_info->ddhead,ImagePrefix[(int)*p-'0']);
  1384.         else
  1385.         {
  1386.             if (*p == ':')
  1387.                 (void) sprintf(tmpbuf,"%s/%s/%s.gif",
  1388.                     DigitDir,digit_info->ddhead,"colon");
  1389.             if ((*p == 'A') || (*p == 'a'))
  1390.                 (void) sprintf(tmpbuf,"%s/%s/%s.gif",
  1391.                     DigitDir,digit_info->ddhead,"am");
  1392.             if ((*p == 'P') || (*p == 'p'))
  1393.                 (void) sprintf(tmpbuf,"%s/%s/%s.gif",
  1394.                     DigitDir,digit_info->ddhead,"pm");
  1395.             if (*p == ',')
  1396.                 (void) sprintf(tmpbuf,"%s/%s/%s.gif",
  1397.                     DigitDir,digit_info->ddhead,"comma");
  1398.             if (*p == '-')
  1399.                 (void) sprintf(tmpbuf,"%s/%s/%s.gif",
  1400.                     DigitDir,digit_info->ddhead,"dash");
  1401.         }
  1402.  
  1403.         sub_image=ReadImage(tmpbuf);
  1404.         if (sub_image != (Image *) NULL)
  1405.         {
  1406.             FlattenImage(base_image,sub_image,ReplaceCompositeOp,
  1407.                 base_width,0);
  1408.             base_width += sub_image->columns;
  1409.             DestroyAnyImageStruct(&sub_image);
  1410.         }
  1411.         else
  1412.         {
  1413.             PrintHeader();
  1414.             StringImage(" FAILED to combine digit images!");
  1415.             exit(1);
  1416.         }
  1417.     }
  1418. }
  1419. else
  1420. {
  1421.    rinfo.y=0;
  1422.    rinfo.width=15;
  1423.    rinfo.height=strip_image->rows;
  1424.     for (p=digitbuf; *p != '\0'; p++)
  1425.     {
  1426.         *tmpbuf='\0';
  1427.         if (isdigit(*p))
  1428.         {
  1429.             n=(*p-'0');
  1430.             rinfo.x=seg_array[n+1];
  1431.             rinfo.width=seg_array[n+2]-seg_array[n+1];
  1432.         }
  1433.         else
  1434.         {
  1435.             if (*p == ':')
  1436.             {
  1437.                 rinfo.x=seg_array[11];
  1438.                 rinfo.width=seg_array[12]-seg_array[11];
  1439.             }
  1440.             if ((*p == 'A') || (*p == 'a'))
  1441.             {
  1442.                 rinfo.x=seg_array[12];
  1443.                 rinfo.width=seg_array[13]-seg_array[12];
  1444.             }
  1445.             if ((*p == 'P') || (*p == 'p'))
  1446.             {
  1447.                 rinfo.x=seg_array[13];
  1448.                 rinfo.width=seg_array[14]-seg_array[13];
  1449.             }
  1450.             if (*p == ',')
  1451.             {
  1452.                 rinfo.x=seg_array[14];
  1453.                 rinfo.width=seg_array[15]-seg_array[14];
  1454.             }
  1455.             if (*p == '-')    
  1456.             {
  1457.                 rinfo.x=seg_array[15];
  1458.                 rinfo.width=seg_array[16]-seg_array[15];
  1459.             }    
  1460.         }
  1461.  
  1462.         sub_image=CropImage(strip_image,&rinfo);
  1463.         if (sub_image != (Image *) NULL)
  1464.         {
  1465.             FlattenImage(base_image,sub_image,ReplaceCompositeOp, base_width,0);
  1466.             base_width += sub_image->columns;
  1467.             DestroyAnyImageStruct(&sub_image); 
  1468.         }
  1469.         else
  1470.         {
  1471.             PrintHeader();
  1472.             StringImage("Failed to extract image from strip!");
  1473.             exit(1);
  1474.         }    
  1475.     } 
  1476. }
  1477.     return(base_image);
  1478. }
  1479.  
  1480. /*
  1481. ** buf is modified
  1482. */
  1483. void Commaize(buf)
  1484. char
  1485.     *buf;
  1486. {
  1487.     char
  1488.         tmpbuf[100];
  1489.  
  1490.     register char
  1491.         *p,
  1492.         *q;
  1493.  
  1494.     int
  1495.         m=0;
  1496.     int
  1497.         i=-1;
  1498.  
  1499.     *tmpbuf='\0';
  1500.  
  1501.     if (*buf != '\0')
  1502.     {
  1503.         m=0;
  1504.         m=m+strlen(buf)/3;
  1505.         if (strlen(buf)%3 == 0)
  1506.             m--;
  1507.  
  1508.         p=buf+strlen(buf)-1;
  1509.         tmpbuf[strlen(buf)+m]='\0';
  1510.         q=tmpbuf+strlen(buf)+m-1;
  1511.         while (1)
  1512.         {
  1513.             if (p < buf)
  1514.                 break;
  1515.             if (++i == 3)
  1516.                 i=0, *q-- = ',';
  1517.              *q-- = *p--;
  1518.         }
  1519.         (void) strcpy(buf,tmpbuf);
  1520.     }
  1521.  
  1522. }
  1523.  
  1524. /*
  1525. ** mogrify image if needed
  1526. */
  1527. void MogrifyImage(image,digit_info,frame_info)
  1528. Image
  1529.     **image;
  1530. DigitInfo
  1531.     *digit_info;
  1532. FrameInfo
  1533.     *frame_info;
  1534. {
  1535.     Image
  1536.         *framed_image,
  1537.         *rotated_image;
  1538.  
  1539.     if (*image != (Image *) NULL)
  1540.     {
  1541.         if (digit_info->negate == True)
  1542.             NegateImage(*image);
  1543.             
  1544.         if (digit_info->Frame == True) 
  1545.         {
  1546.             RGB 
  1547.                color,
  1548.                matte_color;
  1549.             
  1550.             matte_color.red=frame_info->matte_color.red;
  1551.             matte_color.green=frame_info->matte_color.green;
  1552.             matte_color.blue=frame_info->matte_color.blue;
  1553.  
  1554.             frame_info->height=frame_info->width;
  1555.             frame_info->outer_bevel=(frame_info->width >> 2)+1;
  1556.             frame_info->inner_bevel=frame_info->outer_bevel;
  1557.             frame_info->x=frame_info->width;
  1558.             frame_info->y=frame_info->height;
  1559.             frame_info->width=(*image)->columns+(frame_info->width << 1);
  1560.             frame_info->height=(*image)->rows+(frame_info->height << 1);
  1561.             frame_info->matte_color=matte_color; 
  1562.         
  1563.             XModulate(&color,matte_color.red,matte_color.green,
  1564.                 matte_color.blue, HighlightModulate);
  1565.             frame_info->highlight_color.red=color.red;
  1566.             frame_info->highlight_color.green=color.green;
  1567.             frame_info->highlight_color.blue=color.blue;
  1568.  
  1569.             XModulate(&color,matte_color.red,matte_color.green,
  1570.                 matte_color.blue, ShadowModulate);
  1571.             frame_info->shadow_color.red=color.red;
  1572.             frame_info->shadow_color.green=color.green;
  1573.             frame_info->shadow_color.green=color.green;
  1574.  
  1575.             framed_image=FrameImage(*image,frame_info);
  1576.             if (framed_image != (Image *) NULL)
  1577.             {
  1578.                 DestroyAnyImageStruct (image);
  1579.                 framed_image->class=DirectClass;
  1580.                 *image=framed_image;
  1581.             }
  1582.         }    
  1583.         
  1584.         (*image)->comments = (char *) malloc (1024*sizeof(char));
  1585.         if ((*image)->comments != (char *) NULL)
  1586.         {
  1587.             (void) sprintf((*image)->comments,"\n%s %s \n%s %s\n%s %s\n",
  1588.                 "Count.cgi", Version, "By", Author, "URL:", Url);
  1589.         }
  1590.         
  1591.  
  1592.         if (digit_info->replace_color == True)
  1593.         {
  1594.             OpaqueImage(*image,
  1595.                 digit_info->opaque_red,
  1596.                 digit_info->opaque_green,
  1597.                 digit_info->opaque_blue,
  1598.                 digit_info->pen_red,
  1599.                 digit_info->pen_green,
  1600.                 digit_info->pen_blue);
  1601.  
  1602.         }
  1603.  
  1604.         if (digit_info->alpha == True)
  1605.         {
  1606.              AlphaImage(*image,digit_info->alpha_red,digit_info->alpha_green,
  1607.                 digit_info->alpha_blue);
  1608.         }
  1609.          if (digit_info->rotate == True)
  1610.          {
  1611.             rotated_image=RotateImage(*image,digit_info->rotate_degrees);
  1612.             if (rotated_image != (Image *) NULL)
  1613.             {
  1614.                 DestroyAnyImageStruct (image);
  1615.                 *image=rotated_image;
  1616.             }
  1617.             else
  1618.             {
  1619.                 (void) fprintf (stderr," Could not rotate %d degrees\n",
  1620.                     digit_info->rotate_degrees);
  1621.             }
  1622.          }
  1623.     }
  1624. }
  1625.