iwebreprt.c
资源名称:ilib [点击查看]
上传用户:changbiao
上传日期:2007-01-13
资源大小:141k
文件大小:32k
源码类别:

图片显示

开发平台:

C/C++

  1. /*
  2.   Report generator for WWW access.log file
  3.   Usage:
  4.     httpgraph [options] [-tod|-dom|-dow|-moy] accesslogfile [accesslogfile ...]
  5.     Default action is to generate a day of the month usage graph to stdout.
  6.     -tod Display a time of day report indicating what
  7. hours of the day get the most usage.
  8. [THIS IS THE DEFAULT]
  9.     -dom Display a day of month report indicating what
  10. days of the month get the most usage.
  11.     -dow Display a day of week report indicating what
  12. days of the week get the most usage.
  13.     -moy Displays month report indicating usage by month
  14.     options what it does
  15.     ---------------- ------------------------------------------------
  16.     -all Use all data [default]
  17.     -today Use data from today only
  18.     -yesterday Use data from yesterday only
  19.     -lastweek Use data from the Mon-Sun week prior to this one
  20.     -thisweek Use data for this Mon-Sun week
  21.     -thismonth Use data for the the current month
  22.     -lastmonth Use data for the month prior to this one
  23.     -bar Use a bar graph instead of a line graph.
  24.     -line Use line graph [default]
  25.     -nohdr Do not display title and summary at bottom
  26.   21-Sep-94 Craig Knudsen cknudsen@radix.net
  27. Created
  28.   29-May-96 Craig Knudsen cknudsen@radix.net
  29.   29-May-96 Craig Knudsen cknudsen@radix.net
  30. Converted from gd library to Ilib.
  31. ***************************************************************************/
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <time.h>
  36. #include <ctype.h>
  37. #include <math.h>
  38. #include <values.h>
  39. #include <sys/types.h>
  40. #include <sys/time.h>
  41. #include <Ilib.h>
  42. #include "helvB18.h"
  43. #include "courR10.h"
  44. #ifndef min
  45. #define min(a,b) ( (a) < (b) ? (a) : (b) )
  46. #define max(a,b) ( (a) > (b) ? (a) : (b) )
  47. #endif
  48. #ifndef TRUE
  49. #define TRUE 1
  50. #define FALSE 0
  51. #endif
  52. static void read_file (
  53. #ifndef _NO_PROTO
  54.   char *filename
  55. #endif
  56. );
  57. static void add_time (
  58. #ifndef _NO_PROTO
  59.   char *text
  60. #endif
  61. );
  62. static int is_in_time_range (
  63. #ifndef _NO_PROTO
  64.   char *text
  65. #endif
  66. );
  67. static void set_times_today ();
  68. static void set_times_yesterday ();
  69. static void set_times_last_week ();
  70. static void set_times_this_week ();
  71. static void set_times_this_month ();
  72. static void set_times_last_month ();
  73. static void generate_gif ();
  74. static int calc_max (
  75. #ifndef _NO_PROTO
  76.   int cur_max
  77. #endif
  78. );
  79. /*
  80. ** Define start and stop times.  Use YYMMDDHHMMSS so that we can just
  81. ** use strcmp() to compare times.
  82. */
  83. static char start_time[20]; /* in YYMMDDHHMMSS format */
  84. static char stop_time[20]; /* in YYMMDDHHMMSS format */
  85. static char pretty_start[30]; /* in human readable format */
  86. static char pretty_stop[30]; /* in human readable format */
  87. static char *months[] = {
  88.   "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  89.   "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
  90. };
  91. static char *wdays[] = {
  92.   "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
  93. };
  94. static int days_in_month[] =
  95.   { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  96. static int days_in_lmonth[] =
  97.   { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  98. static int tod[24]; /* count by time of day */
  99. static int dow[7]; /* couny by day of week */
  100. static int dom[31]; /* count by day of month */
  101. static int moy[12]; /* count by month */
  102. #define SUNDAY 0
  103. #define MONDAY 1
  104. #define TUESDAY 2
  105. #define WEDNESDAY 3
  106. #define THURSDAY 4
  107. #define FRIDAY 5
  108. #define SATURDAY 6
  109. static int total = 0; /* total number of requests counted */
  110. typedef enum {
  111.   DAY_OF_MONTH,
  112.   DAY_OF_WEEK,
  113.   TIME_OF_DAY,
  114.   MONTH_OF_YEAR
  115. } OutputType;
  116. typedef enum {
  117.   BAR,
  118.   LINE
  119. } GraphType;
  120. static OutputType output_type = DAY_OF_MONTH;
  121. static GraphType graph_type = LINE;
  122. static int display_header = TRUE;
  123. static int line_width = 2; /* for line graphs (can use 1-3) */
  124. /* String to use in place of "Retrievals" */
  125. static char *retrievals = "Retrievals";
  126. /*
  127. ** Main
  128. */
  129. int main ( argc, argv )
  130. int argc;
  131. char *argv[];
  132. {
  133.   int loop;
  134.   /* default is to use all data */
  135.   start_time[0] = stop_time[0] = '';
  136.   for ( loop = 0; loop < 24; loop++ )
  137.     tod[loop] = 0;
  138.   for ( loop = 0; loop < 7; loop++ )
  139.     dow[loop] = 0;
  140.   for ( loop = 0; loop < 31; loop++ )
  141.     dom[loop] = 0;
  142.   for ( loop = 0; loop < 12; loop++ )
  143.     moy[loop] = 0;
  144.   /* process command line arguments */
  145.   for ( loop = 1; loop < argc; loop++ ) {
  146.     if ( strcmp ( argv[loop], "-bar" ) == 0 )
  147.       graph_type = BAR;
  148.     else if ( strcmp ( argv[loop], "-line" ) == 0 )
  149.       graph_type = LINE;
  150.     else if ( strcmp ( argv[loop], "-tod" ) == 0 )
  151.       output_type = TIME_OF_DAY;
  152.     else if ( strcmp ( argv[loop], "-dom" ) == 0 )
  153.       output_type = DAY_OF_MONTH;
  154.     else if ( strcmp ( argv[loop], "-dow" ) == 0 )
  155.       output_type = DAY_OF_WEEK;
  156.     else if ( strcmp ( argv[loop], "-moy" ) == 0 )
  157.       output_type = MONTH_OF_YEAR;
  158.     else if ( strcmp ( argv[loop], "-today" ) == 0 )
  159.       set_times_today ();
  160.     else if ( strcmp ( argv[loop], "-yesterday" ) == 0 )
  161.       set_times_yesterday ();
  162.     else if ( strcmp ( argv[loop], "-lastweek" ) == 0 )
  163.       set_times_last_week ();
  164.     else if ( strcmp ( argv[loop], "-thisweek" ) == 0 )
  165.       set_times_this_week ();
  166.     else if ( strcmp ( argv[loop], "-thismonth" ) == 0 )
  167.       set_times_this_month ();
  168.     else if ( strcmp ( argv[loop], "-lastmonth" ) == 0 )
  169.       set_times_last_month ();
  170.     else if ( strcmp ( argv[loop], "-noheader" ) == 0 ||
  171.       strcmp ( argv[loop], "-nohdr" ) == 0 )
  172.       display_header = FALSE;
  173.     else if ( strcmp ( argv[loop], "-rstring" ) == 0 ) {
  174.       if ( argv[++loop] == NULL ) {
  175.         fprintf ( stderr, "%s : -rstring requires another parametern",
  176.           argv[0] );
  177.         exit ( 1 );
  178.       }
  179.       retrievals = argv[loop];
  180.     }
  181.     else if ( *argv[loop] == '-' ) {
  182.       fprintf ( stderr, "%s: unrecognized argument "%s"n",
  183.         argv[0], argv[loop] );
  184.       exit ( 1 );
  185.     }
  186.     else {
  187.       read_file ( argv[loop] );
  188.     }
  189.   }
  190.   /* create output */
  191.   generate_gif ();
  192.   /* exit */
  193.   return ( 0 );
  194. }
  195. /****************************************************************************
  196. *
  197. * Set the time range variables so that we look at data from today only.
  198. *
  199. ****************************************************************************/
  200. static void set_times_today ()
  201. {
  202.   time_t now;
  203.   struct tm *tm;
  204.   time ( &now );
  205.   tm = localtime ( &now );
  206.   sprintf ( start_time, "%02d%02d%02d%02d%02d%02d",
  207.     tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 0, 0, 0 );
  208.   sprintf ( pretty_start, "%s %02d %s %d %02d:%02d:%02d",
  209.     wdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
  210.     0, 0, 0 );
  211.   sprintf ( stop_time, "%02d%02d%02d%02d%02d%02d",
  212.     tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 23, 59, 59 );
  213.   sprintf ( pretty_stop, "%s %02d %s %d %02d:%02d:%02d",
  214.     wdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
  215.     23, 59, 59 );
  216. }
  217. /****************************************************************************
  218. *
  219. * Set the time range variables so that we look at data from yesterday only.
  220. *
  221. ****************************************************************************/
  222. static void set_times_yesterday ()
  223. {
  224.   time_t now, yest;
  225.   struct tm *tm;
  226.   time ( &now );
  227.   yest = now - ( 24 * 3600 );
  228.   tm = localtime ( &yest );
  229.   sprintf ( start_time, "%02d%02d%02d%02d%02d%02d",
  230.     tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 0, 0, 0 );
  231.   sprintf ( pretty_start, "%s %02d %s %d %02d:%02d:%02d",
  232.     wdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
  233.     0, 0, 0 );
  234.   sprintf ( stop_time, "%02d%02d%02d%02d%02d%02d",
  235.     tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 23, 59, 59 );
  236.   sprintf ( pretty_stop, "%s %02d %s %d %02d:%02d:%02d",
  237.     wdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
  238.     23, 59, 59 );
  239. }
  240. /****************************************************************************
  241. *
  242. * Set the time range variables so that we look at data from last week
  243. * where the week starts on Monday and finishes on Sunday.
  244. *
  245. ****************************************************************************/
  246. static void set_times_last_week ()
  247. {
  248.   time_t now, lastweek, lastweekstop;
  249.   struct tm *tm;
  250.   time ( &now );
  251.   tm = localtime ( &now );
  252.   switch ( tm->tm_wday ) {
  253.     case MONDAY:
  254.       lastweek = now - ( 7 * ( 24 * 3600 ) ); break;
  255.     case TUESDAY:
  256.       lastweek = now - ( 8 * ( 24 * 3600 ) ); break;
  257.     case WEDNESDAY:
  258.       lastweek = now - ( 9 * ( 24 * 3600 ) ); break;
  259.     case THURSDAY:
  260.       lastweek = now - ( 10 * ( 24 * 3600 ) ); break;
  261.     case FRIDAY:
  262.       lastweek = now - ( 11 * ( 24 * 3600 ) ); break;
  263.     case SATURDAY:
  264.       lastweek = now - ( 12 * ( 24 * 3600 ) ); break;
  265.     case SUNDAY:
  266.       lastweek = now - ( 13 * ( 24 * 3600 ) ); break;
  267.   }
  268.   tm = localtime ( &lastweek );
  269.   sprintf ( start_time, "%02d%02d%02d%02d%02d%02d",
  270.     tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 0, 0, 0 );
  271.   sprintf ( pretty_start, "%s %02d %s %d %02d:%02d:%02d",
  272.     wdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
  273.     0, 0, 0 );
  274.   lastweekstop = lastweek + ( 7 * 24 * 3600 );
  275.   tm = localtime ( &lastweekstop );
  276.   sprintf ( stop_time, "%02d%02d%02d%02d%02d%02d",
  277.     tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 23, 59, 59 );
  278.   sprintf ( pretty_stop, "%s %02d %s %d %02d:%02d:%02d",
  279.     wdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
  280.     23, 59, 59 );
  281. }
  282. /****************************************************************************
  283. *
  284. * Set the time range variables so that we look at data from this week
  285. * where the week starts on Monday and finishes on Sunday.
  286. *
  287. ****************************************************************************/
  288. static void set_times_this_week ()
  289. {
  290.   time_t now, thisweek, thisweekstop;
  291.   struct tm *tm;
  292.   time ( &now );
  293.   tm = localtime ( &now );
  294.   switch ( tm->tm_wday ) {
  295.     case MONDAY:
  296.       thisweek = now - ( 0 * ( 24 * 3600 ) ); break;
  297.     case TUESDAY:
  298.       thisweek = now - ( 1 * ( 24 * 3600 ) ); break;
  299.     case WEDNESDAY:
  300.       thisweek = now - ( 2 * ( 24 * 3600 ) ); break;
  301.     case THURSDAY:
  302.       thisweek = now - ( 3 * ( 24 * 3600 ) ); break;
  303.     case FRIDAY:
  304.       thisweek = now - ( 4 * ( 24 * 3600 ) ); break;
  305.     case SATURDAY:
  306.       thisweek = now - ( 5 * ( 24 * 3600 ) ); break;
  307.     case SUNDAY:
  308.       thisweek = now - ( 6 * ( 24 * 3600 ) ); break;
  309.   }
  310.   tm = localtime ( &thisweek );
  311.   sprintf ( start_time, "%02d%02d%02d%02d%02d%02d",
  312.     tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 0, 0, 0 );
  313.   sprintf ( pretty_start, "%s %02d %s %d %02d:%02d:%02d",
  314.     wdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
  315.     0, 0, 0 );
  316.   thisweekstop = thisweek + ( 7 * 24 * 3600 );
  317.   tm = localtime ( &thisweekstop );
  318.   sprintf ( stop_time, "%02d%02d%02d%02d%02d%02d",
  319.     tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 23, 59, 59 );
  320.   sprintf ( pretty_stop, "%s %02d %s %d %02d:%02d:%02d",
  321.     wdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
  322.     23, 59, 59 );
  323. }
  324. /****************************************************************************
  325. *
  326. * Set the time range variables so that we look at data from this month only.
  327. *
  328. ****************************************************************************/
  329. static void set_times_this_month ()
  330. {
  331.   time_t now, first, last;
  332.   struct tm *tm;
  333.   /* Figure out the first of the month */
  334.   time ( &now );
  335.   tm = localtime ( &now );
  336.   first = now - ( ( tm->tm_mday - 1 ) * ( 24 * 3600 ) );
  337.   /* start of month */
  338.   tm = localtime ( &first );
  339.   sprintf ( start_time, "%02d%02d%02d%02d%02d%02d",
  340.     tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 0, 0, 0 );
  341.   sprintf ( pretty_start, "%s %02d %s %d %02d:%02d:%02d",
  342.     wdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
  343.     0, 0, 0 );
  344.   /* end of month */
  345.   if ( tm->tm_year % 4 == 0 ) {
  346.     /* leap year */
  347.     last = first + ( ( days_in_lmonth[tm->tm_mon] - 1 ) * 24 * 3600 );
  348.   }
  349.   else {
  350.     last = first + ( ( days_in_month[tm->tm_mon] - 1 ) * 24 * 3600 );
  351.   }
  352.   tm = localtime ( &last );
  353.   sprintf ( stop_time, "%02d%02d%02d%02d%02d%02d",
  354.     tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 23, 59, 59 );
  355.   sprintf ( pretty_stop, "%s %02d %s %d %02d:%02d:%02d",
  356.     wdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
  357.     23, 59, 59 );
  358. }
  359. /****************************************************************************
  360. *
  361. * Set the time range variables so that we look at data from the month
  362. * prior to the current month.
  363. *
  364. ****************************************************************************/
  365. static void set_times_last_month ()
  366. {
  367.   time_t now, first, last;
  368.   struct tm *tm;
  369.   int prev_month;
  370.   /* Figure out the 1st of the current month */
  371.   time ( &now );
  372.   tm = localtime ( &now );
  373.   first = now - ( ( tm->tm_mday - 1 ) * ( 24 * 3600 ) );
  374.   /* move to the 1st of previous month */
  375.   prev_month = tm->tm_mon - 1;
  376.   if ( prev_month < 0 )
  377.     prev_month = 12;
  378.   if ( tm->tm_year % 4 == 0 ) {
  379.     /* leap year */
  380.     first -= days_in_lmonth[prev_month] * 24 * 3600;
  381.   }
  382.   else {
  383.     first -= days_in_month[prev_month] * 24 * 3600;
  384.   }
  385.   /* start */
  386.   tm = localtime ( &first );
  387.   sprintf ( start_time, "%02d%02d%02d%02d%02d%02d",
  388.     tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 0, 0, 0 );
  389.   sprintf ( pretty_start, "%s %02d %s %d %02d:%02d:%02d",
  390.     wdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
  391.     0, 0, 0 );
  392.   /* end of month */
  393.   if ( tm->tm_year % 4 == 0 ) {
  394.     /* leap year */
  395.     last = first + ( ( days_in_lmonth[tm->tm_mon] - 1 ) * 24 * 3600 );
  396.   }
  397.   else {
  398.     last = first + ( ( days_in_month[tm->tm_mon] - 1 ) * 24 * 3600 );
  399.   }
  400.   tm = localtime ( &last );
  401.   sprintf ( stop_time, "%02d%02d%02d%02d%02d%02d",
  402.     tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 23, 59, 59 );
  403.   sprintf ( pretty_stop, "%s %02d %s %d %02d:%02d:%02d",
  404.     wdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
  405.     23, 59, 59 );
  406. }
  407. /****************************************************************************
  408. *
  409. * Read in the data file
  410. *
  411. ****************************************************************************/
  412. static void read_file ( filename )
  413. char *filename;
  414. {
  415.   FILE *fp;
  416.   char text[10240];
  417.   fp = fopen ( filename, "r" );
  418.   if ( ! fp ) {
  419.     fprintf ( stderr, "Unable to open log file %sn", filename );
  420.     return;
  421.   }
  422.   while ( fgets ( text, 10240, fp ) ) {
  423.     if ( is_in_time_range ( text ) ) {
  424.       /* get hour of day, day of week, and day of month */
  425.       add_time ( text );
  426.       total++;
  427.     }
  428.   }
  429.   fclose ( fp );
  430. }
  431. /*
  432. ** Add the time information so we can report time of day, day of month.
  433. */
  434. static void add_time ( text )
  435. char *text;
  436. {
  437.   char *ptr;
  438.   char temp[10];
  439.   int int1, loop, month, year, day, hour, weekday, y, m, d;
  440.   static int dlook[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };
  441.   temp[2] = '';
  442.   /* first get the day of month */
  443.   ptr = strstr ( text, "[" );
  444.   day = -1;
  445.   if ( ! ptr ) {
  446.     /* very unexpected.  (but expect the unexpected, right?) */
  447.     return;
  448.   }
  449.   strncpy ( temp, ptr + 1, 2 );
  450.   if ( isdigit ( temp[0] ) && isdigit ( temp[1] ) ) {
  451.     int1 = atoi ( temp );
  452.     if ( int1 >= 1 && int1 <= 31 )
  453.       day = int1 -1;
  454.   }
  455.   if ( day < 0 )
  456.     return;
  457.   /* now get the month */
  458.   temp[3] = '';
  459.   month = -1;
  460.   strncpy ( temp, ptr + 4, 3 );
  461.   for ( loop = 0; loop < 12; loop++ ) {
  462.     if ( strcmp ( months[loop], temp ) == 0 ) {
  463.       month = loop; /* remember: Jan=0 */
  464.       break;
  465.     }
  466.   }
  467.   if ( month < 0 )
  468.     return;
  469.   /* now get the year */
  470.   temp[4] = '';
  471.   year = -1;
  472.   strncpy ( temp, ptr + 8, 4 );
  473.   if ( isdigit ( temp[0] ) && isdigit ( temp[1] ) &&
  474.     isdigit ( temp[2] ) && isdigit ( temp[3] ) ) {
  475.     int1 = atoi ( temp );
  476.     if ( int1 >= 1900 && int1 <= 9999 )
  477.       year = int1;
  478.   }
  479.   if ( year < 0 )
  480.     return;
  481.   /* now get the hour of day */
  482.   temp[2] = '';
  483.   strncpy ( temp, ptr + 13, 2 );
  484.   if ( isdigit ( temp[0] ) && isdigit ( temp[1] ) ) {
  485.     int1 = atoi ( temp );
  486.     if ( int1 >= 0 && int1 <= 23 )
  487.       hour = int1;
  488.   }
  489.   if ( hour < 0 )
  490.     return;
  491.   /* determine day of week from a nifty algorithm */
  492.   m = month + 1;
  493.   y = year;
  494.   d = day + 1;
  495.   if ( m < 3 )
  496.     y--;
  497.   weekday = ( y + ( y/4 ) - ( y/100 ) + ( y/400 ) + dlook[m-1] + d ) % 7;
  498. /*
  499.   fprintf ( stderr, "%sdow=%stmonth=%stdom=%dttod=%dn",
  500.     text, wdays[weekday], months[month], day + 1, hour );
  501. */
  502.   dow[weekday]++;
  503.   tod[hour]++;
  504.   moy[month]++;
  505.   dom[day]++;
  506. }
  507. /****************************************************************************
  508. *
  509. * Generate the output image
  510. *
  511. ****************************************************************************/
  512. #define LEFT_PAD 80
  513. #define TOP_PAD 50
  514. #define RIGHT_PAD 50
  515. #define BOTTOM_PAD 55
  516. #define DATA_WIDTH 15
  517. #define DATA_HEIGHT 200
  518. static void generate_gif ()
  519. {
  520.   int loop;
  521.   char temp[200];
  522.   int maxval;
  523.   int lastday;
  524.   int x, y, lastx, lasty;
  525.   IImage im_out; /* output image */
  526.   IFont helvB18, courR10;
  527.   IColor red, blue, black, grey;
  528.   IGC gc;
  529.   int height, width;
  530.   /*
  531.   ** Display day of month data
  532.   */
  533.   if ( output_type == DAY_OF_MONTH ) {
  534.     /* get max value and last day we have data for */
  535.     for ( maxval = 0, loop = 0; loop < 31; loop++ ) {
  536.       maxval = max ( maxval, dom[loop] );
  537.       if ( dom[loop] )
  538.         lastday = loop;
  539.     }
  540.     maxval = calc_max ( maxval );
  541.     /* Create graph output */
  542.     width = LEFT_PAD + ( ( lastday + 1 ) * DATA_WIDTH ) + RIGHT_PAD;
  543.     width = max ( width, 500 );
  544.     height = TOP_PAD + DATA_HEIGHT + BOTTOM_PAD;
  545.   }
  546.   else if ( output_type == TIME_OF_DAY ) {
  547.     /* get max value */
  548.     for ( maxval = 0, loop = 0; loop < 24; loop++ ) {
  549.       maxval = max ( maxval, tod[loop] );
  550.     }
  551.     maxval = calc_max ( maxval );
  552.     /* Create graph output */
  553.     width = LEFT_PAD + ( 24 * DATA_WIDTH ) + RIGHT_PAD;
  554.     height = TOP_PAD + DATA_HEIGHT + BOTTOM_PAD;
  555.   }
  556.   else if ( output_type == DAY_OF_WEEK ) {
  557.     /* get max value */
  558.     for ( maxval = 0, loop = 0; loop < 7; loop++ ) {
  559.       maxval = max ( maxval, dow[loop] );
  560.     }
  561.     maxval = calc_max ( maxval );
  562.     /* Create graph output */
  563.     width = LEFT_PAD + ( 7 * DATA_WIDTH * 3 ) + RIGHT_PAD;
  564.     height = TOP_PAD + DATA_HEIGHT + BOTTOM_PAD;
  565.   }
  566.   else if ( output_type == MONTH_OF_YEAR ) {
  567.     /* get max value */
  568.     for ( maxval = 0, loop = 0; loop < 12; loop++ ) {
  569.       maxval = max ( maxval, moy[loop] );
  570.     }
  571.     maxval = calc_max ( maxval );
  572.     /* Create graph output */
  573.     width = LEFT_PAD + ( 24 * DATA_WIDTH ) + RIGHT_PAD;
  574.     width = max ( width, 500 );
  575.     height = TOP_PAD + DATA_HEIGHT + BOTTOM_PAD;
  576.   }
  577.   /* allocate image */
  578.   im_out = ICreateImage ( width, height, IOPTION_NONE );
  579.   /* first color is background color */
  580.   black = IAllocColor ( 0, 0, 0 );
  581.   grey = IAllocColor ( 192, 192, 192 );
  582.   ISetTransparent ( im_out, grey );
  583.   red = IAllocColor ( 255, 0, 0 );
  584.   blue = IAllocColor ( 0, 0, 255 );
  585.   gc = ICreateGC ();
  586.   ISetForeground ( gc, grey );
  587.   IFillRectangle ( im_out, gc, 0, 0, width, height );
  588.   /* draw black border */
  589.   ISetForeground ( gc, black );
  590.   IDrawRectangle ( im_out, gc, 0, 0, width - 1, height - 1 );
  591.   /* draw title */
  592.   if ( display_header ) {
  593.     sprintf ( temp, "WebReport 1.0" );
  594.   }
  595.   ILoadFontFromData ( "courR10", courR10_font, &courR10 );
  596.   ILoadFontFromData ( "helvB18", helvB18_font, &helvB18 );
  597.   
  598.   /* Draw title */
  599.   ISetFont ( gc, helvB18 );
  600.   ISetForeground ( gc, grey );
  601.   IDrawString ( im_out, gc, LEFT_PAD + 81, 31, temp, strlen ( temp ) );
  602.   ISetForeground ( gc, black );
  603.   IDrawString ( im_out, gc, LEFT_PAD + 80, 30, temp, strlen ( temp ) );
  604.   /* write "Retrievals" to the left of the y axis */
  605.   ISetFont ( gc, courR10 );
  606.   IDrawString ( im_out, gc, 5, TOP_PAD + DATA_HEIGHT / 2 - 5,
  607.     retrievals, strlen ( retrievals ) );
  608.   /* label the y axis  with the top value */
  609.   sprintf ( temp, "%12d", maxval );
  610.   IDrawString ( im_out, gc, 5, TOP_PAD + 3, temp, strlen ( temp ) );
  611.   ISetForeground ( gc, blue );
  612.   IDrawLine ( im_out, gc, LEFT_PAD - 3, TOP_PAD, LEFT_PAD, TOP_PAD );
  613.   /* draw x and y axis in blue */
  614.   IDrawLine ( im_out, gc, LEFT_PAD, TOP_PAD, LEFT_PAD, TOP_PAD + DATA_HEIGHT );
  615.   if ( graph_type == LINE )
  616.     IDrawLine ( im_out, gc, LEFT_PAD, TOP_PAD + DATA_HEIGHT, width - RIGHT_PAD,
  617.       TOP_PAD + DATA_HEIGHT );
  618.   else
  619.     IDrawLine ( im_out, gc, LEFT_PAD, TOP_PAD + DATA_HEIGHT,
  620.       width - RIGHT_PAD + ( DATA_WIDTH / 2 ),
  621.       TOP_PAD + DATA_HEIGHT );
  622.   /* draw dashed lines horizontally */
  623.   ISetLineStyle ( gc, ILINE_ON_OFF_DASH );
  624.   for ( loop = 0; loop <= 4; loop++ ) {
  625.     y = TOP_PAD + ( ( DATA_HEIGHT / 5 ) * loop );
  626.     if ( graph_type == LINE )
  627.       IDrawLine ( im_out, gc, LEFT_PAD, y, width - RIGHT_PAD, y );
  628.     else
  629.       IDrawLine ( im_out, gc, LEFT_PAD, y,
  630.         width - RIGHT_PAD + ( DATA_WIDTH / 2 ), y );
  631.   }
  632.   ISetLineStyle ( gc, ILINE_SOLID );
  633.   if ( output_type == DAY_OF_MONTH ) {
  634.     /* label this as day of month on x axis */
  635.     ISetForeground ( gc, black );
  636.     IDrawString ( im_out, gc, LEFT_PAD + 80, height - 35,
  637.       "Day of the Month", strlen ( "Day of the Month" ) );
  638.     /* now draw a line for each point */
  639.     lastx = LEFT_PAD + DATA_WIDTH;
  640.     lasty = TOP_PAD + (int)
  641.       ( ( (double)(maxval - dom[0]) / (double)maxval )
  642.        * (double)DATA_HEIGHT );
  643.     if ( graph_type == BAR ) {
  644.       ISetForeground ( gc, red );
  645.       IFillRectangle ( im_out, gc, lastx - ( DATA_WIDTH / 2 ) + 1, lasty,
  646.         DATA_WIDTH - 2, ( TOP_PAD + DATA_HEIGHT ) - lasty );
  647.     }
  648.     /* draw a tic mark */
  649.     ISetForeground ( gc, blue );
  650.     IDrawLine ( im_out, gc, lastx, TOP_PAD + DATA_HEIGHT, lastx, 
  651.       TOP_PAD + DATA_HEIGHT + 3 );
  652.     ISetForeground ( gc, black );
  653.     IDrawString ( im_out, gc, lastx - 2, TOP_PAD + DATA_HEIGHT + 11,
  654.       "1", 1 );
  655.     for ( loop = 1; loop <= lastday; loop++ ) {
  656.       x = LEFT_PAD + ( ( loop + 1 ) * DATA_WIDTH );
  657.       y = TOP_PAD + (int)
  658.         ( ( (double)(maxval - dom[loop]) / (double)maxval )
  659.          * (double)DATA_HEIGHT );
  660.       /* draw the line graph */
  661.       ISetForeground ( gc, red );
  662.       if ( graph_type == LINE ) {
  663.         ISetLineWidth ( gc, line_width );
  664.         IDrawLine ( im_out, gc, lastx, lasty, x, y );
  665.         ISetLineWidth ( gc, 1 );
  666.       }
  667.       else
  668.         IFillRectangle ( im_out, gc, x - ( DATA_WIDTH / 2 ) + 1, y,
  669.           DATA_WIDTH - 2, ( TOP_PAD + DATA_HEIGHT ) - y );
  670.       /* draw a tic mark */
  671.       ISetForeground ( gc, blue );
  672.       IDrawLine ( im_out, gc, x, TOP_PAD + DATA_HEIGHT, x, 
  673.         TOP_PAD + DATA_HEIGHT + 3 );
  674.       /* label the x axis */
  675.       ISetForeground ( gc, black );
  676.       sprintf ( temp, "%d", loop + 1 );
  677.       if ( loop < 9 )
  678.         IDrawString ( im_out, gc, x - 2, TOP_PAD + DATA_HEIGHT + 11,
  679.           temp, strlen ( temp ) );
  680.       else
  681.         IDrawString ( im_out, gc, x - 5, TOP_PAD + DATA_HEIGHT + 11,
  682.           temp, strlen ( temp ) );
  683.       /* save x and y for the next point */
  684.       lastx = x;
  685.       lasty = y;
  686.     }
  687.   }
  688.   else if ( output_type == TIME_OF_DAY ) {
  689.     /* label this as time of day on x axis */
  690.     ISetForeground ( gc, black );
  691.     IDrawString ( im_out, gc, LEFT_PAD + 80, height - 35,
  692.       "Hour of the Day", strlen ( "Hour of the Day" ) );
  693.     /* now draw a line for each point */
  694.     lastx = LEFT_PAD + DATA_WIDTH;
  695.     lasty = TOP_PAD + (int)
  696.       ( ( (double)(maxval - tod[0]) / (double)maxval )
  697.        * (double)DATA_HEIGHT );
  698.     if ( graph_type == BAR ) {
  699.       ISetForeground ( gc, red );
  700.       IFillRectangle ( im_out, gc, lastx - ( DATA_WIDTH / 2 ) + 1, lasty,
  701.         DATA_WIDTH - 2, ( TOP_PAD + DATA_HEIGHT ) - lasty );
  702.     }
  703.     /* draw a tic mark */
  704.     ISetForeground ( gc, blue );
  705.     IDrawLine ( im_out, gc, lastx, TOP_PAD + DATA_HEIGHT, lastx, 
  706.       TOP_PAD + DATA_HEIGHT + 3 );
  707.     ISetForeground ( gc, black );
  708.     IDrawString ( im_out, gc, lastx - 2, TOP_PAD + DATA_HEIGHT + 11,
  709.       "1", 1 );
  710.     for ( loop = 1; loop < 24; loop++ ) {
  711.       x = LEFT_PAD + ( ( loop + 1 ) * DATA_WIDTH );
  712.       y = TOP_PAD + (int)
  713.         ( ( (double)(maxval - tod[loop]) / (double)maxval )
  714.          * (double)DATA_HEIGHT );
  715.       /* draw the line graph */
  716.       ISetForeground ( gc, red );
  717.       if ( graph_type == LINE ) {
  718.         ISetLineWidth ( gc, line_width );
  719.         IDrawLine ( im_out, gc, lastx, lasty, x, y );
  720.         ISetLineWidth ( gc, 1 );
  721.       }
  722.       else
  723.         IFillRectangle ( im_out, gc, x - ( DATA_WIDTH / 2 ) + 1, y,
  724.           DATA_WIDTH - 2, ( TOP_PAD + DATA_HEIGHT ) - y );
  725.       /* draw a tic mark */
  726.       ISetForeground ( gc, blue );
  727.       IDrawLine ( im_out, gc, x, TOP_PAD + DATA_HEIGHT, x, 
  728.         TOP_PAD + DATA_HEIGHT + 3 );
  729.       /* label the x axis */
  730.       sprintf ( temp, "%d", loop + 1 );
  731.       ISetForeground ( gc, black );
  732.       if ( loop < 9 )
  733.         IDrawString ( im_out, gc, x - 2, TOP_PAD + DATA_HEIGHT + 11,
  734.           temp, strlen ( temp ) );
  735.       else
  736.         IDrawString ( im_out, gc, x - 5, TOP_PAD + DATA_HEIGHT + 11,
  737.           temp, strlen ( temp ) );
  738.       /* save x and y for the next point */
  739.       lastx = x;
  740.       lasty = y;
  741.     }
  742.   }
  743.   else if ( output_type == DAY_OF_WEEK ) {
  744.     /* label this as time of day on x axis */
  745.     ISetForeground ( gc, black );
  746.     IDrawString ( im_out, gc, LEFT_PAD + 80, height - 35,
  747.       "Day of Week", strlen ( "Day of Week" ) );
  748.     /* now draw a line for each point */
  749.     lastx = LEFT_PAD + DATA_WIDTH * 3;
  750.     lasty = TOP_PAD + (int)
  751.       ( ( (double)(maxval - tod[0]) / (double)maxval )
  752.        * (double)DATA_HEIGHT );
  753.     if ( graph_type == BAR ) {
  754.       ISetForeground ( gc, red );
  755.       IFillRectangle ( im_out, gc, lastx - ( DATA_WIDTH / 2 ) + 1, lasty,
  756.         DATA_WIDTH - 2, ( TOP_PAD + DATA_HEIGHT ) - lasty );
  757.     }
  758.     /* draw a tic mark */
  759.     ISetForeground ( gc, blue );
  760.     IDrawLine ( im_out, gc, lastx, TOP_PAD + DATA_HEIGHT, lastx, 
  761.       TOP_PAD + DATA_HEIGHT + 3 );
  762.     ISetForeground ( gc, black );
  763.     IDrawString ( im_out, gc, lastx - 2, TOP_PAD + DATA_HEIGHT + 11,
  764.       "Sun", 3 );
  765.     for ( loop = 1; loop < 7; loop++ ) {
  766.       x = LEFT_PAD + ( ( loop + 1 ) * DATA_WIDTH  * 3 );
  767.       y = TOP_PAD + (int)
  768.         ( ( (double)(maxval - dow[loop]) / (double)maxval )
  769.          * (double)DATA_HEIGHT );
  770.       /* draw the line graph */
  771.       ISetForeground ( gc, red );
  772.       if ( graph_type == LINE ) {
  773.         ISetLineWidth ( gc, line_width );
  774.         IDrawLine ( im_out, gc, lastx, lasty, x, y );
  775.         ISetLineWidth ( gc, 1 );
  776.       }
  777.       else
  778.         IFillRectangle ( im_out, gc, x - ( DATA_WIDTH / 2 ) + 1, y,
  779.           DATA_WIDTH - 2, ( TOP_PAD + DATA_HEIGHT ) - y );
  780.       /* draw a tic mark */
  781.       ISetForeground ( gc, blue );
  782.       IDrawLine ( im_out, gc, x, TOP_PAD + DATA_HEIGHT, x, 
  783.         TOP_PAD + DATA_HEIGHT + 3 );
  784.       /* label the x axis */
  785.       sprintf ( temp, "%s", wdays[loop] );
  786.       ISetForeground ( gc, black );
  787.       if ( loop < 9 )
  788.         IDrawString ( im_out, gc, x - 9, TOP_PAD + DATA_HEIGHT + 11,
  789.           temp, strlen ( temp ) );
  790.       else
  791.         IDrawString ( im_out, gc, x - 12, TOP_PAD + DATA_HEIGHT + 11,
  792.           temp, strlen ( temp ) );
  793.       /* save x and y for the next point */
  794.       lastx = x;
  795.       lasty = y;
  796.     }
  797.   }
  798.   else if ( output_type == MONTH_OF_YEAR ) {
  799.     /* label this as time of day on x axis */
  800.     ISetForeground ( gc, black );
  801.     IDrawString ( im_out, gc, LEFT_PAD + 80, height - 35,
  802.       "Month of Year", strlen ( "Month of Year" ) );
  803.     /* now draw a line for each point */
  804.     lastx = LEFT_PAD + DATA_WIDTH * 2;
  805.     lasty = TOP_PAD + (int)
  806.       ( ( (double)(maxval - moy[0]) / (double)maxval )
  807.        * (double)DATA_HEIGHT );
  808.     if ( graph_type == BAR ) {
  809.       ISetForeground ( gc, red );
  810.       IFillRectangle ( im_out, gc, lastx - ( DATA_WIDTH / 2 ) + 1, lasty,
  811.         DATA_WIDTH - 2, ( TOP_PAD + DATA_HEIGHT ) - lasty );
  812.     }
  813.       /* draw a tic mark */
  814.     ISetForeground ( gc, blue );
  815.     IDrawLine ( im_out, gc, lastx, TOP_PAD + DATA_HEIGHT, lastx, 
  816.       TOP_PAD + DATA_HEIGHT + 3 );
  817.     ISetForeground ( gc, black );
  818.     IDrawString ( im_out, gc, lastx - 2, TOP_PAD + DATA_HEIGHT + 11,
  819.       months[0], strlen ( months[0] ) );
  820.     for ( loop = 1; loop < 12; loop++ ) {
  821.       x = LEFT_PAD + ( ( loop + 1 ) * DATA_WIDTH  * 2 );
  822.       y = TOP_PAD + (int)
  823.         ( ( (double)(maxval - moy[loop]) / (double)maxval )
  824.          * (double)DATA_HEIGHT );
  825.       /* draw the line graph */
  826.       ISetForeground ( gc, red );
  827.       if ( graph_type == LINE ) {
  828.         ISetLineWidth ( gc, line_width );
  829.         IDrawLine ( im_out, gc, lastx, lasty, x, y );
  830.         ISetLineWidth ( gc, 1 );
  831.       }
  832.       else
  833.         IFillRectangle ( im_out, gc, x - ( DATA_WIDTH / 2 ) + 1, y,
  834.           DATA_WIDTH - 2, ( TOP_PAD + DATA_HEIGHT ) - y );
  835.       /* draw a tic mark */
  836.       ISetForeground ( gc, blue );
  837.       IDrawLine ( im_out, gc, x, TOP_PAD + DATA_HEIGHT, x, 
  838.         TOP_PAD + DATA_HEIGHT + 3 );
  839.       /* label the x axis */
  840.       sprintf ( temp, "%s", months[loop] );
  841.       ISetForeground ( gc, black );
  842.       if ( loop < 9 )
  843.         IDrawString ( im_out, gc, x - 9, TOP_PAD + DATA_HEIGHT + 11,
  844.           temp, strlen ( temp ) );
  845.       else
  846.         IDrawString ( im_out, gc, x - 12, TOP_PAD + DATA_HEIGHT + 11,
  847.           temp, strlen ( temp ) );
  848.       /* save x and y for the next point */
  849.       lastx = x;
  850.       lasty = y;
  851.     }
  852.   }
  853.   if ( display_header ) {
  854.     sprintf ( temp, "Total retrievals for interval: %d", total );
  855.     ISetForeground ( gc, black );
  856.     IDrawString ( im_out, gc, 5, height - 13, temp, strlen ( temp ) );
  857.     if ( strlen ( start_time ) && ! strlen ( stop_time ) )
  858.       sprintf ( temp, "Time range: after %s", pretty_start );
  859.     else if ( strlen ( stop_time ) && ! strlen ( start_time ) )
  860.       printf ( temp, "Time range: prior to %s", pretty_stop );
  861.     else if ( strlen ( start_time ) && strlen ( stop_time ) )
  862.       sprintf ( temp, "Time range: %s through %s",
  863.       pretty_start, pretty_stop );
  864.     else
  865.       sprintf ( temp, "Time range: all" );
  866.     IDrawString ( im_out, gc, 5, height - 23, temp, strlen ( temp ) );
  867.   }
  868.   /*
  869.   ** make output interlaced
  870.   */
  871.   /*
  872.   ** Write GIF output file.
  873.   */
  874.   IWriteImageFile ( stdout, im_out, IFORMAT_GIF, IOPTION_INTERLACED );
  875.   IFreeImage ( im_out );
  876. }
  877. /****************************************************************************
  878. *
  879. * Calculate a nice round number to use as the maximum for the y axis.
  880. *
  881. ****************************************************************************/
  882. static int calc_max ( cur_max )
  883. int cur_max;  /* the current max value */
  884. {
  885.   int ret_val;
  886.   int next_round, tens, div_val;
  887.   if ( cur_max == 0 )
  888.     return ( 1 );
  889.   tens = (int) log10 ( (double) cur_max );
  890.   next_round = (int) pow ( (double) 10.0, (double) (tens+1) );
  891.   div_val = (int) ( next_round / (int) cur_max );
  892.   switch ( div_val ) {
  893.     case 10:
  894.     case 9:
  895.     case 8:
  896.     case 7:
  897.     case 6:
  898.     case 5:
  899.     next_round /= 5;
  900.       break;
  901.     case 4:
  902.       next_round /= 4;
  903.       break;
  904.     case 3:
  905.       next_round = (int) ( 0.4 * (float) next_round );
  906.       break;
  907.     case 2:
  908.       next_round /= 2;
  909.       break;
  910.     case 1:
  911.     case 0:
  912.       break;
  913.   }
  914.   ret_val = (int) ( max ( 5.0, (float) next_round ) );
  915.   if ( ret_val < cur_max )
  916.     ret_val = cur_max; /* floating point round error */
  917.   return ( ret_val );
  918. }
  919. /****************************************************************************
  920. *
  921. * Check to see if the entry is within our time window
  922. *
  923. ****************************************************************************/
  924. static int is_in_time_range ( entry )
  925. char *entry;
  926. {
  927.   char *ptr;
  928.   int is_after_start, is_before_stop;
  929.   int loop;
  930.   char entry_time[30];
  931.   ptr = strstr ( entry, "[" );
  932.   if ( ! ptr )
  933.     return ( FALSE );
  934.   
  935.   ptr++;
  936.   /* Get year */
  937.   strncpy ( entry_time, ptr + 9, 2 );
  938.   /* Get month */
  939.   for ( loop = 0; loop < 12; loop++ ) {
  940.     if ( strncmp ( months[loop], ptr + 3, 3 ) == 0 ) {
  941.       sprintf ( entry_time + 2, "%02d", loop + 1 );
  942.       break;
  943.     }
  944.   }
  945.   /* Get day */
  946.   strncpy ( entry_time + 4, ptr, 2 );
  947.   /* Get hour */
  948.   strncpy ( entry_time + 6, ptr + 12, 2 );
  949.   /* Get minute */
  950.   strncpy ( entry_time + 8, ptr + 15, 2 );
  951.   /* Get second */
  952.   strncpy ( entry_time + 10, ptr + 18, 2 );
  953.   /* terminate string */
  954.   entry_time[12] = '';
  955.   
  956.   if ( ! strlen ( start_time ) ) {
  957.     is_after_start = TRUE;
  958.   }
  959.   else {
  960.     is_after_start = ( strcmp ( entry_time, start_time ) > 0 );
  961.   }
  962.   
  963.   if ( ! strlen ( stop_time ) ) {
  964.     is_before_stop = TRUE;
  965.   }
  966.   else {
  967.     is_before_stop = ( strcmp ( stop_time, entry_time ) > 0 );
  968.   }
  969.   if ( is_after_start && is_before_stop ) {
  970.     return ( TRUE );
  971.   }
  972.   else
  973.     return ( FALSE );
  974.   
  975. }