2 graphs.c - produces graphs used by the Webalizer
4 Copyright (C) 1997-2011 Bradford L. Barrett
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version, and provided that the above
10 copyright and permission notice is included with all distributed
11 copies of this or derived software.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
27 #include <sys/types.h>
35 /* need socket header? */
36 #ifdef HAVE_SYS_SOCKET_H
37 #include <sys/socket.h>
40 #include "webalizer.h"
45 /* Some systems don't define this */
47 #define PI 3.14159265358979323846
50 #define HITCOLOR hit_or_green /* graph color - hits */
51 #define FILECOLOR file_or_blue /* files */
52 #define SITECOLOR site_or_orange /* sites */
53 #define KBYTECOLOR kbyte_or_red /* KBytes */
54 #define PAGECOLOR page_or_cyan /* Files */
55 #define VISITCOLOR visit_or_yellow /* Visits */
57 /* shortcuts to convert ASCII hex color for gdImageColorAllocate() */
59 #define getred(s) (ashex2int((s[0] == '#')?s+1:s))
60 /* returns the red base-10 integer value from a html color */
62 #define getgreen(s) (ashex2int((s[0] == '#')?s+3:s+2))
63 /* returns the green base-10 integer value from a html color */
65 #define getblue(s) (ashex2int((s[0] == '#')?s+5:s+4))
66 /* returns the blue base-10 integer value from a html color */
68 #define CX 156 /* center x (for pie) */
69 #define CY 150 /* center y (chart) */
70 #define XRAD 240 /* X-axis radius */
71 #define YRAD 200 /* Y-axis radius */
73 /* forward reference internal routines */
75 void init_graph(char *, int, int);
76 struct pie_data
*calc_arc(float, float);
77 int ashex2int(char *);
79 /* common public declarations */
81 char *numchar
[] = { " 0"," 1"," 2"," 3"," 4"," 5"," 6"," 7"," 8"," 9","10",
82 "11","12","13","14","15","16","17","18","19","20",
83 "21","22","23","24","25","26","27","28","29","30","31"};
85 gdImagePtr im
; /* image buffer */
86 FILE *out
; /* output file for PNG */
87 struct stat out_stat
; /* stat struct for PNG */
88 char maxvaltxt
[32]; /* graph values */
89 float percent
; /* percent storage */
90 u_int64_t julday
; /* julday value */
92 struct pie_data
{ int x
; int y
; /* line x,y */
93 int mx
; int my
; }; /* midpoint x,y */
95 int black
, white
, grey
, dkgrey
, kbyte_or_red
,
96 file_or_blue
, site_or_orange
, hit_or_green
,
97 page_or_cyan
, visit_or_yellow
, blue
;
99 /*****************************************************************/
101 /* YEAR_GRAPH6x - Year graph from array of hist_rec structs */
103 /*****************************************************************/
105 int year_graph6x(char *fname
, char *title
, struct hist_rec data
[HISTSIZE
])
108 /* local variables */
116 /* initalize the graph */
117 init_graph(title
,512,256); /* init as 512 x 256 */
119 gdImageLine(im
, 305,25,305,233,black
); /* draw section lines */
120 gdImageLine(im
, 304,25,304,233,white
);
121 gdImageLine(im
, 305,130,490,130,black
);
122 gdImageLine(im
, 305,129,490,129,white
);
127 y1
=210/(graph_lines
+1);
128 for (i
=0;i
<graph_lines
;i
++)
129 gdImageLine(im
,21,((i
+1)*y1
)+25,303,((i
+1)*y1
)+25,dkgrey
);
130 y1
=105/(graph_lines
+1);
131 for (i
=0;i
<graph_lines
;i
++)
132 gdImageLine(im
,306,((i
+1)*y1
)+25,489,((i
+1)*y1
)+25,dkgrey
);
133 for (i
=0;i
<graph_lines
;i
++)
134 gdImageLine(im
,306,((i
+1)*y1
)+130,489,((i
+1)*y1
)+130,dkgrey
);
137 /* color coded legends? */
141 i
= (strlen(msg_h_xfer
)*6);
142 gdImageString(im
,gdFontSmall
,491-i
,237,
143 (unsigned char *)msg_h_xfer
,dkgrey
);
144 gdImageString(im
,gdFontSmall
,490-i
,236,
145 (unsigned char *)msg_h_xfer
,KBYTECOLOR
);
147 /* Sites/Visits Legend */
148 i
= (strlen(msg_h_visits
)*6);
149 j
= (strlen(msg_h_sites
)*6);
150 gdImageString(im
,gdFontSmall
,491-i
-j
-12,11,
151 (unsigned char *)msg_h_visits
,dkgrey
);
152 gdImageString(im
,gdFontSmall
,490-i
-j
-12,10,
153 (unsigned char *)msg_h_visits
,VISITCOLOR
);
154 gdImageString(im
,gdFontSmall
,491-j
-9,11,(unsigned char *)"/",dkgrey
);
155 gdImageString(im
,gdFontSmall
,490-j
-9,10,(unsigned char *)"/",black
);
156 gdImageString(im
,gdFontSmall
,491-j
,11,
157 (unsigned char *)msg_h_sites
,dkgrey
);
158 gdImageString(im
,gdFontSmall
,490-j
,10,
159 (unsigned char *)msg_h_sites
,SITECOLOR
);
161 /* Hits/Files/Pages Legend */
162 i
= (strlen(msg_h_pages
)*6);
163 j
= (strlen(msg_h_files
)*6);
164 gdImageStringUp(im
,gdFontSmall
,6,231,
165 (unsigned char *)msg_h_pages
,dkgrey
);
166 gdImageStringUp(im
,gdFontSmall
,5,230,
167 (unsigned char *)msg_h_pages
,PAGECOLOR
);
168 gdImageStringUp(im
,gdFontSmall
,6,231-i
-3,(unsigned char *)"/",dkgrey
);
169 gdImageStringUp(im
,gdFontSmall
,5,230-i
-3,(unsigned char *)"/",black
);
170 gdImageStringUp(im
,gdFontSmall
,6,231-i
-12,
171 (unsigned char *)msg_h_files
,dkgrey
);
172 gdImageStringUp(im
,gdFontSmall
,5,230-i
-12,
173 (unsigned char *)msg_h_files
,FILECOLOR
);
174 gdImageStringUp(im
,gdFontSmall
,6,231-i
-j
-15,(unsigned char *)"/",dkgrey
);
175 gdImageStringUp(im
,gdFontSmall
,5,230-i
-j
-15,(unsigned char *)"/",black
);
176 gdImageStringUp(im
,gdFontSmall
,6,231-i
-j
-24,
177 (unsigned char *)msg_h_hits
,dkgrey
);
178 gdImageStringUp(im
,gdFontSmall
,5,230-i
-j
-24,
179 (unsigned char *)msg_h_hits
,HITCOLOR
);
182 /* Now draw data areas */
183 s_mth
= HISTSIZE
-graph_mths
;
184 cs
= 280.0/graph_mths
; cw
= cs
/2;
185 co
= (48/graph_mths
<1)?1:48/graph_mths
;
189 for (i
=s_mth
;i
<HISTSIZE
;i
++)
193 gdImageString(im
,gdFontSmall
,ci
+((i
-s_mth
)*cs
)+(((cw
+co
+co
)-18)/2)+1,
194 236,(unsigned char *)s_month
[data
[i
].month
-1],black
);
196 else if (graph_mths
<36)
198 gdImageChar(im
,gdFontSmall
,ci
+((i
-s_mth
)*cs
)+(((cw
+co
+co
)-6)/2)+1,
199 236,s_month
[data
[i
].month
-1][0],
200 (data
[i
].month
==1)?blue
:black
);
204 if (s_year
!=data
[i
].year
) /* year change only */
206 if (data
[i
].month
==1 && (i
-s_mth
)!=0)
207 gdImageChar(im
,gdFontSmall
, ci
+((i
-s_mth
)*cs
)-3,236,'|',blue
);
208 j
=(12-data
[i
].month
+1)*cs
;
209 if ((HISTSIZE
-i
)*cs
< j
) j
=(HISTSIZE
-i
)*cs
;
212 /* format the year string */
213 sprintf(maxvaltxt
, "%04d", data
[i
].year
);
214 gdImageString(im
,gdFontSmall
,ci
+((i
-s_mth
)*cs
)+(j
/2)-12,
215 236, (unsigned char *)maxvaltxt
, black
);
221 if (data
[i
].hit
> maxval
) maxval
= data
[i
].hit
;
222 if (data
[i
].files
> maxval
) maxval
= data
[i
].files
;
223 if (data
[i
].page
> maxval
) maxval
= data
[i
].page
;
225 if (maxval
<= 0) maxval
= 1;
226 sprintf(maxvaltxt
, "%llu", maxval
);
227 gdImageStringUp(im
,gdFontSmall
,6,26+(strlen(maxvaltxt
)*6),
228 (unsigned char *)maxvaltxt
,black
);
231 for (i
=s_mth
; i
<HISTSIZE
; i
++)
233 percent
= ((float)data
[i
].hit
/ (float)maxval
);
234 if (percent
<= 0.0) continue;
235 x1
= ci
+ ((i
-s_mth
)*cs
);
237 y1
= 232 - (percent
* 203);
238 gdImageFilledRectangle(im
, x1
, y1
, x2
, 232, HITCOLOR
);
239 if (cw
>2) gdImageRectangle(im
, x1
, y1
, x2
, 232, black
);
243 for (i
=s_mth
; i
<HISTSIZE
; i
++)
245 percent
= ((float)data
[i
].files
/ (float)maxval
);
246 if (percent
<= 0.0) continue;
247 x1
= ci
+ co
+ ((i
-s_mth
)*cs
);
249 y1
= 232 - (percent
* 203);
250 gdImageFilledRectangle(im
, x1
, y1
, x2
, 232, FILECOLOR
);
251 if (cw
>2) gdImageRectangle(im
, x1
, y1
, x2
, 232, black
);
255 for (i
=s_mth
; i
<HISTSIZE
; i
++)
257 percent
= ((float)data
[i
].page
/ (float)maxval
);
258 if (percent
<= 0.0) continue;
259 x1
= ci
+ co
+ co
+ ((i
-s_mth
)*cs
);
261 y1
= 232 - (percent
* 203);
262 gdImageFilledRectangle(im
, x1
, y1
, x2
, 232, PAGECOLOR
);
263 if (cw
>2) gdImageRectangle(im
, x1
, y1
, x2
, 232, black
);
267 for (i
=s_mth
; i
<HISTSIZE
; i
++)
269 if (data
[i
].site
> maxval
) maxval
= data
[i
].site
;
270 if (data
[i
].visit
> maxval
) maxval
= data
[i
].visit
;
272 if (maxval
<= 0) maxval
= 1;
273 sprintf(maxvaltxt
, "%llu", maxval
);
274 gdImageStringUp(im
, gdFontSmall
,493,26+(strlen(maxvaltxt
)*6),
275 (unsigned char *)maxvaltxt
, black
);
277 cs
= 180.0/graph_mths
; cw
= cs
/2;
278 co
= (48/graph_mths
<1)?1:48/graph_mths
;
279 ci
= 308+((cw
-co
)/2);
282 for (i
=s_mth
; i
<HISTSIZE
; i
++)
284 percent
= ((float)data
[i
].visit
/ (float)maxval
);
285 if (percent
<= 0.0) continue;
286 x1
= ci
+ ((i
-s_mth
)*cs
);
288 y1
= 127 - (percent
* 98);
289 gdImageFilledRectangle(im
, x1
, y1
, x2
, 127, VISITCOLOR
);
290 if (cw
>2) gdImageRectangle(im
, x1
, y1
, x2
, 127, black
);
294 for (i
=s_mth
; i
<HISTSIZE
; i
++)
296 percent
= ((float)data
[i
].site
/ (float)maxval
);
297 if (percent
<= 0.0) continue;
298 x1
= ci
+ co
+ ((i
-s_mth
)*cs
);
300 y1
= 127 - (percent
* 98);
301 gdImageFilledRectangle(im
, x1
, y1
, x2
, 127, SITECOLOR
);
302 if (cw
>2) gdImageRectangle(im
, x1
, y1
, x2
, 127, black
);
306 for (i
=s_mth
; i
<HISTSIZE
; i
++)
307 if (data
[i
].xfer
> fmaxval
) fmaxval
= data
[i
].xfer
;
308 if (fmaxval
<= 0.0) fmaxval
= 1.0;
309 sprintf(maxvaltxt
, "%.0f", fmaxval
);
310 gdImageStringUp(im
, gdFontSmall
,493,130+(strlen(maxvaltxt
)*6),
311 (unsigned char *)maxvaltxt
,black
);
313 cs
= 180.0/graph_mths
; cw
= (cs
/2)+(co
/2);
314 ci
= 308+((cw
-co
)/2);
317 for (i
=s_mth
; i
<HISTSIZE
; i
++)
319 percent
= ((float)data
[i
].xfer
/ (float)fmaxval
);
320 if (percent
<= 0.0) continue;
321 x1
= ci
+ ((i
-s_mth
)*cs
);
323 y1
= 232 - (percent
* 98);
324 gdImageFilledRectangle(im
, x1
, y1
, x2
, 232, KBYTECOLOR
);
325 if (cw
>2) gdImageRectangle(im
, x1
, y1
, x2
, 232, black
);
329 if ( !(lstat(fname
, &out_stat
)) )
331 /* check if the file a symlink */
332 if ( S_ISLNK(out_stat
.st_mode
) )
335 fprintf(stderr
,"%s %s (symlink)\n",msg_no_open
,fname
);
341 if ((out
= fopen(fname
, "wb")) != NULL
)
346 /* deallocate memory */
352 /*****************************************************************/
354 /* MONTH_GRAPH6 - Month graph with six data sets */
356 /*****************************************************************/
360 int month_graph6( char *fname
, /* filename */
361 char *title
, /* graph title */
362 int month
, /* graph month */
363 int year
, /* graph year */
364 u_int64_t data1
[31], /* data1 (hits) */
365 u_int64_t data2
[31], /* data2 (files) */
366 u_int64_t data3
[31], /* data3 (sites) */
367 double data4
[31], /* data4 (kbytes) */
368 u_int64_t data5
[31], /* data5 (views) */
369 u_int64_t data6
[31]) /* data6 (visits) */
372 /* local variables */
377 /* calc julian date for month */
378 julday
= (jdate(1, month
,year
) % 7);
380 /* initalize the graph */
381 init_graph(title
,512,400);
383 gdImageLine(im
, 21, 180, 490, 180, black
); /* draw section lines */
384 gdImageLine(im
, 21, 179, 490, 179, white
);
385 gdImageLine(im
, 21, 280, 490, 280, black
);
386 gdImageLine(im
, 21, 279, 490, 279, white
);
391 y1
=154/(graph_lines
+1);
392 for (i
=0;i
<graph_lines
;i
++)
393 gdImageLine(im
,21,((i
+1)*y1
)+25,489,((i
+1)*y1
)+25,dkgrey
);
394 y1
=100/(graph_lines
+1);
395 for (i
=0;i
<graph_lines
;i
++)
396 gdImageLine(im
,21,((i
+1)*y1
)+180,489,((i
+1)*y1
)+180,dkgrey
);
397 for (i
=0;i
<graph_lines
;i
++)
398 gdImageLine(im
,21,((i
+1)*y1
)+280,489,((i
+1)*y1
)+280,dkgrey
);
404 if ((julday
% 7 == 6) || (julday
% 7 == 0))
405 gdImageString(im
,gdFontSmall
,25+(i
*15),382,
406 (unsigned char *)numchar
[i
+1],HITCOLOR
);
408 gdImageString(im
,gdFontSmall
,25+(i
*15),382,
409 (unsigned char *)numchar
[i
+1],black
);
416 if (data1
[i
] > maxval
) maxval
= data1
[i
]; /* get max val */
417 if (data2
[i
] > maxval
) maxval
= data2
[i
];
418 if (data5
[i
] > maxval
) maxval
= data5
[i
];
420 if (maxval
<= 0) maxval
= 1;
421 sprintf(maxvaltxt
, "%llu", maxval
);
422 gdImageStringUp(im
, gdFontSmall
,8,26+(strlen(maxvaltxt
)*6),
423 (unsigned char *)maxvaltxt
,black
);
425 if (graph_legend
) /* Print color coded legends? */
428 gdImageStringUp(im
,gdFontSmall
,494,376,
429 (unsigned char *)msg_h_xfer
,dkgrey
);
430 gdImageStringUp(im
,gdFontSmall
,493,375,
431 (unsigned char *)msg_h_xfer
,KBYTECOLOR
);
433 /* Sites/Visits Legend */
434 i
= (strlen(msg_h_sites
)*6);
435 gdImageStringUp(im
,gdFontSmall
,494,276,
436 (unsigned char *)msg_h_sites
,dkgrey
);
437 gdImageStringUp(im
,gdFontSmall
,493,275,
438 (unsigned char *)msg_h_sites
,SITECOLOR
);
439 gdImageStringUp(im
,gdFontSmall
,494,276-i
-3,(unsigned char *)"/",dkgrey
);
440 gdImageStringUp(im
,gdFontSmall
,493,275-i
-3,(unsigned char *)"/",black
);
441 gdImageStringUp(im
,gdFontSmall
,494,276-i
-12,
442 (unsigned char *)msg_h_visits
,dkgrey
);
443 gdImageStringUp(im
,gdFontSmall
,493,275-i
-12,
444 (unsigned char *)msg_h_visits
,VISITCOLOR
);
446 /* Pages/Files/Hits Legend */
447 s
= ( i
=(strlen(msg_h_pages
)*6) )+
448 ( j
=(strlen(msg_h_files
)*6) )+
449 ( strlen(msg_h_hits
)*6 )+ 52;
450 gdImageStringUp(im
,gdFontSmall
,494,s
,
451 (unsigned char *)msg_h_pages
,dkgrey
);
452 gdImageStringUp(im
,gdFontSmall
,493,s
-1,
453 (unsigned char *)msg_h_pages
,PAGECOLOR
);
454 gdImageStringUp(im
,gdFontSmall
,494,s
-i
-3,(unsigned char *)"/",dkgrey
);
455 gdImageStringUp(im
,gdFontSmall
,493,s
-i
-4,(unsigned char *)"/",black
);
456 gdImageStringUp(im
,gdFontSmall
,494,s
-i
-12,
457 (unsigned char *)msg_h_files
,dkgrey
);
458 gdImageStringUp(im
,gdFontSmall
,493,s
-i
-13,
459 (unsigned char *)msg_h_files
,FILECOLOR
);
460 gdImageStringUp(im
,gdFontSmall
,494,s
-i
-j
-15,(unsigned char *)"/",dkgrey
);
461 gdImageStringUp(im
,gdFontSmall
,493,s
-i
-j
-16,(unsigned char *)"/",black
);
462 gdImageStringUp(im
,gdFontSmall
,494,s
-i
-j
-24,
463 (unsigned char *)msg_h_hits
,dkgrey
);
464 gdImageStringUp(im
,gdFontSmall
,493,s
-i
-j
-25,
465 (unsigned char *)msg_h_hits
,HITCOLOR
);
471 percent
= ((float)data1
[i
] / (float)maxval
);
472 if (percent
<= 0.0) continue;
475 y1
= 176 - (percent
* 147);
476 gdImageFilledRectangle(im
, x1
, y1
, x2
, 176, HITCOLOR
);
477 gdImageRectangle(im
, x1
, y1
, x2
, 176, black
);
483 percent
= ((float)data2
[i
] / (float)maxval
);
484 if (percent
<= 0.0) continue;
487 y1
= 176 - (percent
* 147);
488 gdImageFilledRectangle(im
, x1
, y1
, x2
, 176, FILECOLOR
);
489 gdImageRectangle(im
, x1
, y1
, x2
, 176, black
);
495 if (data5
[i
]==0) continue;
496 percent
= ((float)data5
[i
] / (float)maxval
);
497 if (percent
<= 0.0) continue;
500 y1
= 176 - (percent
* 147);
501 gdImageFilledRectangle(im
, x1
, y1
, x2
, 176, PAGECOLOR
);
502 gdImageRectangle(im
, x1
, y1
, x2
, 176, black
);
509 if (data3
[i
]>maxval
) maxval
= data3
[i
];
510 if (data6
[i
]>maxval
) maxval
= data6
[i
];
512 if (maxval
<= 0) maxval
= 1;
513 sprintf(maxvaltxt
, "%llu", maxval
);
514 gdImageStringUp(im
, gdFontSmall
,8,180+(strlen(maxvaltxt
)*6),
515 (unsigned char *)maxvaltxt
, black
);
520 percent
= ((float)data6
[i
] / (float)maxval
);
521 if (percent
<= 0.0) continue;
524 y1
= 276 - (percent
* 92);
525 gdImageFilledRectangle(im
, x1
, y1
, x2
, 276, VISITCOLOR
);
526 gdImageRectangle(im
, x1
, y1
, x2
, 276, black
);
532 percent
= ((float)data3
[i
] / (float)maxval
);
533 if (percent
<= 0.0) continue;
536 y1
= 276 - (percent
* 92);
537 gdImageFilledRectangle(im
, x1
, y1
, x2
, 276, SITECOLOR
);
538 gdImageRectangle(im
, x1
, y1
, x2
, 276, black
);
544 if (data4
[i
]>fmaxval
) fmaxval
= data4
[i
];
545 if (fmaxval
<= 0.0) fmaxval
= 1.0;
546 sprintf(maxvaltxt
, "%.0f", fmaxval
/1024);
547 gdImageStringUp(im
, gdFontSmall
,8,280+(strlen(maxvaltxt
)*6),
548 (unsigned char *)maxvaltxt
, black
);
552 percent
= data4
[i
] / fmaxval
;
553 if (percent
<= 0.0) continue;
556 y1
= 375 - ( percent
* 91 );
557 gdImageFilledRectangle(im
, x1
, y1
, x2
, 375, KBYTECOLOR
);
558 gdImageRectangle(im
, x1
, y1
, x2
, 375, black
);
562 if ( !(lstat(fname
, &out_stat
)) )
564 /* check if the file a symlink */
565 if ( S_ISLNK(out_stat
.st_mode
) )
568 fprintf(stderr
,"%s %s (symlink)\n",msg_no_open
,fname
);
574 if ((out
= fopen(fname
, "wb")) != NULL
)
579 /* deallocate memory */
585 /*****************************************************************/
587 /* DAY_GRAPH3 - Day graph with three data sets */
589 /*****************************************************************/
591 int day_graph3( char *fname
,
598 /* local variables */
602 /* initalize the graph */
603 init_graph(title
,512,256);
608 y1
=210/(graph_lines
+1);
609 for (i
=0;i
<graph_lines
;i
++)
610 gdImageLine(im
,21,((i
+1)*y1
)+25,489,((i
+1)*y1
)+25,dkgrey
);
616 gdImageString(im
,gdFontSmall
,33+(i
*19),238,
617 (unsigned char *)numchar
[i
],black
);
618 if (data1
[i
] > maxval
) maxval
= data1
[i
]; /* get max val */
619 if (data2
[i
] > maxval
) maxval
= data2
[i
];
620 if (data3
[i
] > maxval
) maxval
= data3
[i
];
622 if (maxval
<= 0) maxval
= 1;
623 sprintf(maxvaltxt
, "%llu", maxval
);
624 gdImageStringUp(im
, gdFontSmall
, 8, 26+(strlen(maxvaltxt
)*6),
625 (unsigned char *)maxvaltxt
, black
);
627 if (graph_legend
) /* print color coded legends? */
629 /* Pages/Files/Hits Legend */
630 s
= ( i
=(strlen(msg_h_pages
)*6) )+
631 ( j
=(strlen(msg_h_files
)*6) )+
632 ( strlen(msg_h_hits
)*6 )+ 52;
633 gdImageStringUp(im
,gdFontSmall
,494,s
,
634 (unsigned char *)msg_h_pages
,dkgrey
);
635 gdImageStringUp(im
,gdFontSmall
,493,s
-1,
636 (unsigned char *)msg_h_pages
,PAGECOLOR
);
637 gdImageStringUp(im
,gdFontSmall
,494,s
-i
-3,(unsigned char *)"/",dkgrey
);
638 gdImageStringUp(im
,gdFontSmall
,493,s
-i
-4,(unsigned char *)"/",black
);
639 gdImageStringUp(im
,gdFontSmall
,494,s
-i
-12,
640 (unsigned char *)msg_h_files
,dkgrey
);
641 gdImageStringUp(im
,gdFontSmall
,493,s
-i
-13,
642 (unsigned char *)msg_h_files
,FILECOLOR
);
643 gdImageStringUp(im
,gdFontSmall
,494,s
-i
-j
-15,(unsigned char *)"/",dkgrey
);
644 gdImageStringUp(im
,gdFontSmall
,493,s
-i
-j
-16,(unsigned char *)"/",black
);
645 gdImageStringUp(im
,gdFontSmall
,494,s
-i
-j
-24,
646 (unsigned char *)msg_h_hits
,dkgrey
);
647 gdImageStringUp(im
,gdFontSmall
,493,s
-i
-j
-25,
648 (unsigned char *)msg_h_hits
,HITCOLOR
);
654 percent
= ((float)data1
[i
] / (float)maxval
); /* percent of 100% */
655 if (percent
<= 0.0) continue;
658 y1
= 232 - (percent
* 203);
659 gdImageFilledRectangle(im
, x1
, y1
, x2
, 232, HITCOLOR
);
660 gdImageRectangle(im
, x1
, y1
, x2
, 232, black
);
666 percent
= ((float)data2
[i
] / (float)maxval
); /* percent of 100% */
667 if (percent
<= 0.0) continue;
670 y1
= 232 - (percent
* 203);
671 gdImageFilledRectangle(im
, x1
, y1
, x2
, 232, FILECOLOR
);
672 gdImageRectangle(im
, x1
, y1
, x2
, 232, black
);
678 percent
= ((float)data3
[i
] / (float)maxval
); /* percent of 100% */
679 if (percent
<= 0.0) continue;
682 y1
= 232 - (percent
* 203);
683 gdImageFilledRectangle(im
, x1
, y1
, x2
, 232, PAGECOLOR
);
684 gdImageRectangle(im
, x1
, y1
, x2
, 232, black
);
688 if ( !(lstat(fname
, &out_stat
)) )
690 /* check if the file a symlink */
691 if ( S_ISLNK(out_stat
.st_mode
) )
694 fprintf(stderr
,"%s %s (symlink)\n",msg_no_open
,fname
);
700 if ((out
= fopen(fname
, "wb")) != NULL
)
705 /* deallocate memory */
711 /*****************************************************************/
713 /* PIE_CHART - draw a pie chart (10 data items max) */
715 /*****************************************************************/
717 int pie_chart(char *fname
, char *title
, u_int64_t t_val
,
718 u_int64_t data1
[], char *legend
[])
720 int i
,x
,percent
,y
=47;
722 int purple_or_pie1
, ltgreen_or_pie2
, ltpurple_or_pie3
, brown_or_pie4
;
726 struct pie_data gdata
;
728 /* init graph and colors */
729 init_graph(title
,512,300);
730 r
=getred(pie_color1
); g
=getgreen(pie_color1
); b
=getblue(pie_color1
);
731 purple_or_pie1
= gdImageColorAllocate(im
, r
, g
, b
);
732 r
=getred(pie_color2
); g
=getgreen(pie_color2
); b
=getblue(pie_color2
);
733 ltgreen_or_pie2
= gdImageColorAllocate(im
, r
, g
, b
);
734 r
=getred(pie_color3
); g
=getgreen(pie_color3
); b
=getblue(pie_color3
);
735 ltpurple_or_pie3
= gdImageColorAllocate(im
, r
, g
, b
);
736 r
=getred(pie_color4
); g
=getgreen(pie_color4
); b
=getblue(pie_color4
);
737 brown_or_pie4
= gdImageColorAllocate(im
, r
, g
, b
);
739 /* do the circle... */
740 gdImageArc(im
, CX
, CY
, XRAD
, YRAD
, 0, 360, black
);
741 gdImageArc(im
, CX
, CY
+10, XRAD
-2, YRAD
-2, 2, 178, black
);
742 gdImageFillToBorder(im
, CX
, CY
+(YRAD
/2)+1, black
, black
);
745 gdata
=*calc_arc(0.0,0.0);
746 gdImageLine(im
,CX
,CY
,gdata
.x
,gdata
.y
,black
); /* inital line */
748 for (i
=0;i
<10;i
++) /* run through data array */
750 if ((data1
[i
]!=0)&&(s_arc
<1.0)) /* make sure valid slice */
752 percent
=(((double)data1
[i
]/t_val
)+0.005)*100.0;
753 if (percent
<1) break;
755 if (s_arc
+((double)percent
/100.0)>=1.0)
757 gdata
=*calc_arc(s_arc
,1.0);
762 gdata
=*calc_arc(s_arc
,s_arc
+((double)percent
/100.0));
763 s_arc
+=(double)percent
/100.0;
766 gdImageLine(im
, CX
, CY
, gdata
.x
, gdata
.y
, black
);
767 gdImageFill(im
, gdata
.mx
, gdata
.my
, i
+5);
769 snprintf(buffer
,sizeof(buffer
),"%s (%d%%)",legend
[i
], percent
);
770 x
=480-(strlen(buffer
)*7);
771 gdImageString(im
,gdFontMediumBold
, x
+1, y
+1,
772 (unsigned char *)buffer
, black
);
773 gdImageString(im
,gdFontMediumBold
, x
, y
,
774 (unsigned char *)buffer
, i
+5);
779 if (s_arc
< 1.0) /* anything left over? */
781 gdata
=*calc_arc(s_arc
,1.0);
783 gdImageFill(im
, gdata
.mx
, gdata
.my
, white
);
784 snprintf(buffer
,sizeof(buffer
),"%s (%d%%)",
785 msg_h_other
,100-(int)(s_arc
*100));
786 x
=480-(strlen(buffer
)*7);
787 gdImageString(im
,gdFontMediumBold
, x
+1, y
+1,
788 (unsigned char *)buffer
, black
);
789 gdImageString(im
,gdFontMediumBold
, x
, y
,
790 (unsigned char *)buffer
, white
);
794 if ( !(lstat(fname
, &out_stat
)) )
796 /* check if the file a symlink */
797 if ( S_ISLNK(out_stat
.st_mode
) )
800 fprintf(stderr
,"%s %s (symlink)\n",msg_no_open
,fname
);
806 if ((out
= fopen(fname
, "wb")) != NULL
)
811 /* deallocate memory */
817 /*****************************************************************/
819 /* CALC_ARC - generate x,y coordinates for pie chart */
821 /*****************************************************************/
823 struct pie_data
*calc_arc(float min
, float max
)
825 static struct pie_data data
;
828 /* Calculate max line */
830 data
.x
=cos(d
*(2*PI
))*((XRAD
-2)/2)+CX
;
831 data
.y
=sin(d
*(2*PI
))*((YRAD
-2)/2)+CY
;
832 /* Now get mid-point */
834 data
.mx
=cos(d
*(2*PI
))*(XRAD
/3)+CX
;
835 data
.my
=sin(d
*(2*PI
))*(YRAD
/3)+CY
;
839 /*****************************************************************/
841 /* INIT_GRAPH - initalize graph and draw borders */
843 /*****************************************************************/
845 void init_graph(char *title
, int xsize
, int ysize
)
849 im
= gdImageCreate(xsize
,ysize
);
851 /* allocate color maps, background color first (grey) */
852 grey
= gdImageColorAllocate(im
, 192, 192, 192);
853 dkgrey
= gdImageColorAllocate(im
, 128, 128, 128);
854 black
= gdImageColorAllocate(im
, 0, 0, 0);
855 white
= gdImageColorAllocate(im
, 255, 255, 255);
856 blue
= gdImageColorAllocate(im
, 0, 0, 255);
857 r
=getred(hit_color
); g
=getgreen(hit_color
); b
=getblue(hit_color
);
858 hit_or_green
= gdImageColorAllocate(im
, r
, g
, b
);
859 r
=getred(site_color
); g
=getgreen(site_color
); b
=getblue(site_color
);
860 site_or_orange
= gdImageColorAllocate(im
, r
, g
, b
);
861 r
=getred(file_color
); g
=getgreen(file_color
); b
=getblue(file_color
);
862 file_or_blue
= gdImageColorAllocate(im
, r
, g
, b
);
863 r
=getred(kbyte_color
); g
=getgreen(kbyte_color
); b
=getblue(kbyte_color
);
864 kbyte_or_red
= gdImageColorAllocate(im
, r
, g
, b
);
865 r
=getred(page_color
); g
=getgreen(page_color
); b
=getblue(page_color
);
866 page_or_cyan
= gdImageColorAllocate(im
, r
, g
, b
);
867 r
=getred(visit_color
); g
=getgreen(visit_color
); b
=getblue(visit_color
);
868 visit_or_yellow
= gdImageColorAllocate(im
, r
, g
, b
);
870 /* black outside border */
871 gdImageRectangle(im
, 0, 0, xsize
-1, ysize
-1, black
);
873 /* do shadow effect (bevel) border */
876 gdImageLine(im
, i
, i
, xsize
-i
-2, i
, white
);
877 gdImageLine(im
, i
, i
, i
, ysize
-i
-2, white
);
878 gdImageLine(im
, i
+1, ysize
-i
-1, xsize
-i
-1, ysize
-i
-1, dkgrey
);
879 gdImageLine(im
, xsize
-i
-1, i
+1, xsize
-i
-1, ysize
-i
-1, dkgrey
);
882 /* generic inside shadow box */
883 gdImageRectangle(im
, 20, 25, xsize
-21, ysize
-21, black
);
884 gdImageRectangle(im
, 19, 24, xsize
-22, ysize
-22, white
);
886 /* display the graph title */
887 gdImageString(im
, gdFontMediumBold
, 20, 8,
888 (unsigned char *)title
, blue
);
893 /****************************************************************/
895 /* ASHEX2INT - ASCII HEX TO INT CONVERTER */
897 /****************************************************************/
899 int ashex2int(char *str
)
901 /* returns base-10 integer value from a 2 ASCII hex number */
902 return from_hex(str
[1])+(from_hex(str
[0])*16);