]>
git.ipfire.org Git - thirdparty/sarg.git/blob - grepday.c
2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
6 * please look at http://sarg.sourceforge.net/donations.php
8 * http://sourceforge.net/projects/sarg/forums/forum/363374
9 * ---------------------------------------------------------------------
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
27 #include "include/conf.h"
28 #include "include/defs.h"
32 #if defined(HAVE_ICONV_H) && defined(gdFTEX_Unicode)
37 struct GraphDataStruct
47 //! The color of the top side of a graph bar.
49 //! The color of the right side of a graph bar.
51 //! The color of the front side of a graph bar.
53 //! The libgd image we are drawing on.
55 //! An allocated buffer to convert the string into UTF-8.
57 //! The number of bytes allocated for the string buffer.
59 //! The bottom border of the graph.
61 //! The top border of the graph.
63 //! The left border of the graph.
65 //! The right border of the graph.
67 //! The height at which the bottom depth border of the graph extends.
69 //! The distance between two ticks on the horizontal axis.
71 //! The distance between two ticks on the vertical axis.
73 //! The exterior length of a tick on the scales.
75 //! The distance, in pixels, between two ticks along the Y axis.
88 //! The data points to plot.
89 long long int *datapoints
;
90 //! The number of points to plot.
92 //! The minimum data to plot along the Y axis.
94 //! The maximum data to plot along the Y axis.
96 //! The type of Y axis to draw.
98 //! The label to write on the X axis.
100 //! The label to write on the Y axis.
102 //! The name of the output PNG file.
120 //! The iconv object to convert the text from the locale character set to UTF-8.
121 iconv_t localtoutf
=(iconv_t
)-1;
124 static void Sarg_gdImageStringFT (struct GraphDataStruct
*gdata
, int fg
, char *fontlist
,
125 double ptsize
, double angle
, int x
, int y
, const char *string
,enum TextRefPos RefPos
)
130 int minx
,miny
,maxx
,maxy
;
134 if (localtoutf
!=(iconv_t
)-1) {
139 slen
= strlen(string
) + 1; // We must include string termination character
140 sslen
= slen
* 3; // We assume that the UTF8 string will not be bigger than 3 times the original size.
141 if (sslen
>gdata
->string_size
) {
142 sstring
= (char *)realloc(gdata
->string
,sslen
);
144 debuga(__FILE__
,__LINE__
,_("realloc error (%"PRIu64
" bytes required)\n"),(uint64_t)sslen
);
147 gdata
->string
=(char *)sstring
;
148 gdata
->string_size
=sslen
;
150 sstring
=gdata
->string
;
151 sslen
=gdata
->string_size
;
156 if (iconv (localtoutf
, (ICONV_CONST
char **)&str
, &slen
, &sstr
, &sslen
)==-1) {
157 debuga(__FILE__
,__LINE__
,_("iconv failed to convert string \"%s\" from %s to UTF-8: %s\n"),string
,CharSet
,strerror(errno
));
158 sstring
=(char *)string
; //show something sensible on the graph
161 sstring
=(char *)string
; //show something sensible on the graph
164 sstring
=(char *)string
;
167 if (RefPos
!=TRP_BottomLeft
) {
168 retval
= gdImageStringFTEx (NULL
, brect
, fg
, fontlist
, ptsize
, angle
, 0, 0, sstring
, gdFTEX_Unicode
);
170 debuga(__FILE__
,__LINE__
,_("libgd failed to calculate the bounding box of the text \"%s\": %s\n"),sstring
,retval
);
174 From libgd documentation, brect contains this without taking into account the angle:
175 0 lower left corner, X position
176 1 lower left corner, Y position
177 2 lower right corner, X position
178 3 lower right corner, Y position
179 4 upper right corner, X position
180 5 upper right corner, Y position
181 6 upper left corner, X position
182 7 upper left corner, Y position
186 for (i
=2 ; i
<7 ; i
+=2) {
187 if (minx
>brect
[i
]) minx
=brect
[i
];
188 if (maxx
<brect
[i
]) maxx
=brect
[i
];
189 if (miny
>brect
[i
+1]) miny
=brect
[i
+1];
190 if (maxy
<brect
[i
+1]) maxy
=brect
[i
+1];
213 case TRP_BottomCenter
:
217 case TRP_BottomRight
:
230 case TRP_CenterRight
:
235 retval
= gdImageStringFTEx (gdata
->im
, brect
, fg
, fontlist
, ptsize
, angle
, x
, y
, sstring
, gdFTEX_Unicode
);
237 debuga(__FILE__
,__LINE__
,_("libgd failed to render the text \"%s\": %s\n"),sstring
,retval
);
242 static void bar(struct GraphDataStruct
*gdata
,int x1
,double y
,const char *label
)
248 val
=gdata
->BottomGraph
+5-(int)(y
*gdata
->YScale
+0.5);
249 width2
=(int)(gdata
->XScale
/4.);
251 // front side of the bar
252 if (val
<gdata
->BottomDepth
)
253 gdImageFilledRectangle(gdata
->im
, x1
-width2
, val
, x1
+width2
, gdata
->BottomDepth
, gdata
->color3
);
255 // top side of the bar
256 points
[0].x
= x1
-width2
+5;
258 points
[1].x
= x1
-width2
;
260 points
[2].x
= x1
+width2
;
262 points
[3].x
= x1
+width2
+5;
264 gdImageFilledPolygon(gdata
->im
, points
, 4, gdata
->color1
);
266 gdImageLine(gdata
->im
, x1
+2, val
-2, x1
+2, val
-10, gdata
->dimgray
);
267 gdImageFilledRectangle(gdata
->im
, x1
-8, val
-20, x1
+12, val
-10, gdata
->goldenrod
);
268 gdImageRectangle(gdata
->im
, x1
-8, val
-20, x1
+12, val
-10, gdata
->goldenrod2
);
270 Sarg_gdImageStringFT(gdata
,gdata
->black
,GraphFont
,6,0.0,x1
+2,val
-12,label
,TRP_BottomCenter
);
272 // lateral side of the bar
273 if (val
<gdata
->BottomDepth
) {
274 points
[0].x
= x1
+width2
+5;
276 points
[1].x
= x1
+width2
;
278 points
[2].x
= x1
+width2
;
279 points
[2].y
= gdata
->BottomDepth
;
280 points
[3].x
= x1
+width2
+5;
281 points
[3].y
= gdata
->BottomGraph
;
282 gdImageFilledPolygon(gdata
->im
, points
, 4, gdata
->color2
);
288 static int greport_compute_yaxis(struct PlotStruct
*pdata
,struct GraphDataStruct
*gdata
)
294 if (pdata
->ymin
<0.) {
295 debuga(__FILE__
,__LINE__
,_("Minimum for Y scale of the graph is out of range: %"PRId64
"\n"),(int64_t)pdata
->ymin
);
298 if (pdata
->ymax
<=0.) {
299 debuga(__FILE__
,__LINE__
,_("Maximum for Y scale of the graph is out of range: %"PRId64
"\n"),(int64_t)pdata
->ymax
);
306 symin
=(double)pdata
->ymin
;
307 symax
=(double)pdata
->ymax
;
312 symin
=log(pdata
->ymin
);
315 symax
=log(pdata
->ymax
);
319 symin
=(double)pdata
->ymin
;
320 symax
=(double)pdata
->ymax
;
324 debuga(__FILE__
,__LINE__
,_("Unknown type %d for Y axis scale\n"),pdata
->ytype
);
327 gdata
->YTickSpace
=10;
330 yscale
=(double)(gdata
->BottomGraph
-gdata
->TopGraph
)/range
;
331 gdata
->YScale
=yscale
;
335 static void greport_formatbin(double yval
,int maxdigits
,char *string
,int slen
)
338 char schar
[]={'\0','k','M','G','T','P'};
343 for (scount
=0 ; scount
<sizeof(schar
)/sizeof(*schar
) && yval
>=1000. ; scount
++)
351 if (ndigits
>maxdigits
) ndigits
=maxdigits
;
352 len
=snprintf(string
,slen
,"%.*f",ndigits
,(float)yval
);
354 for (i
=0 ; i
<len
; i
++)
355 if (string
[i
]=='.') string
[i
]=',';
356 if (schar
[scount
] && len
<slen
) {
357 string
[len
++]=schar
[scount
];
362 static void greport_draw_yaxis(struct PlotStruct
*pdata
,struct GraphDataStruct
*gdata
)
373 y0
=gdata
->BottomGraph
;
374 yt
=gdata
->BottomDepth
-gdata
->BottomGraph
;
375 xexterior
=gdata
->LeftGraph
-10;
376 xinterior
=gdata
->LeftGraph
;
377 xtick
=gdata
->LeftGraph
-10-gdata
->TickLength
;
378 for(y
=y0
-gdata
->YTickSpace
; y
>=gdata
->TopGraph
; y
-=gdata
->YTickSpace
) {
379 gdImageLine(gdata
->im
, xtick
, y
+yt
, xexterior
, y
+yt
, gdata
->dimgray
);
380 gdImageLine(gdata
->im
, xexterior
, y
+yt
, xinterior
, y
, gdata
->dimgray
);
381 gdImageLine(gdata
->im
, xinterior
, y
, gdata
->RightGraph
, y
, gdata
->dimgray
);
382 switch (pdata
->ytype
)
385 yval
=(double)(y0
-y
)/gdata
->YScale
+(double)pdata
->ymin
;
386 greport_formatbin(yval
,2,YLabel
,sizeof(YLabel
));
390 yval
=exp((double)(y0
-y
)/gdata
->YScale
+log(pdata
->ymin
));
391 greport_formatbin(yval
,2,YLabel
,sizeof(YLabel
));
398 yval
=(double)(y0
-y
)/gdata
->YScale
+(double)pdata
->ymin
;
399 t
=(int)(yval
/60000.+0.5);
400 snprintf(YLabel
,sizeof(YLabel
),"%02d:%02d",t
/60,t
%60);
404 Sarg_gdImageStringFT(gdata
,gdata
->dimgray
,GraphFont
,7,0.0,xtick
,y
+yt
,YLabel
,TRP_CenterRight
);
408 static void greport_plot(const struct userinfostruct
*uinfo
,struct PlotStruct
*pdata
)
420 struct GraphDataStruct gdata
;
421 const int ImgXSize
=720;
422 const int ImgYSize
=480;
423 const int LeftMargin
=60;
424 const int RightMargin
=20;
425 const int TopMargin
=60;
426 const int BottomMargin
=60;
427 const int TickLength
=3;
428 const int ZTickLength
=5;
433 memset(&gdata
,0,sizeof(gdata
));
435 gdata
.im
= gdImageCreate(ImgXSize
, ImgYSize
);
436 gdata
.BottomGraph
=ImgYSize
-BottomMargin
;
437 gdata
.LeftGraph
=LeftMargin
;
438 gdata
.RightGraph
=ImgXSize
-RightMargin
;
439 gdata
.TopGraph
=TopMargin
;
440 gdata
.BottomDepth
=gdata
.BottomGraph
+5;
441 gdata
.XScale
=(double)(gdata
.RightGraph
-gdata
.LeftGraph
)/(pdata
->npoints
+1);
442 if (greport_compute_yaxis(pdata
,&gdata
)<0) return;
443 gdata
.TickLength
=TickLength
;
445 // first allocated color is the background
446 gdata
.lavender
= gdImageColorAllocate(gdata
.im
, 230, 230, 250);
447 gdata
.gray
= gdImageColorAllocate(gdata
.im
, 192, 192, 192);
448 gdata
.silver
= gdImageColorAllocate(gdata
.im
, 211, 211, 211);
449 gdata
.black
= gdImageColorAllocate(gdata
.im
, 0, 0, 0);
450 gdata
.dimgray
= gdImageColorAllocate(gdata
.im
, 105, 105, 105);
451 gdata
.darkblue
= gdImageColorAllocate(gdata
.im
, 0, 0, 139);
452 gdata
.goldenrod
= gdImageColorAllocate(gdata
.im
, 234, 234, 174);
453 gdata
.goldenrod2
= gdImageColorAllocate(gdata
.im
, 207, 181, 59);
455 if(strcmp(GraphDaysBytesBarColor
,"orange") == 0) {
456 gdata
.color1
= gdImageColorAllocate(gdata
.im
, 255, 233, 142);
457 gdata
.color2
= gdImageColorAllocate(gdata
.im
, 220, 163, 72);
458 gdata
.color3
= gdImageColorAllocate(gdata
.im
, 255, 198, 107);
460 else if(strcmp(GraphDaysBytesBarColor
,"blue") == 0) {
461 gdata
.color1
= gdImageColorAllocate(gdata
.im
, 62, 80, 167);
462 gdata
.color2
= gdImageColorAllocate(gdata
.im
, 40, 51, 101);
463 gdata
.color3
= gdImageColorAllocate(gdata
.im
, 57, 73, 150);
465 else if(strcmp(GraphDaysBytesBarColor
,"green") == 0) {
466 gdata
.color1
= gdImageColorAllocate(gdata
.im
,120,166,129);
467 gdata
.color2
= gdImageColorAllocate(gdata
.im
,84,113,82);
468 gdata
.color3
= gdImageColorAllocate(gdata
.im
,158,223,167);
470 else if(strcmp(GraphDaysBytesBarColor
,"yellow") == 0) {
471 gdata
.color1
= gdImageColorAllocate(gdata
.im
,185,185,10);
472 gdata
.color2
= gdImageColorAllocate(gdata
.im
,111,111,10);
473 gdata
.color3
= gdImageColorAllocate(gdata
.im
,166,166,10);
475 else if(strcmp(GraphDaysBytesBarColor
,"brown") == 0) {
476 gdata
.color1
= gdImageColorAllocate(gdata
.im
,97,45,27);
477 gdata
.color2
= gdImageColorAllocate(gdata
.im
,60,30,20);
478 gdata
.color3
= gdImageColorAllocate(gdata
.im
,88,41,26);
480 else if(strcmp(GraphDaysBytesBarColor
,"red") == 0){
481 gdata
.color1
= gdImageColorAllocate(gdata
.im
,185,10,10);
482 gdata
.color2
= gdImageColorAllocate(gdata
.im
,111,10,10);
483 gdata
.color3
= gdImageColorAllocate(gdata
.im
,166,10,10);
485 debuga(__FILE__
,__LINE__
,_("Unknown color \"%s\" requested for the graph. Using orange instead\n"),GraphDaysBytesBarColor
);
486 gdata
.color1
= gdImageColorAllocate(gdata
.im
, 255, 233, 142);
487 gdata
.color2
= gdImageColorAllocate(gdata
.im
, 220, 163, 72);
488 gdata
.color3
= gdImageColorAllocate(gdata
.im
, 255, 198, 107);
491 // rectangle around the image
492 gdImageRectangle(gdata
.im
, 0, 0, ImgXSize
-1, ImgYSize
-1, gdata
.dimgray
);
493 // backtround of the graph
494 gdImageFilledRectangle(gdata
.im
, LeftMargin
, gdata
.TopGraph
, gdata
.RightGraph
, gdata
.BottomGraph
, gdata
.silver
);
496 // depth of the left Y axis
497 points
[0].x
= gdata
.LeftGraph
-10;
498 points
[0].y
= gdata
.TopGraph
+5;
499 points
[1].x
= gdata
.LeftGraph
-10;
500 points
[1].y
= gdata
.BottomDepth
;
501 points
[2].x
= gdata
.LeftGraph
;
502 points
[2].y
= gdata
.BottomGraph
;
503 points
[3].x
= gdata
.LeftGraph
;
504 points
[3].y
= gdata
.TopGraph
;
505 gdImageFilledPolygon(gdata
.im
, points
, 4, gdata
.gray
);
507 // depth of the bottom X axis
508 points
[0].x
= gdata
.LeftGraph
;
509 points
[0].y
= gdata
.BottomGraph
;
510 points
[1].x
= gdata
.LeftGraph
-10;
511 points
[1].y
= gdata
.BottomDepth
;
512 points
[2].x
= gdata
.RightGraph
-10;
513 points
[2].y
= gdata
.BottomDepth
;
514 points
[3].x
= gdata
.RightGraph
;
515 points
[3].y
= gdata
.BottomGraph
;
516 gdImageFilledPolygon(gdata
.im
, points
, 4, gdata
.gray
);
518 // vertical exterior line of the depth
519 gdImageLine(gdata
.im
, LeftMargin
-10, TopMargin
+5, LeftMargin
-10, gdata
.BottomDepth
+ZTickLength
, gdata
.black
);
520 // horizontal exterior line of the depth
521 gdImageLine(gdata
.im
, LeftMargin
-10-ZTickLength
, gdata
.BottomDepth
, gdata
.RightGraph
-10, gdata
.BottomDepth
, gdata
.black
);
522 // diagonal line between the two depths
523 gdImageLine(gdata
.im
, LeftMargin
-10, gdata
.BottomDepth
, LeftMargin
, gdata
.BottomGraph
, gdata
.black
);
524 // vertical left line of the graph
525 gdImageLine(gdata
.im
, LeftMargin
, gdata
.BottomGraph
, LeftMargin
, gdata
.TopGraph
, gdata
.black
);
526 // horizontal bottom line of the graph
527 gdImageLine(gdata
.im
, LeftMargin
, gdata
.BottomGraph
, gdata
.RightGraph
, gdata
.BottomGraph
, gdata
.black
);
528 // vertical right line of the graph
529 gdImageLine(gdata
.im
, gdata
.RightGraph
, gdata
.TopGraph
, gdata
.RightGraph
, gdata
.BottomGraph
, gdata
.black
);
530 // diagonal line to close the right of the bottom depth
531 gdImageLine(gdata
.im
, gdata
.RightGraph
-10, gdata
.BottomDepth
, gdata
.RightGraph
, gdata
.BottomGraph
, gdata
.black
);
534 greport_draw_yaxis(pdata
,&gdata
);
536 // X axis ticks and labels
537 for(y
=1; y
<=pdata
->npoints
; y
++) {
538 x
=gdata
.LeftGraph
-10+(int)((double)y
*gdata
.XScale
+0.5);
539 gdImageLine(gdata
.im
, x
, gdata
.BottomDepth
, x
, gdata
.BottomDepth
+TickLength
, gdata
.dimgray
);
541 Sarg_gdImageStringFT(&gdata
,gdata
.dimgray
,GraphFont
,7,0.0,x
,gdata
.BottomDepth
+TickLength
+1,s
,TRP_TopCenter
);
545 local
= localtime(&t
);
547 strftime(ftime
, sizeof(ftime
), "%b/%d/%Y %H:%M", local
);
549 strftime(ftime
, sizeof(ftime
), "%d/%b/%Y-%H:%M", local
);
552 Sarg_gdImageStringFT(&gdata
,gdata
.darkblue
,GraphFont
,7,0.0,ImgXSize
-10,ImgYSize
-10,ftime
,TRP_BottomRight
);
553 if(ShowSargInfo
) Sarg_gdImageStringFT(&gdata
,gdata
.darkblue
,GraphFont
,10,0.0,x
,15,_("SARG, "),TRP_BottomRight
);
554 Sarg_gdImageStringFT(&gdata
,gdata
.darkblue
,GraphFont
,10,0.0,x
,15,Title
,TRP_BottomLeft
);
555 sprintf(warea
,_("Period: %s"),period
.text
);
556 Sarg_gdImageStringFT(&gdata
,gdata
.darkblue
,GraphFont
,9,0.0,x
,27,warea
,TRP_BottomLeft
);
557 sprintf(warea
,_("User: %s"),uinfo
->label
);
558 Sarg_gdImageStringFT(&gdata
,gdata
.darkblue
,GraphFont
,9,0.0,x
,38,warea
,TRP_BottomLeft
);
560 Sarg_gdImageStringFT(&gdata
,gdata
.black
,GraphFont
,10,3.141592/2,15,ImgYSize
/2,pdata
->YLabel
,TRP_CenterLeft
);
561 Sarg_gdImageStringFT(&gdata
,gdata
.black
,GraphFont
,10,0.0,ImgXSize
/2,ImgYSize
-20,pdata
->XLabel
,TRP_BottomCenter
);
563 logpmin
=(pdata
->ytype
==PTG_LogBin
&& pdata
->ymin
>0.) ? log(pdata
->ymin
) : 0.;
564 for (day
=0 ; day
<pdata
->npoints
; day
++) {
565 if (pdata
->datapoints
[day
]>0) {
566 x1
=gdata
.LeftGraph
-10+(int)((double)(day
+1)*gdata
.XScale
+0.5);
567 switch (pdata
->ytype
)
570 yval
=(double)pdata
->datapoints
[day
];
571 if (yval
<pdata
->ymin
)
573 else if (yval
>pdata
->ymax
)
577 greport_formatbin(pdata
->datapoints
[day
],1,blabel
,sizeof(blabel
));
580 yval
=(double)pdata
->datapoints
[day
];
581 if (yval
<=pdata
->ymin
)
583 else if (yval
>pdata
->ymax
)
584 yval
=log(pdata
->ymax
)-logpmin
;
586 yval
=log(yval
)-logpmin
;
587 greport_formatbin(pdata
->datapoints
[day
],1,blabel
,sizeof(blabel
));
593 yval
=(double)pdata
->datapoints
[day
];
594 if (yval
<pdata
->ymin
)
596 else if (yval
>pdata
->ymax
)
600 t
=(int)(pdata
->datapoints
[day
]/60000.);
601 snprintf(blabel
,sizeof(blabel
),"%d:%02d",t
/60,t
%60);
608 if (yval
>=0.) bar(&gdata
,x1
,yval
,blabel
);
612 if (snprintf(graph
,sizeof(graph
),"%s/%s/%s",outdirname
,uinfo
->filename
,pdata
->pngfile
)>=sizeof(graph
)) {
613 /* TRANSLATORS: The message is followed by the path that is too long. */
614 debuga(__FILE__
,__LINE__
,_("User name too long to manufacture file name "));
615 debuga_more("%s/%s/%s\n",outdirname
,uinfo
->filename
,pdata
->pngfile
);
618 if((pngout
=fopen(graph
,"wb"))==NULL
) {
619 debuga(__FILE__
,__LINE__
,_("Cannot open file \"%s\": %s\n"),graph
,strerror(errno
));
622 gdImagePng(gdata
.im
, pngout
);
623 if (fclose(pngout
)==EOF
) {
624 debuga(__FILE__
,__LINE__
,_("Write error in \"%s\": %s\n"),graph
,strerror(errno
));
626 gdImageDestroy(gdata
.im
);
628 if (gdata
.string
) free(gdata
.string
);
633 void greport_prepare(void)
637 if (debugz
>=LogLevel_Process
)
638 debugaz(__FILE__
,__LINE__
,_("Graphs disabled as requested in %s\n"),ConfigFile
);
641 if (GraphFont
[0]=='\0') {
642 if (debugz
>=LogLevel_Process
)
643 debugaz(__FILE__
,__LINE__
,_("Graphs disabled as no font names were provided in %s\n"),ConfigFile
);
647 if(access(GraphFont
, R_OK
) != 0) {
648 debuga(__FILE__
,__LINE__
,_("Font name %s not found\n"),GraphFont
);
653 localtoutf
= iconv_open ("UTF-8", CharSet
);
654 if (localtoutf
==(iconv_t
)-1) {
655 debuga(__FILE__
,__LINE__
,_("iconv cannot convert from %s to UTF-8: %s\n"),CharSet
,strerror(errno
));
662 void greport_day(const struct userinfostruct
*uinfo
)
666 char wdirname
[MAXLEN
];
672 long long int bytespoints
[31];
673 long long int elappoints
[31];
674 struct getwordstruct gwarea
;
675 struct PlotStruct pdata
;
677 if (datetimeby
==0) return;
678 if (!Graphs
|| GraphFont
[0]=='\0') return;
679 if (snprintf(wdirname
,sizeof(wdirname
),"%s/%s.day",tmp
,uinfo
->filename
)>=sizeof(wdirname
)) {
680 debuga(__FILE__
,__LINE__
,_("User name too long to manufacture file name "));
681 debuga_more("%s/%s.day\n",tmp
,uinfo
->filename
);
684 if(access(wdirname
, R_OK
) != 0) {
688 if((fp_in
=fopen(wdirname
,"r"))==NULL
) {
689 debuga(__FILE__
,__LINE__
,_("Cannot open file \"%s\": %s\n"),wdirname
,strerror(errno
));
693 memset(bytespoints
,0,sizeof(bytespoints
));
694 memset(elappoints
,0,sizeof(elappoints
));
695 while(fgets(buf
,sizeof(buf
),fp_in
)!=NULL
) {
697 getword_start(&gwarea
,buf
);
698 if (getword_atoll(&llday
,&gwarea
,'/')<0) {
699 debuga(__FILE__
,__LINE__
,_("Invalid date in file \"%s\"\n"),wdirname
);
703 if (day
<1 || day
>31) continue;
704 if (getword_skip(20,&gwarea
,'\t')<0 || getword_skip(20,&gwarea
,'\t')<0) {
705 debuga(__FILE__
,__LINE__
,_("Invalid entry in file \"%s\"\n"),wdirname
);
708 if ((datetimeby
& DATETIME_BYTE
)!=0) {
709 if (getword_atoll(&bytes
,&gwarea
,'\t')<0) {
710 debuga(__FILE__
,__LINE__
,_("Invalid number of bytes in file \"%s\"\n"),wdirname
);
713 bytespoints
[day
-1]+=bytes
;
715 if ((datetimeby
& DATETIME_ELAP
)!=0) {
716 if (getword_atoll(&elap
,&gwarea
,'\0')<0) {
717 debuga(__FILE__
,__LINE__
,_("Invalid elapsed time in file \"%s\"\n"),wdirname
);
720 elappoints
[day
-1]+=elap
;
723 if (fclose(fp_in
)==EOF
) {
724 debuga(__FILE__
,__LINE__
,_("Read error in \"%s\": %s\n"),wdirname
,strerror(errno
));
728 if (snprintf(wdirname
,sizeof(wdirname
),"%s/%s/graph.html",outdirname
,uinfo
->filename
)>=sizeof(wdirname
)) {
729 debuga(__FILE__
,__LINE__
,_("User name too long to manufacture file name "));
730 debuga_more("%s/%s/%s\n",outdirname
,uinfo
->filename
,"graph.html");
733 if ((fp_ou
=fopen(wdirname
,"wt"))==NULL
) {
734 debuga(__FILE__
,__LINE__
,_("Cannot open file \"%s\": %s\n"),wdirname
,strerror(errno
));
737 write_html_head(fp_ou
,(IndexTree
== INDEX_TREE_DATE
) ? 4 : 2,_("Graph report"),HTML_JS_NONE
);
739 fputs("<table class=\"report\" cellpadding=\"0\" cellspacing=\"2\">\n", fp_ou
);
740 if((datetimeby
& DATETIME_BYTE
)!=0) {
741 memset(&pdata
,0,sizeof(pdata
));
742 pdata
.datapoints
=bytespoints
;
744 pdata
.XLabel
=_("DAYS");
745 pdata
.ymin
=50LL*1000LL;
746 pdata
.ymax
=5LL*1000LL*1000LL*1000LL;
747 pdata
.ytype
=PTG_LogBin
;
748 pdata
.YLabel
=_("BYTES");
749 pdata
.pngfile
="graph_day_byte.png";
750 greport_plot(uinfo
,&pdata
);
751 fprintf(fp_ou
,"<tr><td><img src=\"%s\" alt=\"B\"></td></tr>\n",pdata
.pngfile
);
753 if((datetimeby
& DATETIME_ELAP
)!=0) {
754 memset(&pdata
,0,sizeof(pdata
));
755 pdata
.datapoints
=elappoints
;
757 pdata
.XLabel
=_("DAYS");
760 pdata
.ytype
=PTG_Time
;
761 pdata
.YLabel
=_("ELAPSED TIME");
762 pdata
.pngfile
="graph_day_elap.png";
763 greport_plot(uinfo
,&pdata
);
764 fprintf(fp_ou
,"<tr><td><img src=\"%s\" alt=\"E\"></td></tr>\n",pdata
.pngfile
);
766 fputs("</table>\n",fp_ou
);
768 write_html_trailer(fp_ou
);
769 if (fclose(fp_ou
)==EOF
) {
770 debuga(__FILE__
,__LINE__
,_("Write error in \"%s\": %s\n"),wdirname
,strerror(errno
));
778 void greport_cleanup(void)
781 gdFontCacheShutdown();
784 if (localtoutf
!=(iconv_t
)-1)
785 iconv_close (localtoutf
);