X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=grepday.c;h=99ba095192dafd57253463c6737f695a8f3ec293;hb=ffc9b006b8358644c054c5e4c2929791efec7475;hp=0482dcfee860e129e3a6f0dacbfe08a96f2d4e91;hpb=e43854ef606dd87414bfd19487c8f0288ed8d2aa;p=thirdparty%2Fsarg.git diff --git a/grepday.c b/grepday.c index 0482dcf..99ba095 100644 --- a/grepday.c +++ b/grepday.c @@ -1,6 +1,6 @@ /* * SARG Squid Analysis Report Generator http://sarg.sourceforge.net - * 1998, 2010 + * 1998, 2015 * * SARG donations: * please look at http://sarg.sourceforge.net/donations.php @@ -36,583 +36,753 @@ struct GraphDataStruct { -#ifdef USE_ICONV - iconv_t localtoutf; -#endif - int lavender; - int darkblue; - int dimgray; - int goldenrod; - int goldenrod2; - int gray; - int silver; - int black; - int color1; - int color2; - int color3; - gdImage *im; - char *string; - size_t string_size; + int lavender; + int darkblue; + int dimgray; + int goldenrod; + int goldenrod2; + int gray; + int silver; + int black; + //! The color of the top side of a graph bar. + int color1; + //! The color of the right side of a graph bar. + int color2; + //! The color of the front side of a graph bar. + int color3; + //! The libgd image we are drawing on. + gdImage *im; + //! An allocated buffer to convert the string into UTF-8. + char *string; + //! The number of bytes allocated for the string buffer. + size_t string_size; + //! The bottom border of the graph. + int BottomGraph; + //! The top border of the graph. + int TopGraph; + //! The left border of the graph. + int LeftGraph; + //! The right border of the graph. + int RightGraph; + //! The height at which the bottom depth border of the graph extends. + int BottomDepth; + //! The distance between two ticks on the horizontal axis. + double XScale; + //! The distance between two ticks on the vertical axis. + double YScale; + //! The exterior length of a tick on the scales. + int TickLength; + //! The distance, in pixels, between two ticks along the Y axis. + int YTickSpace; +}; + +enum PlotType +{ + PTG_LinBin, + PTG_LogBin, + PTG_Time, +}; + +struct PlotStruct +{ + //! The data points to plot. + long long int *datapoints; + //! The number of points to plot. + int npoints; + //! The minimum data to plot along the Y axis. + long long int ymin; + //! The maximum data to plot along the Y axis. + long long int ymax; + //! The type of Y axis to draw. + enum PlotType ytype; + //! The label to write on the X axis. + const char *XLabel; + //! The label to write on the Y axis. + const char *YLabel; + //! The name of the output PNG file. + const char *pngfile; }; enum TextRefPos { - TRP_TopLeft, - TRP_TopCenter, - TRP_TopRight, - TRP_BottomLeft, - TRP_BottomCenter, - TRP_BottomRight, - TRP_CenterLeft, - TRP_Center, - TRP_CenterRight, + TRP_TopLeft, + TRP_TopCenter, + TRP_TopRight, + TRP_BottomLeft, + TRP_BottomCenter, + TRP_BottomRight, + TRP_CenterLeft, + TRP_Center, + TRP_CenterRight, }; -static char * Sarg_gdImageStringFT (struct GraphDataStruct *gdata, int fg, char *fontlist, - double ptsize, double angle, int x, int y, char *string,enum TextRefPos RefPos) +#ifdef USE_ICONV +//! The iconv object to convert the text from the locale character set to UTF-8. +iconv_t localtoutf=(iconv_t)-1; +#endif + +static void Sarg_gdImageStringFT (struct GraphDataStruct *gdata, int fg, char *fontlist, + double ptsize, double angle, int x, int y, const char *string,enum TextRefPos RefPos) { - char *sstring, *retval; - int brect[8]; - int minx,miny,maxx,maxy; - int i; + char *sstring; + char *retval; + int brect[8]; + int minx,miny,maxx,maxy; + int i; #ifdef USE_ICONV - if (gdata->localtoutf!=(iconv_t)-1) { - char *str; - char *sstr; - size_t slen, sslen; - - slen = strlen(string) + 1; // We must include string termination character - sslen = slen * 2; // We assume that UTF8 maximum 2 times large than local - if (sslen>gdata->string_size) { - sstring = (char *)realloc(gdata->string,sslen); - if (!sstring) { - debuga(_("realloc error (%zu bytes required)\n"),sslen); - exit(EXIT_FAILURE); - } - gdata->string=sstring; - gdata->string_size=sslen; - } else { - sstring=gdata->string; - sslen=gdata->string_size; - } - - str = string; - sstr = sstring; - if (iconv (gdata->localtoutf, (ICONV_CONST char **)&str, &slen, &sstr, &sslen)==-1) { - debuga(_("(grepday) iconv failed to convert string \"%s\" from %s to UTF-8 - %s\n"),string,CharSet,strerror(errno)); - sstring=string; //show something sensible on the graph - } - } else { - sstring=string; //show something sensible on the graph - } + if (localtoutf!=(iconv_t)-1) { + const char *str; + char *sstr; + size_t slen, sslen; + + slen = strlen(string) + 1; // We must include string termination character + sslen = slen * 3; // We assume that the UTF8 string will not be bigger than 3 times the original size. + if (sslen>gdata->string_size) { + sstring = (char *)realloc(gdata->string,sslen); + if (!sstring) { + debuga(__FILE__,__LINE__,_("realloc error (%"PRIu64" bytes required)\n"),(uint64_t)sslen); + exit(EXIT_FAILURE); + } + gdata->string=(char *)sstring; + gdata->string_size=sslen; + } else { + sstring=gdata->string; + sslen=gdata->string_size; + } + + str = string; + sstr = sstring; + if (iconv (localtoutf, (ICONV_CONST char **)&str, &slen, &sstr, &sslen)==-1) { + debuga(__FILE__,__LINE__,_("iconv failed to convert string \"%s\" from %s to UTF-8: %s\n"),string,CharSet,strerror(errno)); + sstring=(char *)string; //show something sensible on the graph + } + } else { + sstring=(char *)string; //show something sensible on the graph + } #else - sstring=string; + sstring=(char *)string; #endif - if (RefPos!=TRP_BottomLeft) { - retval = gdImageStringFTEx (NULL, brect, fg, fontlist, ptsize, angle, 0, 0, sstring, gdFTEX_Unicode); - if (retval) { - debuga(_("libgd failed to calculate the bounding box of the text \"%s\": %s\n"),sstring,retval); - exit(EXIT_FAILURE); - } - /* - From libgd documentation, brect contains this without taking into account the angle: - 0 lower left corner, X position - 1 lower left corner, Y position - 2 lower right corner, X position - 3 lower right corner, Y position - 4 upper right corner, X position - 5 upper right corner, Y position - 6 upper left corner, X position - 7 upper left corner, Y position - */ - minx=maxx=brect[0]; - miny=maxy=brect[1]; - for (i=2 ; i<7 ; i+=2) { - if (minx>brect[i]) minx=brect[i]; - if (maxxbrect[i+1]) miny=brect[i+1]; - if (maxyim, brect, fg, fontlist, ptsize, angle, x, y, sstring, gdFTEX_Unicode); - if (retval) { - debuga(_("libgd failed to render the text \"%s\": %s\n"),sstring,retval); - exit(EXIT_FAILURE); - } - - return retval; + if (RefPos!=TRP_BottomLeft) { + retval = gdImageStringFTEx (NULL, brect, fg, fontlist, ptsize, angle, 0, 0, sstring, gdFTEX_Unicode); + if (retval) { + debuga(__FILE__,__LINE__,_("libgd failed to calculate the bounding box of the text \"%s\": %s\n"),sstring,retval); + exit(EXIT_FAILURE); + } + /* + From libgd documentation, brect contains this without taking into account the angle: + 0 lower left corner, X position + 1 lower left corner, Y position + 2 lower right corner, X position + 3 lower right corner, Y position + 4 upper right corner, X position + 5 upper right corner, Y position + 6 upper left corner, X position + 7 upper left corner, Y position + */ + minx=maxx=brect[0]; + miny=maxy=brect[1]; + for (i=2 ; i<7 ; i+=2) { + if (minx>brect[i]) minx=brect[i]; + if (maxxbrect[i+1]) miny=brect[i+1]; + if (maxyim, brect, fg, fontlist, ptsize, angle, x, y, sstring, gdFTEX_Unicode); + if (retval) { + debuga(__FILE__,__LINE__,_("libgd failed to render the text \"%s\": %s\n"),sstring,retval); + exit(EXIT_FAILURE); + } +} + +static void bar(struct GraphDataStruct *gdata,int x1,double y,const char *label) +{ + gdPoint points[4]; + int val=0; + int width2; + + val=gdata->BottomGraph+5-(int)(y*gdata->YScale+0.5); + width2=(int)(gdata->XScale/4.); + + // front side of the bar + if (valBottomDepth) + gdImageFilledRectangle(gdata->im, x1-width2, val, x1+width2, gdata->BottomDepth, gdata->color3); + + // top side of the bar + points[0].x = x1-width2+5; + points[0].y = val-5; + points[1].x = x1-width2; + points[1].y = val; + points[2].x = x1+width2; + points[2].y = val; + points[3].x = x1+width2+5; + points[3].y = val-5; + gdImageFilledPolygon(gdata->im, points, 4, gdata->color1); + + gdImageLine(gdata->im, x1+2, val-2, x1+2, val-10, gdata->dimgray); + gdImageFilledRectangle(gdata->im, x1-8, val-20, x1+12, val-10, gdata->goldenrod); + gdImageRectangle(gdata->im, x1-8, val-20, x1+12, val-10, gdata->goldenrod2); + + Sarg_gdImageStringFT(gdata,gdata->black,GraphFont,6,0.0,x1+2,val-12,label,TRP_BottomCenter); + + // lateral side of the bar + if (valBottomDepth) { + points[0].x = x1+width2+5; + points[0].y = val-5; + points[1].x = x1+width2; + points[1].y = val; + points[2].x = x1+width2; + points[2].y = gdata->BottomDepth; + points[3].x = x1+width2+5; + points[3].y = gdata->BottomGraph; + gdImageFilledPolygon(gdata->im, points, 4, gdata->color2); + } + + return; } -static void bar(struct GraphDataStruct *gdata,int x1,long long int n) +static int greport_compute_yaxis(struct PlotStruct *pdata,struct GraphDataStruct *gdata) { - gdPoint points[4]; - int val=0, x; - long long int num; - - static const long long int limits[400]={0,500,1000,2000,3000,4000, - 5000,6000,7000,8000,9000,10000, - 20000,30000,40000,50000,70000,90000, - 110000,130000,150000,170000,190000,210000, - 230000,250000,280000,310000,340000,370000, - 400000,430000,450000,460000,490000,500000, - 550000,600000,650000,700000,750000,800000, - 850000,900000,950000,1000000,1100000,1200000, - 1300000,1400000,1500000,1600000,1700000,1800000, - 1900000,2000000,2100000,2200000,2300000,2400000, - 2500000,2600000,2700000,2800000,2900000,3000000, - 3100000,3200000,3300000,3400000,3500000,3600000, - 3700000,3800000,3900000,4000000,4100000,4200000, - 4300000,4400000,4500000,4600000,4700000,4800000, - 4900000,5000000,5100000,5200000,5300000,5400000, - 5500000,5600000,5700000,5800000,5900000,6000000, - 6100000,6200000,6300000,6400000,6500000,6600000, - 6700000,6800000,6900000,7000000,7100000,7200000, - 7300000,7400000,7500000,7600000,7700000,7800000, - 7900000,8000000,8100000,8200000,8300000,8400000, - 8500000,8600000,8700000,8800000,8900000,9000000, - 9100000,9200000,9300000,9400000,9500000,9600000, - 9700000,9800000,9900000,10000000,10500000,11000000, - 11500000,12000000,12500000,13000000,13500000,14000000, - 14500000,15000000,15500000,16000000,16500000,17000000, - 17500000,18000000,18500000,19000000,19500000,20000000, - 21000000,22000000,23000000,24000000,25000000,26000000, - 27000000,28000000,29000000,30000000,31000000,32000000, - 33000000,34000000,35000000,36000000,37000000,38000000, - 39000000,40000000,41000000,42000000,43000000,44000000, - 45000000,46000000,47000000,48000000,49000000,50000000, - 51000000,52000000,53000000,54000000,55000000,56000000, - 57000000,58000000,59000000,60000000,61000000,62000000, - 63000000,64000000,65000000,66000000,67000000,68000000, - 69000000,70000000,71000000,72000000,73000000,74000000, - 75000000,76000000,77000000,78000000,79000000,80000000, - 81000000,82000000,83000000,84000000,85000000,86000000, - 87000000,88000000,89000000,90000000,91000000,92000000, - 93000000,94000000,95000000,96000000,97000000,98000000, - 99000000,100000000,110000000,120000000,130000000,140000000, - 150000000,160000000,170000000,180000000,190000000,200000000, - 210000000,220000000,230000000,240000000,250000000,260000000, - 270000000,280000000,290000000,300000000,310000000,320000000, - 330000000,340000000,350000000,360000000,370000000,380000000, - 390000000,400000000,410000000,420000000,430000000,440000000, - 450000000,460000000,470000000,480000000,490000000,500000000, - 510000000,520000000,530000000,540000000,550000000,560000000, - 570000000,580000000,590000000,600000000,610000000,620000000, - 630000000,640000000,650000000,660000000,670000000,680000000, - 690000000,700000000,710000000,720000000,730000000,740000000, - 750000000,760000000,770000000,780000000,790000000,800000000, - 810000000,820000000,830000000,840000000,850000000,860000000, - 870000000,880000000,890000000,900000000,910000000,920000000, - 930000000,940000000,950000000,960000000,970000000,980000000, - 990000000LL,1000000000LL,1100000000LL,1200000000LL,1300000000LL,1400000000LL, - 1500000000LL,1600000000LL,1700000000LL,1800000000LL,1900000000LL,2000000000LL, - 2100000000LL,2200000000LL,2300000000LL,2400000000LL,2500000000LL,2600000000LL, - 2700000000LL,2800000000LL,2900000000LL,3000000000LL,3100000000LL,3200000000LL, - 3300000000LL,3400000000LL,3500000000LL,3600000000LL,3700000000LL,3800000000LL, - 3900000000LL,4000000000LL,4100000000LL,4200000000LL,4300000000LL,4400000000LL, - 4500000000LL,4600000000LL,4700000000LL,4800000000LL,4900000000LL,5000000000LL}; - - num = n; - val = 55; - for(x=0; x<=366; x++) { - if(limits[x] >= num) { - val = 425 - x; - break; - } - } - - gdImageFilledRectangle(gdata->im, x1, val, x1+11, 425, gdata->color3); - - points[0].x = x1+7; - points[0].y = val-5; - points[1].x = x1; - points[1].y = val; - points[2].x = x1+11; - points[2].y = val; - points[3].x = x1+17; - points[3].y = val-5; - gdImageFilledPolygon(gdata->im, points, 4, gdata->color1); - - gdImageLine(gdata->im, x1+8, val-2, x1+8, val-10, gdata->dimgray); - gdImageFilledRectangle(gdata->im, x1-2, val-20, x1+18, val-10, gdata->goldenrod); - gdImageRectangle(gdata->im, x1-2, val-20, x1+18, val-10, gdata->goldenrod2); - - Sarg_gdImageStringFT(gdata,gdata->black,GraphFont,6,0.0,x1+8,val-12,fixnum(num,0),TRP_BottomCenter); - - points[0].x = x1+17; - points[0].y = val-5; - points[1].x = x1+11; - points[1].y = val; - points[2].x = x1+11; - points[2].y = 426; - points[3].x = x1+17; - points[3].y = 420; - gdImageFilledPolygon(gdata->im, points, 4, gdata->color2); - - return; + double symin,symax; + double range; + double yscale; + + if (pdata->ymin<0.) { + debuga(__FILE__,__LINE__,_("Minimum for Y scale of the graph is out of range: %"PRId64"\n"),(int64_t)pdata->ymin); + return(-1); + } + if (pdata->ymax<=0.) { + debuga(__FILE__,__LINE__,_("Maximum for Y scale of the graph is out of range: %"PRId64"\n"),(int64_t)pdata->ymax); + return(-1); + } + + switch(pdata->ytype) + { + case PTG_LinBin: + symin=(double)pdata->ymin; + symax=(double)pdata->ymax; + break; + + case PTG_LogBin: + if (pdata->ymin>0.) + symin=log(pdata->ymin); + else + symin=0.; + symax=log(pdata->ymax); + break; + + case PTG_Time: + symin=(double)pdata->ymin; + symax=(double)pdata->ymax; + break; + + default: + debuga(__FILE__,__LINE__,_("Unknown type %d for Y axis scale\n"),pdata->ytype); + return(-1); + } + gdata->YTickSpace=10; + + range=symax-symin; + yscale=(double)(gdata->BottomGraph-gdata->TopGraph)/range; + gdata->YScale=yscale; + return(0); } + +static void greport_formatbin(double yval,int maxdigits,char *string,int slen) +{ + int len; + char schar[]={'\0','k','M','G','T','P'}; + int scount; + int i; + int ndigits; + + for (scount=0 ; scount=1000. ; scount++) + yval/=1000.; + if (yval<2.) + ndigits=2; + else if (yval<3.) + ndigits=1; + else + ndigits=0; + if (ndigits>maxdigits) ndigits=maxdigits; + len=snprintf(string,slen,"%.*f",ndigits,(float)yval); + if (UseComma) + for (i=0 ; iBottomGraph; + yt=gdata->BottomDepth-gdata->BottomGraph; + xexterior=gdata->LeftGraph-10; + xinterior=gdata->LeftGraph; + xtick=gdata->LeftGraph-10-gdata->TickLength; + for(y=y0-gdata->YTickSpace ; y>=gdata->TopGraph ; y-=gdata->YTickSpace) { + gdImageLine(gdata->im, xtick, y+yt, xexterior, y+yt, gdata->dimgray); + gdImageLine(gdata->im, xexterior, y+yt, xinterior, y, gdata->dimgray); + gdImageLine(gdata->im, xinterior, y, gdata->RightGraph, y, gdata->dimgray); + switch (pdata->ytype) + { + case PTG_LinBin: + yval=(double)(y0-y)/gdata->YScale+(double)pdata->ymin; + greport_formatbin(yval,2,YLabel,sizeof(YLabel)); + break; + + case PTG_LogBin: + yval=exp((double)(y0-y)/gdata->YScale+log(pdata->ymin)); + greport_formatbin(yval,2,YLabel,sizeof(YLabel)); + break; + + case PTG_Time: + { + int t; + + yval=(double)(y0-y)/gdata->YScale+(double)pdata->ymin; + t=(int)(yval/60000.+0.5); + snprintf(YLabel,sizeof(YLabel),"%02d:%02d",t/60,t%60); + break; + } + } + Sarg_gdImageStringFT(gdata,gdata->dimgray,GraphFont,7,0.0,xtick,y+yt,YLabel,TRP_CenterRight); + } +} + +static void greport_plot(const struct userinfostruct *uinfo,struct PlotStruct *pdata) +{ + FILE *pngout; + int x, y; + int day; + int x1; + char graph[MAXLEN]; + char s[15]; + char ftime[128]; + time_t t; + struct tm *local; + gdPoint points[4]; + struct GraphDataStruct gdata; + const int ImgXSize=720; + const int ImgYSize=480; + const int LeftMargin=60; + const int RightMargin=20; + const int TopMargin=60; + const int BottomMargin=60; + const int TickLength=3; + const int ZTickLength=5; + double yval; + char blabel[50]; + double logpmin; + + memset(&gdata,0,sizeof(gdata)); + + gdata.im = gdImageCreate(ImgXSize, ImgYSize); + gdata.BottomGraph=ImgYSize-BottomMargin; + gdata.LeftGraph=LeftMargin; + gdata.RightGraph=ImgXSize-RightMargin; + gdata.TopGraph=TopMargin; + gdata.BottomDepth=gdata.BottomGraph+5; + gdata.XScale=(double)(gdata.RightGraph-gdata.LeftGraph)/(pdata->npoints+1); + if (greport_compute_yaxis(pdata,&gdata)<0) return; + gdata.TickLength=TickLength; + + // first allocated color is the background + gdata.lavender = gdImageColorAllocate(gdata.im, 230, 230, 250); + gdata.gray = gdImageColorAllocate(gdata.im, 192, 192, 192); + gdata.silver = gdImageColorAllocate(gdata.im, 211, 211, 211); + gdata.black = gdImageColorAllocate(gdata.im, 0, 0, 0); + gdata.dimgray = gdImageColorAllocate(gdata.im, 105, 105, 105); + gdata.darkblue = gdImageColorAllocate(gdata.im, 0, 0, 139); + gdata.goldenrod = gdImageColorAllocate(gdata.im, 234, 234, 174); + gdata.goldenrod2 = gdImageColorAllocate(gdata.im, 207, 181, 59); + + if(strcmp(GraphDaysBytesBarColor,"orange") == 0) { + gdata.color1 = gdImageColorAllocate(gdata.im, 255, 233, 142); + gdata.color2 = gdImageColorAllocate(gdata.im, 220, 163, 72); + gdata.color3 = gdImageColorAllocate(gdata.im, 255, 198, 107); + } + else if(strcmp(GraphDaysBytesBarColor,"blue") == 0) { + gdata.color1 = gdImageColorAllocate(gdata.im, 62, 80, 167); + gdata.color2 = gdImageColorAllocate(gdata.im, 40, 51, 101); + gdata.color3 = gdImageColorAllocate(gdata.im, 57, 73, 150); + } + else if(strcmp(GraphDaysBytesBarColor,"green") == 0) { + gdata.color1 = gdImageColorAllocate(gdata.im,120,166,129); + gdata.color2 = gdImageColorAllocate(gdata.im,84,113,82); + gdata.color3 = gdImageColorAllocate(gdata.im,158,223,167); + } + else if(strcmp(GraphDaysBytesBarColor,"yellow") == 0) { + gdata.color1 = gdImageColorAllocate(gdata.im,185,185,10); + gdata.color2 = gdImageColorAllocate(gdata.im,111,111,10); + gdata.color3 = gdImageColorAllocate(gdata.im,166,166,10); + } + else if(strcmp(GraphDaysBytesBarColor,"brown") == 0) { + gdata.color1 = gdImageColorAllocate(gdata.im,97,45,27); + gdata.color2 = gdImageColorAllocate(gdata.im,60,30,20); + gdata.color3 = gdImageColorAllocate(gdata.im,88,41,26); + } + else if(strcmp(GraphDaysBytesBarColor,"red") == 0){ + gdata.color1 = gdImageColorAllocate(gdata.im,185,10,10); + gdata.color2 = gdImageColorAllocate(gdata.im,111,10,10); + gdata.color3 = gdImageColorAllocate(gdata.im,166,10,10); + } else { + debuga(__FILE__,__LINE__,_("Unknown color \"%s\" requested for the graph. Using orange instead\n"),GraphDaysBytesBarColor); + gdata.color1 = gdImageColorAllocate(gdata.im, 255, 233, 142); + gdata.color2 = gdImageColorAllocate(gdata.im, 220, 163, 72); + gdata.color3 = gdImageColorAllocate(gdata.im, 255, 198, 107); + } + + // rectangle around the image + gdImageRectangle(gdata.im, 0, 0, ImgXSize-1, ImgYSize-1, gdata.dimgray); + // backtround of the graph + gdImageFilledRectangle(gdata.im, LeftMargin, gdata.TopGraph, gdata.RightGraph, gdata.BottomGraph, gdata.silver); + + // depth of the left Y axis + points[0].x = gdata.LeftGraph-10; + points[0].y = gdata.TopGraph+5; + points[1].x = gdata.LeftGraph-10; + points[1].y = gdata.BottomDepth; + points[2].x = gdata.LeftGraph; + points[2].y = gdata.BottomGraph; + points[3].x = gdata.LeftGraph; + points[3].y = gdata.TopGraph; + gdImageFilledPolygon(gdata.im, points, 4, gdata.gray); + + // depth of the bottom X axis + points[0].x = gdata.LeftGraph; + points[0].y = gdata.BottomGraph; + points[1].x = gdata.LeftGraph-10; + points[1].y = gdata.BottomDepth; + points[2].x = gdata.RightGraph-10; + points[2].y = gdata.BottomDepth; + points[3].x = gdata.RightGraph; + points[3].y = gdata.BottomGraph; + gdImageFilledPolygon(gdata.im, points, 4, gdata.gray); + + // vertical exterior line of the depth + gdImageLine(gdata.im, LeftMargin-10, TopMargin+5, LeftMargin-10, gdata.BottomDepth+ZTickLength, gdata.black); + // horizontal exterior line of the depth + gdImageLine(gdata.im, LeftMargin-10-ZTickLength, gdata.BottomDepth, gdata.RightGraph-10, gdata.BottomDepth, gdata.black); + // diagonal line between the two depths + gdImageLine(gdata.im, LeftMargin-10, gdata.BottomDepth, LeftMargin, gdata.BottomGraph, gdata.black); + // vertical left line of the graph + gdImageLine(gdata.im, LeftMargin, gdata.BottomGraph, LeftMargin, gdata.TopGraph, gdata.black); + // horizontal bottom line of the graph + gdImageLine(gdata.im, LeftMargin, gdata.BottomGraph, gdata.RightGraph, gdata.BottomGraph, gdata.black); + // vertical right line of the graph + gdImageLine(gdata.im, gdata.RightGraph, gdata.TopGraph, gdata.RightGraph, gdata.BottomGraph, gdata.black); + // diagonal line to close the right of the bottom depth + gdImageLine(gdata.im, gdata.RightGraph-10, gdata.BottomDepth, gdata.RightGraph, gdata.BottomGraph, gdata.black); + + // Y axis ticks + greport_draw_yaxis(pdata,&gdata); + + // X axis ticks and labels + for(y=1; y<=pdata->npoints; y++) { + x=gdata.LeftGraph-10+(int)((double)y*gdata.XScale+0.5); + gdImageLine(gdata.im, x, gdata.BottomDepth, x, gdata.BottomDepth+TickLength, gdata.dimgray); + sprintf(s,"%02d",y); + Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,x,gdata.BottomDepth+TickLength+1,s,TRP_TopCenter); + } + + t = time(NULL); + local = localtime(&t); + if (df=='u') + strftime(ftime, sizeof(ftime), "%b/%d/%Y %H:%M", local); + if (df=='e') + strftime(ftime, sizeof(ftime), "%d/%b/%Y-%H:%M", local); + + x=ImgXSize*5/12; + Sarg_gdImageStringFT(&gdata,gdata.darkblue,GraphFont,7,0.0,ImgXSize-10,ImgYSize-10,ftime,TRP_BottomRight); + if(ShowSargInfo) Sarg_gdImageStringFT(&gdata,gdata.darkblue,GraphFont,10,0.0,x,15,_("SARG, "),TRP_BottomRight); + Sarg_gdImageStringFT(&gdata,gdata.darkblue,GraphFont,10,0.0,x,15,Title,TRP_BottomLeft); + sprintf(warea,_("Period: %s"),period.text); + Sarg_gdImageStringFT(&gdata,gdata.darkblue,GraphFont,9,0.0,x,27,warea,TRP_BottomLeft); + sprintf(warea,_("User: %s"),uinfo->label); + Sarg_gdImageStringFT(&gdata,gdata.darkblue,GraphFont,9,0.0,x,38,warea,TRP_BottomLeft); + + Sarg_gdImageStringFT(&gdata,gdata.black,GraphFont,10,3.141592/2,15,ImgYSize/2,pdata->YLabel,TRP_CenterLeft); + Sarg_gdImageStringFT(&gdata,gdata.black,GraphFont,10,0.0,ImgXSize/2,ImgYSize-20,pdata->XLabel,TRP_BottomCenter); + + logpmin=(pdata->ytype==PTG_LogBin && pdata->ymin>0.) ? log(pdata->ymin) : 0.; + for (day=0 ; daynpoints ; day++) { + if (pdata->datapoints[day]>0) { + x1=gdata.LeftGraph-10+(int)((double)(day+1)*gdata.XScale+0.5); + switch (pdata->ytype) + { + case PTG_LinBin: + yval=(double)pdata->datapoints[day]; + if (yvalymin) + yval=0.; + else if (yval>pdata->ymax) + yval=pdata->ymax; + else + yval-=pdata->ymin; + greport_formatbin(pdata->datapoints[day],1,blabel,sizeof(blabel)); + break; + case PTG_LogBin: + yval=(double)pdata->datapoints[day]; + if (yval<=pdata->ymin) + yval=0.; + else if (yval>pdata->ymax) + yval=log(pdata->ymax)-logpmin; + else + yval=log(yval)-logpmin; + greport_formatbin(pdata->datapoints[day],1,blabel,sizeof(blabel)); + break; + case PTG_Time: + { + int t; + + yval=(double)pdata->datapoints[day]; + if (yvalymin) + yval=0.; + else if (yval>pdata->ymax) + yval=pdata->ymax; + else + yval-=pdata->ymin; + t=(int)(pdata->datapoints[day]/60000.); + snprintf(blabel,sizeof(blabel),"%d:%02d",t/60,t%60); + break; + } + default: + yval=-1.; + break; + } + if (yval>=0.) bar(&gdata,x1,yval,blabel); + } + } + + if (snprintf(graph,sizeof(graph),"%s/%s/%s",outdirname,uinfo->filename,pdata->pngfile)>=sizeof(graph)) { + /* TRANSLATORS: The message is followed by the path that is too long. */ + debuga(__FILE__,__LINE__,_("User name too long to manufacture file name ")); + debuga_more("%s/%s/%s\n",outdirname,uinfo->filename,pdata->pngfile); + exit(EXIT_FAILURE); + } + if((pngout=fopen(graph,"wb"))==NULL) { + debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),graph,strerror(errno)); + exit(EXIT_FAILURE); + } + gdImagePng(gdata.im, pngout); + if (fclose(pngout)==EOF) { + debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),graph,strerror(errno)); + } + gdImageDestroy(gdata.im); + + if (gdata.string) free(gdata.string); +} + #endif //HAVE_GD -void greport_day(const struct userinfostruct *uinfo) +void greport_prepare(void) { #ifdef HAVE_GD - FILE *fp_in, *pngout; - int x, y; - int x1; - char wdirname[MAXLEN]; - char graph[MAXLEN]; - char buf[MAXLEN]; - char csort[255]; - char s[15]; - char tmp5[MAXLEN]; - int oday=0; - int day=0; - long long int llday; - long long int bytes; - char ftime[128]; - long long int tot=0; - time_t t; - struct tm *local; - int cstatus; - long long datapoints[31]; - gdPoint points[4]; - struct getwordstruct gwarea; - struct GraphDataStruct gdata; - const int ImgXSize=720; - const int ImgYSize=480; - const int LeftMargin=60; - const int RightMargin=20; - const int TopMargin=60; - const int BottomMargin=60; - const int TickLength=3; - const int ZTickLength=5; - int BottomGraph; - int RightGraph; - - if (snprintf(wdirname,sizeof(wdirname),"%s/%s.day",tmp,uinfo->filename)>=sizeof(wdirname)) { - debuga(_("user name too long for %s/%s.day\n"),tmp,uinfo->filename); - exit(EXIT_FAILURE); - } - if(access(wdirname, R_OK) != 0) { - return; - } - if(!Graphs || GraphFont[0]=='\0') { - unlink(wdirname); - return; - } - - if (snprintf(tmp5,sizeof(tmp5),"%s/%s.graph",tmp,uinfo->filename)>=sizeof(tmp5)) { - debuga(_("user name too long for %s/%s.graph\n"),tmp,uinfo->filename); - exit(EXIT_FAILURE); - } - if(strcmp(DateFormat,"e") == 0) - sprintf(csort,"sort -t\"/\" -k 1,1 -o \"%s\" \"%s\"",tmp5,wdirname); - else - sprintf(csort,"sort -t\"/\" -k 2,2 -o \"%s\" \"%s\"",tmp5,wdirname); - - cstatus=system(csort); - if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) { - debuga(_("sort command return status %d\n"),WEXITSTATUS(cstatus)); - debuga(_("sort command: %s\n"),csort); - exit(EXIT_FAILURE); - } - - if((fp_in=fopen(tmp5,"r"))==NULL) { - debuga(_("(grepday) Cannot open log file %s\n"),tmp5); - exit(EXIT_FAILURE); - } - unlink(wdirname); - - memset(datapoints,0,sizeof(datapoints)); - oday=-1; - while(fgets(buf,sizeof(buf),fp_in)!=NULL) { - fixendofline(buf); - getword_start(&gwarea,buf); - if (getword_atoll(&llday,&gwarea,'/')<0) { - debuga(_("Maybe you have a broken record or garbage in your %s file\n"),tmp5); - exit(EXIT_FAILURE); - } - if(DateFormat[0]=='u') { - if (getword_atoll(&llday,&gwarea,'/')<0) { - debuga(_("Maybe you have a broken record or garbage in your %s file\n"),tmp5); - exit(EXIT_FAILURE); - } - } - day=(int)llday; - if (day<1 || day>31) continue; - if (getword_skip(20,&gwarea,'\t')<0 || getword_skip(20,&gwarea,'\t')<0 || getword_atoll(&bytes,&gwarea,'\t')<0) { - debuga(_("Maybe you have a broken record or garbage in your %s file\n"),tmp5); - exit(EXIT_FAILURE); - } - - if(oday!=day) { - if (oday>0) datapoints[oday-1]=tot; - oday=day; - tot=0; - } - tot+=bytes; - } - fclose(fp_in); - unlink(tmp5); - if (oday>0) datapoints[oday-1]=tot; - - if(access(GraphFont, R_OK) != 0) { - debuga(_("(grepday) Fontname %s not found\n"),GraphFont); - exit(EXIT_FAILURE); - } - memset(&gdata,0,sizeof(gdata)); + if (!Graphs) { + if (debugz>=LogLevel_Process) + debugaz(__FILE__,__LINE__,_("Graphs disabled as requested in %s\n"),ConfigFile); + return; + } + if (GraphFont[0]=='\0') { + if (debugz>=LogLevel_Process) + debugaz(__FILE__,__LINE__,_("Graphs disabled as no font names were provided in %s\n"),ConfigFile); + return; + } + + if(access(GraphFont, R_OK) != 0) { + debuga(__FILE__,__LINE__,_("Font name %s not found\n"),GraphFont); + exit(EXIT_FAILURE); + } #ifdef USE_ICONV - gdata.localtoutf = iconv_open ("UTF-8", CharSet); - if (gdata.localtoutf==(iconv_t)-1) { - debuga(_("(grepday) iconv cannot convert from %s to UTF-8 - %s\n"),CharSet,strerror(errno)); - } + localtoutf = iconv_open ("UTF-8", CharSet); + if (localtoutf==(iconv_t)-1) { + debuga(__FILE__,__LINE__,_("iconv cannot convert from %s to UTF-8: %s\n"),CharSet,strerror(errno)); + } #endif - gdata.im = gdImageCreate(ImgXSize, ImgYSize); - BottomGraph=ImgYSize-BottomMargin; - RightGraph=ImgXSize-RightMargin; - - // first allocated color is the background - gdata.lavender = gdImageColorAllocate(gdata.im, 230, 230, 250); - gdata.gray = gdImageColorAllocate(gdata.im, 192, 192, 192); - gdata.silver = gdImageColorAllocate(gdata.im, 211, 211, 211); - gdata.black = gdImageColorAllocate(gdata.im, 0, 0, 0); - gdata.dimgray = gdImageColorAllocate(gdata.im, 105, 105, 105); - gdata.darkblue = gdImageColorAllocate(gdata.im, 0, 0, 139); - gdata.goldenrod = gdImageColorAllocate(gdata.im, 234, 234, 174); - gdata.goldenrod2 = gdImageColorAllocate(gdata.im, 207, 181, 59); - - if(strcmp(GraphDaysBytesBarColor,"orange") == 0) { - gdata.color1 = gdImageColorAllocate(gdata.im, 255, 233, 142); - gdata.color2 = gdImageColorAllocate(gdata.im, 220, 163, 72); - gdata.color3 = gdImageColorAllocate(gdata.im, 255, 198, 107); - } - else if(strcmp(GraphDaysBytesBarColor,"blue") == 0) { - gdata.color1 = gdImageColorAllocate(gdata.im, 62, 80, 167); - gdata.color2 = gdImageColorAllocate(gdata.im, 40, 51, 101); - gdata.color3 = gdImageColorAllocate(gdata.im, 57, 73, 150); - } - else if(strcmp(GraphDaysBytesBarColor,"green") == 0) { - gdata.color1 = gdImageColorAllocate(gdata.im,120,166,129); - gdata.color2 = gdImageColorAllocate(gdata.im,84,113,82); - gdata.color3 = gdImageColorAllocate(gdata.im,158,223,167); - } - else if(strcmp(GraphDaysBytesBarColor,"yellow") == 0) { - gdata.color1 = gdImageColorAllocate(gdata.im,185,185,10); - gdata.color2 = gdImageColorAllocate(gdata.im,111,111,10); - gdata.color3 = gdImageColorAllocate(gdata.im,166,166,10); - } - else if(strcmp(GraphDaysBytesBarColor,"brown") == 0) { - gdata.color1 = gdImageColorAllocate(gdata.im,97,45,27); - gdata.color2 = gdImageColorAllocate(gdata.im,60,30,20); - gdata.color3 = gdImageColorAllocate(gdata.im,88,41,26); - } - else if(strcmp(GraphDaysBytesBarColor,"red") == 0){ - gdata.color1 = gdImageColorAllocate(gdata.im,185,10,10); - gdata.color2 = gdImageColorAllocate(gdata.im,111,10,10); - gdata.color3 = gdImageColorAllocate(gdata.im,166,10,10); - } else { - debuga(_("Unknown color \"%s\" requested for the graph. Using orange instead\n"),GraphDaysBytesBarColor); - gdata.color1 = gdImageColorAllocate(gdata.im, 255, 233, 142); - gdata.color2 = gdImageColorAllocate(gdata.im, 220, 163, 72); - gdata.color3 = gdImageColorAllocate(gdata.im, 255, 198, 107); - } - - // rectangle around the image - gdImageRectangle(gdata.im, 0, 0, ImgXSize-1, ImgYSize-1, gdata.dimgray); - // backtround of the graph - gdImageFilledRectangle(gdata.im, LeftMargin, TopMargin, RightGraph, BottomGraph, gdata.silver); - - // depth of the left Y axis - points[0].x = LeftMargin-10; - points[0].y = TopMargin+5; - points[1].x = LeftMargin-10; - points[1].y = BottomGraph+5; - points[2].x = LeftMargin; - points[2].y = BottomGraph; - points[3].x = LeftMargin; - points[3].y = TopMargin; - gdImageFilledPolygon(gdata.im, points, 4, gdata.gray); - - // depth of the bottom X axis - points[0].x = LeftMargin; - points[0].y = BottomGraph; - points[1].x = LeftMargin-10; - points[1].y = BottomGraph+5; - points[2].x = RightGraph-10; - points[2].y = BottomGraph+5; - points[3].x = RightGraph; - points[3].y = BottomGraph; - gdImageFilledPolygon(gdata.im, points, 4, gdata.gray); - - // vertical exterior line of the depth - gdImageLine(gdata.im, LeftMargin-10, TopMargin+5, LeftMargin-10, BottomGraph+5+ZTickLength, gdata.black); - // horizontal exterior line of the depth - gdImageLine(gdata.im, LeftMargin-10-ZTickLength, BottomGraph+5, RightGraph-10, BottomGraph+5, gdata.black); - // diagonal line between the two depths - gdImageLine(gdata.im, LeftMargin-10, BottomGraph+5, LeftMargin, BottomGraph, gdata.black); - // vertical left line of the graph - gdImageLine(gdata.im, LeftMargin, BottomGraph, LeftMargin, TopMargin, gdata.black); - // horizontal bottom line of the graph - gdImageLine(gdata.im, LeftMargin, BottomGraph, RightGraph, BottomGraph, gdata.black); - // vertical right line of the graph - gdImageLine(gdata.im, RightGraph, TopMargin, RightGraph, BottomGraph, gdata.black); - // diagonal line to close the right of the bottom depth - gdImageLine(gdata.im, RightGraph-10, BottomGraph+5, RightGraph, BottomGraph, gdata.black); - - // Y axis ticks - for(x=BottomGraph-10; x>=TopMargin; x=x-10) { - gdImageLine(gdata.im, LeftMargin-10, x+5, LeftMargin, x, gdata.dimgray); - gdImageLine(gdata.im, LeftMargin-10-TickLength, x+5, LeftMargin-10, x+5, gdata.dimgray); - } - - // horizontal background lines - for(x=TopMargin; x<=BottomGraph-10; x=x+10) - gdImageLine(gdata.im, LeftMargin, x, RightGraph, x, gdata.dimgray); - - // X axis ticks and labels - x=LeftMargin-10+20; - for(y=1; y<=31; y++) { - gdImageLine(gdata.im, x, BottomGraph+5, x, BottomGraph+5+TickLength, gdata.dimgray); - sprintf(s,"%02d",y); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,x,BottomGraph+5+TickLength+1,s,TRP_TopCenter); - x=x+20; - } - - t = time(NULL); - local = localtime(&t); - if(strcmp(DateFormat,"u") == 0) - strftime(ftime, sizeof(ftime), "%b/%d/%Y %H:%M", local); - if(strcmp(DateFormat,"e") == 0) - strftime(ftime, sizeof(ftime), "%d/%b/%Y-%H:%M", local); - - Sarg_gdImageStringFT(&gdata,gdata.darkblue,GraphFont,7,0.0,ImgXSize-10,ImgYSize-10,ftime,TRP_BottomRight); - if(ShowSargInfo) Sarg_gdImageStringFT(&gdata,gdata.darkblue,GraphFont,10,0.0,300,15,_("SARG, "),TRP_BottomRight); - Sarg_gdImageStringFT(&gdata,gdata.darkblue,GraphFont,10,0.0,300,15,Title,TRP_BottomLeft); - sprintf(warea,_("Period: %s"),period.text); - Sarg_gdImageStringFT(&gdata,gdata.darkblue,GraphFont,9,0.0,300,27,warea,TRP_BottomLeft); - sprintf(warea,_("User: %s"),uinfo->label); - Sarg_gdImageStringFT(&gdata,gdata.darkblue,GraphFont,9,0.0,300,38,warea,TRP_BottomLeft); - - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-10+5,"50K",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-20+5,"250K",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-30+5,"500K",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-40+5,"1M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-50+5,"2M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-60+5,"3M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-70+5,"4M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-80+5,"5M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-90+5,"6M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-100+5,"7M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-110+5,"8M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-120+5,"9M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-130+5,"10M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-140+5,"15M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-150+5,"20M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-160+5,"30M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-170+5,"40M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-180+5,"50M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-190+5,"60M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-200+5,"70M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-210+5,"80M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-220+5,"90M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-230+5,"100M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-240+5,"200M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-250+5,"300M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-260+5,"400M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-270+5,"500M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-280+5,"600M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-290+5,"700M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-300+5,"800M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-310+5,"900M",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-320+5,"1G",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-330+5,"2G",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-340+5,"3G",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-350+5,"4G",TRP_CenterRight); - Sarg_gdImageStringFT(&gdata,gdata.dimgray,GraphFont,7,0.0,LeftMargin-10-TickLength,BottomGraph-360+5,"5G",TRP_CenterRight); - if(strcmp(datetimeby,"bytes") == 0) - Sarg_gdImageStringFT(&gdata,gdata.black,GraphFont,10,3.141592/2,20,ImgYSize/2,_("BYTES"),TRP_CenterLeft); - else - Sarg_gdImageStringFT(&gdata,gdata.black,GraphFont,10,3.141592/2,20,ImgYSize/2,_("ELAPSED TIME"),TRP_CenterLeft); - Sarg_gdImageStringFT(&gdata,gdata.black,GraphFont,10,0.0,ImgXSize/2,ImgYSize-20,_("DAYS"),TRP_BottomCenter); - - for (day=0 ; day<31 ; day++) { - if (datapoints[day]>0) { - x1 = 44 +((day+1) * 20); - bar(&gdata,x1,datapoints[day]); - } - } - - if (snprintf(graph,sizeof(graph),"%s/%s/graph_day.png",outdirname,uinfo->filename)>=sizeof(graph)) { - debuga(_("user name too long for %s/%s/graph_day.png\n"),outdirname,uinfo->filename); - exit(EXIT_FAILURE); - } - if((pngout=fopen(graph,"wb"))==NULL) { - debuga(_("(grepday) Cannot open log file %s\n"),graph); - exit(EXIT_FAILURE); - } - gdImagePng(gdata.im, pngout); - fclose(pngout); - gdImageDestroy(gdata.im); - - if (gdata.string) free(gdata.string); -#ifdef USE_ICONV - if (gdata.localtoutf!=(iconv_t)-1) - iconv_close (gdata.localtoutf); -#endif +#endif //HAVE_GD +} +void greport_day(const struct userinfostruct *uinfo) +{ +#ifdef HAVE_GD + FILE *fp_in, *fp_ou; + char wdirname[MAXLEN]; + char buf[MAXLEN]; + int day; + long long int llday; + long long int bytes; + long long int elap; + long long int bytespoints[31]; + long long int elappoints[31]; + struct getwordstruct gwarea; + struct PlotStruct pdata; + + if (datetimeby==0) return; + if (!Graphs || GraphFont[0]=='\0') return; + if (snprintf(wdirname,sizeof(wdirname),"%s/%s.day",tmp,uinfo->filename)>=sizeof(wdirname)) { + debuga(__FILE__,__LINE__,_("User name too long to manufacture file name ")); + debuga_more("%s/%s.day\n",tmp,uinfo->filename); + exit(EXIT_FAILURE); + } + if(access(wdirname, R_OK) != 0) { + return; + } + + if((fp_in=fopen(wdirname,"r"))==NULL) { + debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),wdirname,strerror(errno)); + exit(EXIT_FAILURE); + } + + memset(bytespoints,0,sizeof(bytespoints)); + memset(elappoints,0,sizeof(elappoints)); + while(fgets(buf,sizeof(buf),fp_in)!=NULL) { + fixendofline(buf); + getword_start(&gwarea,buf); + if (getword_atoll(&llday,&gwarea,'/')<0) { + debuga(__FILE__,__LINE__,_("Invalid date in file \"%s\"\n"),wdirname); + exit(EXIT_FAILURE); + } + day=(int)llday; + if (day<1 || day>31) continue; + if (getword_skip(20,&gwarea,'\t')<0 || getword_skip(20,&gwarea,'\t')<0) { + debuga(__FILE__,__LINE__,_("Invalid entry in file \"%s\"\n"),wdirname); + exit(EXIT_FAILURE); + } + if ((datetimeby & DATETIME_BYTE)!=0) { + if (getword_atoll(&bytes,&gwarea,'\t')<0) { + debuga(__FILE__,__LINE__,_("Invalid number of bytes in file \"%s\"\n"),wdirname); + exit(EXIT_FAILURE); + } + bytespoints[day-1]+=bytes; + } + if ((datetimeby & DATETIME_ELAP)!=0) { + if (getword_atoll(&elap,&gwarea,'\0')<0) { + debuga(__FILE__,__LINE__,_("Invalid elapsed time in file \"%s\"\n"),wdirname); + exit(EXIT_FAILURE); + } + elappoints[day-1]+=elap; + } + } + if (fclose(fp_in)==EOF) { + debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),wdirname,strerror(errno)); + exit(EXIT_FAILURE); + } + + if (snprintf(wdirname,sizeof(wdirname),"%s/%s/graph.html",outdirname,uinfo->filename)>=sizeof(wdirname)) { + debuga(__FILE__,__LINE__,_("User name too long to manufacture file name ")); + debuga_more("%s/%s/%s\n",outdirname,uinfo->filename,"graph.html"); + exit(EXIT_FAILURE); + } + if ((fp_ou=fopen(wdirname,"wt"))==NULL) { + debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),wdirname,strerror(errno)); + exit(EXIT_FAILURE); + } + write_html_head(fp_ou,(IndexTree == INDEX_TREE_DATE) ? 4 : 2,_("Graph report"),HTML_JS_NONE); + + fputs("\n", fp_ou); + if((datetimeby & DATETIME_BYTE)!=0) { + memset(&pdata,0,sizeof(pdata)); + pdata.datapoints=bytespoints; + pdata.npoints=31; + pdata.XLabel=_("DAYS"); + pdata.ymin=50LL*1000LL; + pdata.ymax=5LL*1000LL*1000LL*1000LL; + pdata.ytype=PTG_LogBin; + pdata.YLabel=_("BYTES"); + pdata.pngfile="graph_day_byte.png"; + greport_plot(uinfo,&pdata); + fprintf(fp_ou,"\n",pdata.pngfile); + } + if((datetimeby & DATETIME_ELAP)!=0) { + memset(&pdata,0,sizeof(pdata)); + pdata.datapoints=elappoints; + pdata.npoints=31; + pdata.XLabel=_("DAYS"); + pdata.ymin=0; + pdata.ymax=86400000; + pdata.ytype=PTG_Time; + pdata.YLabel=_("ELAPSED TIME"); + pdata.pngfile="graph_day_elap.png"; + greport_plot(uinfo,&pdata); + fprintf(fp_ou,"\n",pdata.pngfile); + } + fputs("
\"B\"
\"E\"
\n",fp_ou); + + write_html_trailer(fp_ou); + if (fclose(fp_ou)==EOF) { + debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),wdirname,strerror(errno)); + exit(EXIT_FAILURE); + } #endif //HAVE_GD - return; + return; } void greport_cleanup(void) { #ifdef HAVE_GD - gdFontCacheShutdown(); + gdFontCacheShutdown(); + +#ifdef USE_ICONV + if (localtoutf!=(iconv_t)-1) + iconv_close (localtoutf); #endif +#endif //HAVE_GD }