Imported Debian patch 2.23.05-1
[hcoop/zz_old/debian/webalizer.git] / graphs.c
CommitLineData
e015f748
CE
1/*
2 graphs.c - produces graphs used by the Webalizer
3
4 Copyright (C) 1997-2011 Bradford L. Barrett
5
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.
12
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.
17
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
21
22*/
23
24#include <math.h>
25#include <stdio.h>
26#include <string.h>
27#include <sys/types.h>
28#include <errno.h>
29#include <sys/stat.h>
30#include <gd.h>
31#include <gdfontt.h>
32#include <gdfonts.h>
33#include <gdfontmb.h>
34
35/* need socket header? */
36#ifdef HAVE_SYS_SOCKET_H
37#include <sys/socket.h>
38#endif
39
40#include "webalizer.h"
41#include "preserve.h"
42#include "lang.h"
43#include "graphs.h"
44
45/* Some systems don't define this */
46#ifndef PI
47#define PI 3.14159265358979323846
48#endif
49
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 */
56
57/* shortcuts to convert ASCII hex color for gdImageColorAllocate() */
58
59#define getred(s) (ashex2int((s[0] == '#')?s+1:s))
60/* returns the red base-10 integer value from a html color */
61
62#define getgreen(s) (ashex2int((s[0] == '#')?s+3:s+2))
63/* returns the green base-10 integer value from a html color */
64
65#define getblue(s) (ashex2int((s[0] == '#')?s+5:s+4))
66/* returns the blue base-10 integer value from a html color */
67
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 */
72
73/* forward reference internal routines */
74
75void init_graph(char *, int, int);
76struct pie_data *calc_arc(float, float);
77int ashex2int(char *);
78
79/* common public declarations */
80
81char *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"};
84
85gdImagePtr im; /* image buffer */
86FILE *out; /* output file for PNG */
87struct stat out_stat; /* stat struct for PNG */
88char maxvaltxt[32]; /* graph values */
89float percent; /* percent storage */
90u_int64_t julday; /* julday value */
91
92struct pie_data { int x; int y; /* line x,y */
93 int mx; int my; }; /* midpoint x,y */
94/* colors */
95int 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;
98
99/*****************************************************************/
100/* */
101/* YEAR_GRAPH6x - Year graph from array of hist_rec structs */
102/* */
103/*****************************************************************/
104
105int year_graph6x(char *fname, char *title, struct hist_rec data[HISTSIZE])
106{
107
108 /* local variables */
109 int i,j,x1,y1,x2;
110 int s_mth,s_year=0;
111 float cw,cs,co,ci;
112
113 u_int64_t maxval=1;
114 double fmaxval=0.0;
115
116 /* initalize the graph */
117 init_graph(title,512,256); /* init as 512 x 256 */
118
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);
123
124 /* index lines? */
125 if (graph_lines)
126 {
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);
135 }
136
137 /* color coded legends? */
138 if (graph_legend)
139 {
140 /* Kbytes Legend */
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);
146
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);
160
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);
180 }
181
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;
186 ci = 22+((cw-co)/2);
187
188 /* x-axis legend */
189 for (i=s_mth;i<HISTSIZE;i++)
190 {
191 if (graph_mths<16)
192 {
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);
195 }
196 else if (graph_mths<36)
197 {
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);
201 }
202 else
203 {
204 if (s_year!=data[i].year) /* year change only */
205 {
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;
210 if (j>28)
211 {
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);
216 }
217 s_year=data[i].year;
218 }
219 }
220
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;
224 }
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);
229
230 /* hits */
231 for (i=s_mth; i<HISTSIZE; i++)
232 {
233 percent = ((float)data[i].hit / (float)maxval);
234 if (percent <= 0.0) continue;
235 x1 = ci + ((i-s_mth)*cs);
236 x2 = x1 + cw;
237 y1 = 232 - (percent * 203);
238 gdImageFilledRectangle(im, x1, y1, x2, 232, HITCOLOR);
239 if (cw>2) gdImageRectangle(im, x1, y1, x2, 232, black);
240 }
241
242 /* files */
243 for (i=s_mth; i<HISTSIZE; i++)
244 {
245 percent = ((float)data[i].files / (float)maxval);
246 if (percent <= 0.0) continue;
247 x1 = ci + co + ((i-s_mth)*cs);
248 x2 = x1 + cw;
249 y1 = 232 - (percent * 203);
250 gdImageFilledRectangle(im, x1, y1, x2, 232, FILECOLOR);
251 if (cw>2) gdImageRectangle(im, x1, y1, x2, 232, black);
252 }
253
254 /* pages */
255 for (i=s_mth; i<HISTSIZE; i++)
256 {
257 percent = ((float)data[i].page / (float)maxval);
258 if (percent <= 0.0) continue;
259 x1 = ci + co + co + ((i-s_mth)*cs);
260 x2 = x1 + cw;
261 y1 = 232 - (percent * 203);
262 gdImageFilledRectangle(im, x1, y1, x2, 232, PAGECOLOR);
263 if (cw>2) gdImageRectangle(im, x1, y1, x2, 232, black);
264 }
265
266 maxval=0;
267 for (i=s_mth; i<HISTSIZE; i++)
268 {
269 if (data[i].site > maxval) maxval = data[i].site;
270 if (data[i].visit > maxval) maxval = data[i].visit;
271 }
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);
276
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);
280
281 /* visits */
282 for (i=s_mth; i<HISTSIZE; i++)
283 {
284 percent = ((float)data[i].visit / (float)maxval);
285 if (percent <= 0.0) continue;
286 x1 = ci + ((i-s_mth)*cs);
287 x2 = x1 + cw;
288 y1 = 127 - (percent * 98);
289 gdImageFilledRectangle(im, x1, y1, x2, 127, VISITCOLOR);
290 if (cw>2) gdImageRectangle(im, x1, y1, x2, 127, black);
291 }
292
293 /* sites */
294 for (i=s_mth; i<HISTSIZE; i++)
295 {
296 percent = ((float)data[i].site / (float)maxval);
297 if (percent <= 0.0) continue;
298 x1 = ci + co + ((i-s_mth)*cs);
299 x2 = x1 + cw;
300 y1 = 127 - (percent * 98);
301 gdImageFilledRectangle(im, x1, y1, x2, 127, SITECOLOR);
302 if (cw>2) gdImageRectangle(im, x1, y1, x2, 127, black);
303 }
304
305 fmaxval=0.0;
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);
312
313 cs = 180.0/graph_mths; cw = (cs/2)+(co/2);
314 ci = 308+((cw-co)/2);
315
316 /* xfer */
317 for (i=s_mth; i<HISTSIZE; i++)
318 {
319 percent = ((float)data[i].xfer / (float)fmaxval);
320 if (percent <= 0.0) continue;
321 x1 = ci+ ((i-s_mth)*cs);
322 x2 = x1 + cw;
323 y1 = 232 - (percent * 98);
324 gdImageFilledRectangle(im, x1, y1, x2, 232, KBYTECOLOR);
325 if (cw>2) gdImageRectangle(im, x1, y1, x2, 232, black);
326 }
327
328 /* stat the file */
329 if ( !(lstat(fname, &out_stat)) )
330 {
331 /* check if the file a symlink */
332 if ( S_ISLNK(out_stat.st_mode) )
333 {
334 if (verbose)
335 fprintf(stderr,"%s %s (symlink)\n",msg_no_open,fname);
336 return(EBADF);
337 }
338 }
339
340 /* save PNG image */
341 if ((out = fopen(fname, "wb")) != NULL)
342 {
343 gdImagePng(im, out);
344 fclose(out);
345 }
346 /* deallocate memory */
347 gdImageDestroy(im);
348
349 return (0);
350}
351
352/*****************************************************************/
353/* */
354/* MONTH_GRAPH6 - Month graph with six data sets */
355/* */
356/*****************************************************************/
357
358#define YSIZE 400
359
360int 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) */
370{
371
372 /* local variables */
373 int i,j,s,x1,y1,x2;
374 u_int64_t maxval=0;
375 double fmaxval=0.0;
376
377 /* calc julian date for month */
378 julday = (jdate(1, month,year) % 7);
379
380 /* initalize the graph */
381 init_graph(title,512,400);
382
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);
387
388 /* index lines? */
389 if (graph_lines)
390 {
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);
399 }
400
401 /* x-axis legend */
402 for (i=0;i<31;i++)
403 {
404 if ((julday % 7 == 6) || (julday % 7 == 0))
405 gdImageString(im,gdFontSmall,25+(i*15),382,
406 (unsigned char *)numchar[i+1],HITCOLOR);
407 else
408 gdImageString(im,gdFontSmall,25+(i*15),382,
409 (unsigned char *)numchar[i+1],black);
410 julday++;
411 }
412
413 /* y-axis legend */
414 for (i=0; i<31; i++)
415 {
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];
419 }
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);
424
425 if (graph_legend) /* Print color coded legends? */
426 {
427 /* Kbytes Legend */
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);
432
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);
445
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);
466 }
467
468 /* data1 */
469 for (i=0; i<31; i++)
470 {
471 percent = ((float)data1[i] / (float)maxval);
472 if (percent <= 0.0) continue;
473 x1 = 25 + (i*15);
474 x2 = x1 + 7;
475 y1 = 176 - (percent * 147);
476 gdImageFilledRectangle(im, x1, y1, x2, 176, HITCOLOR);
477 gdImageRectangle(im, x1, y1, x2, 176, black);
478 }
479
480 /* data2 */
481 for (i=0; i<31; i++)
482 {
483 percent = ((float)data2[i] / (float)maxval);
484 if (percent <= 0.0) continue;
485 x1 = 27 + (i*15);
486 x2 = x1 + 7;
487 y1 = 176 - (percent * 147);
488 gdImageFilledRectangle(im, x1, y1, x2, 176, FILECOLOR);
489 gdImageRectangle(im, x1, y1, x2, 176, black);
490 }
491
492 /* data5 */
493 for (i=0; i<31; i++)
494 {
495 if (data5[i]==0) continue;
496 percent = ((float)data5[i] / (float)maxval);
497 if (percent <= 0.0) continue;
498 x1 = 29 + (i*15);
499 x2 = x1 + 7;
500 y1 = 176 - (percent * 147);
501 gdImageFilledRectangle(im, x1, y1, x2, 176, PAGECOLOR);
502 gdImageRectangle(im, x1, y1, x2, 176, black);
503 }
504
505 /* sites / visits */
506 maxval=0;
507 for (i=0; i<31; i++)
508 {
509 if (data3[i]>maxval) maxval = data3[i];
510 if (data6[i]>maxval) maxval = data6[i];
511 }
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);
516
517 /* data 6 */
518 for (i=0; i<31; i++)
519 {
520 percent = ((float)data6[i] / (float)maxval);
521 if (percent <= 0.0) continue;
522 x1 = 25 + (i*15);
523 x2 = x1 + 8;
524 y1 = 276 - (percent * 92);
525 gdImageFilledRectangle(im, x1, y1, x2, 276, VISITCOLOR);
526 gdImageRectangle(im, x1, y1, x2, 276, black);
527 }
528
529 /* data 3 */
530 for (i=0; i<31; i++)
531 {
532 percent = ((float)data3[i] / (float)maxval);
533 if (percent <= 0.0) continue;
534 x1 = 29 + (i*15);
535 x2 = x1 + 7;
536 y1 = 276 - (percent * 92);
537 gdImageFilledRectangle(im, x1, y1, x2, 276, SITECOLOR);
538 gdImageRectangle(im, x1, y1, x2, 276, black);
539 }
540
541 /* data4 */
542 fmaxval=0.0;
543 for (i=0; i<31; i++)
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);
549
550 for (i=0; i<31; i++)
551 {
552 percent = data4[i] / fmaxval;
553 if (percent <= 0.0) continue;
554 x1 = 26 + (i*15);
555 x2 = x1 + 10;
556 y1 = 375 - ( percent * 91 );
557 gdImageFilledRectangle(im, x1, y1, x2, 375, KBYTECOLOR);
558 gdImageRectangle(im, x1, y1, x2, 375, black);
559 }
560
561 /* stat the file */
562 if ( !(lstat(fname, &out_stat)) )
563 {
564 /* check if the file a symlink */
565 if ( S_ISLNK(out_stat.st_mode) )
566 {
567 if (verbose)
568 fprintf(stderr,"%s %s (symlink)\n",msg_no_open,fname);
569 return(EBADF);
570 }
571 }
572
573 /* save PNG image */
574 if ((out = fopen(fname, "wb")) != NULL)
575 {
576 gdImagePng(im, out);
577 fclose(out);
578 }
579 /* deallocate memory */
580 gdImageDestroy(im);
581
582 return (0);
583}
584
585/*****************************************************************/
586/* */
587/* DAY_GRAPH3 - Day graph with three data sets */
588/* */
589/*****************************************************************/
590
591int day_graph3( char *fname,
592 char *title,
593 u_int64_t data1[24],
594 u_int64_t data2[24],
595 u_int64_t data3[24])
596{
597
598 /* local variables */
599 int i,j,s,x1,y1,x2;
600 u_int64_t maxval=0;
601
602 /* initalize the graph */
603 init_graph(title,512,256);
604
605 /* index lines? */
606 if (graph_lines)
607 {
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);
611 }
612
613 /* x-axis legend */
614 for (i=0;i<24;i++)
615 {
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];
621 }
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);
626
627 if (graph_legend) /* print color coded legends? */
628 {
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);
649 }
650
651 /* data1 */
652 for (i=0; i<24; i++)
653 {
654 percent = ((float)data1[i] / (float)maxval); /* percent of 100% */
655 if (percent <= 0.0) continue;
656 x1 = 29 + (i*19);
657 x2 = x1 + 10;
658 y1 = 232 - (percent * 203);
659 gdImageFilledRectangle(im, x1, y1, x2, 232, HITCOLOR);
660 gdImageRectangle(im, x1, y1, x2, 232, black);
661 }
662
663 /* data2 */
664 for (i=0; i<24; i++)
665 {
666 percent = ((float)data2[i] / (float)maxval); /* percent of 100% */
667 if (percent <= 0.0) continue;
668 x1 = 32 + (i*19);
669 x2 = x1 + 10;
670 y1 = 232 - (percent * 203);
671 gdImageFilledRectangle(im, x1, y1, x2, 232, FILECOLOR);
672 gdImageRectangle(im, x1, y1, x2, 232, black);
673 }
674
675 /* data3 */
676 for (i=0; i<24; i++)
677 {
678 percent = ((float)data3[i] / (float)maxval); /* percent of 100% */
679 if (percent <= 0.0) continue;
680 x1 = 35 + (i*19);
681 x2 = x1 + 10;
682 y1 = 232 - (percent * 203);
683 gdImageFilledRectangle(im, x1, y1, x2, 232, PAGECOLOR);
684 gdImageRectangle(im, x1, y1, x2, 232, black);
685 }
686
687 /* stat the file */
688 if ( !(lstat(fname, &out_stat)) )
689 {
690 /* check if the file a symlink */
691 if ( S_ISLNK(out_stat.st_mode) )
692 {
693 if (verbose)
694 fprintf(stderr,"%s %s (symlink)\n",msg_no_open,fname);
695 return(EBADF);
696 }
697 }
698
699 /* save PNG image */
700 if ((out = fopen(fname, "wb")) != NULL)
701 {
702 gdImagePng(im, out);
703 fclose(out);
704 }
705 /* deallocate memory */
706 gdImageDestroy(im);
707
708 return (0);
709}
710
711/*****************************************************************/
712/* */
713/* PIE_CHART - draw a pie chart (10 data items max) */
714/* */
715/*****************************************************************/
716
717int pie_chart(char *fname, char *title, u_int64_t t_val,
718 u_int64_t data1[], char *legend[])
719{
720 int i,x,percent,y=47;
721 double s_arc=0.0;
722 int purple_or_pie1, ltgreen_or_pie2, ltpurple_or_pie3, brown_or_pie4;
723 int r, g, b;
724 char buffer[128];
725
726 struct pie_data gdata;
727
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);
738
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);
743
744 /* slice the pie */
745 gdata=*calc_arc(0.0,0.0);
746 gdImageLine(im,CX,CY,gdata.x,gdata.y,black); /* inital line */
747
748 for (i=0;i<10;i++) /* run through data array */
749 {
750 if ((data1[i]!=0)&&(s_arc<1.0)) /* make sure valid slice */
751 {
752 percent=(((double)data1[i]/t_val)+0.005)*100.0;
753 if (percent<1) break;
754
755 if (s_arc+((double)percent/100.0)>=1.0)
756 {
757 gdata=*calc_arc(s_arc,1.0);
758 s_arc=1.0;
759 }
760 else
761 {
762 gdata=*calc_arc(s_arc,s_arc+((double)percent/100.0));
763 s_arc+=(double)percent/100.0;
764 }
765
766 gdImageLine(im, CX, CY, gdata.x, gdata.y, black);
767 gdImageFill(im, gdata.mx, gdata.my, i+5);
768
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);
775 y+=20;
776 }
777 }
778
779 if (s_arc < 1.0) /* anything left over? */
780 {
781 gdata=*calc_arc(s_arc,1.0);
782
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);
791 }
792
793 /* stat the file */
794 if ( !(lstat(fname, &out_stat)) )
795 {
796 /* check if the file a symlink */
797 if ( S_ISLNK(out_stat.st_mode) )
798 {
799 if (verbose)
800 fprintf(stderr,"%s %s (symlink)\n",msg_no_open,fname);
801 return(EBADF);
802 }
803 }
804
805 /* save PNG image */
806 if ((out = fopen(fname, "wb")) != NULL)
807 {
808 gdImagePng(im, out);
809 fclose(out);
810 }
811 /* deallocate memory */
812 gdImageDestroy(im);
813
814 return (0);
815}
816
817/*****************************************************************/
818/* */
819/* CALC_ARC - generate x,y coordinates for pie chart */
820/* */
821/*****************************************************************/
822
823struct pie_data *calc_arc(float min, float max)
824{
825 static struct pie_data data;
826 double d;
827
828 /* Calculate max line */
829 d=max;
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 */
833 d=((min+max)/2);
834 data.mx=cos(d*(2*PI))*(XRAD/3)+CX;
835 data.my=sin(d*(2*PI))*(YRAD/3)+CY;
836 return &data;
837}
838
839/*****************************************************************/
840/* */
841/* INIT_GRAPH - initalize graph and draw borders */
842/* */
843/*****************************************************************/
844
845void init_graph(char *title, int xsize, int ysize)
846{
847 int i, r, g, b;
848
849 im = gdImageCreate(xsize,ysize);
850
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);
869
870 /* black outside border */
871 gdImageRectangle(im, 0, 0, xsize-1, ysize-1, black);
872
873 /* do shadow effect (bevel) border */
874 for (i=1; i<5 ;i++)
875 {
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);
880 }
881
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);
885
886 /* display the graph title */
887 gdImageString(im, gdFontMediumBold, 20, 8,
888 (unsigned char *)title, blue);
889
890 return;
891}
892
893/****************************************************************/
894/* */
895/* ASHEX2INT - ASCII HEX TO INT CONVERTER */
896/* */
897/****************************************************************/
898
899int ashex2int(char *str)
900{
901 /* returns base-10 integer value from a 2 ASCII hex number */
902 return from_hex(str[1])+(from_hex(str[0])*16);
903}