]>
git.ipfire.org Git - thirdparty/sarg.git/blob - util.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 // #define LEGACY_MY_ATOLL
28 // #define LEGACY_TESTVALIDUSERCHAR
30 #include "include/conf.h"
31 #include "include/defs.h"
33 #if defined(HAVE_BACKTRACE)
34 #define USE_GETWORD_BACKTRACE 1
36 #define USE_GETWORD_BACKTRACE 0
39 static char mtab1
[12][4]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
41 //! The list of the HTTP codes to exclude from the report.
42 static char *excludecode
=NULL
;
44 #if USE_GETWORD_BACKTRACE
45 static void getword_backtrace(void)
51 n
=backtrace(buffer
,sizeof(buffer
)/sizeof(buffer
[0]));
53 calls
=backtrace_symbols(buffer
,n
);
55 debuga(_("getword backtrace:\n"));
56 for (i
=0 ; i
<n
; i
++) {
57 fprintf(stderr
,"SARG: %d:%s\n",i
+1,calls
[i
]);
62 #endif //USE_GETWORD_BACKTRACE
64 void getword_start(struct getwordstruct
*gwarea
, const char *line
)
66 gwarea
->beginning
=line
;
71 void getword_restart(struct getwordstruct
*gwarea
)
73 if (gwarea
->modified
) {
74 debuga(_("Cannot parse again the line as it was modified\n"));
77 gwarea
->current
=gwarea
->beginning
;
80 int getword(char *word
, int limit
, struct getwordstruct
*gwarea
, char stop
)
84 for(x
=0;((gwarea
->current
[x
]) && (gwarea
->current
[x
] != stop
));x
++) {
86 printf("SARG: getword loop detected after %d bytes.\n",x
);
87 printf("SARG: Line=\"%s\"\n",gwarea
->beginning
);
88 printf("SARG: Record=\"%s\"\n",gwarea
->current
);
89 printf("SARG: searching for \'x%x\'\n",stop
);
90 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
91 word
[(limit
>0) ? limit
-1 : 0]='\0';
92 #if USE_GETWORD_BACKTRACE
97 word
[x
] = gwarea
->current
[x
];
101 if (gwarea
->current
[x
]) ++x
;
106 int getword_limit(char *word
, int limit
, struct getwordstruct
*gwarea
, char stop
)
111 for(x
=0; x
<limit
&& gwarea
->current
[x
] && gwarea
->current
[x
] != stop
;x
++) {
112 word
[x
] = gwarea
->current
[x
];
116 while (*gwarea
->current
&& *gwarea
->current
!= stop
) gwarea
->current
++;
117 if (*gwarea
->current
) ++gwarea
->current
;
121 int getword_multisep(char *word
, int limit
, struct getwordstruct
*gwarea
, char stop
)
125 for(x
=0;((gwarea
->current
[x
]) && (gwarea
->current
[x
] != stop
));x
++) {
127 printf("SARG: getword_multisep loop detected.\n");
128 printf("SARG: Line=\"%s\"\n",gwarea
->beginning
);
129 printf("SARG: Record=\"%s\"\n",gwarea
->current
);
130 printf("SARG: searching for \'x%x\'\n",stop
);
131 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
132 if (limit
>0) word
[limit
-1]='\0';
133 #if USE_GETWORD_BACKTRACE
136 //exit(EXIT_FAILURE);
139 word
[x
] = gwarea
->current
[x
];
143 while (gwarea
->current
[x
] && gwarea
->current
[x
]==stop
) ++x
;
148 int getword_skip(int limit
, struct getwordstruct
*gwarea
, char stop
)
152 for(x
=0;(gwarea
->current
[x
] && (gwarea
->current
[x
] != stop
));x
++) {
154 printf("SARG: getword_skip loop detected after %d bytes.\n",x
);
155 printf("SARG: Line=\"%s\"\n",gwarea
->beginning
);
156 printf("SARG: Record=\"%s\"\n",gwarea
->current
);
157 printf("SARG: searching for \'x%x\'\n",stop
);
158 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
159 #if USE_GETWORD_BACKTRACE
166 if (gwarea
->current
[x
]) ++x
;
171 int getword_atoll(long long int *number
, struct getwordstruct
*gwarea
, char stop
)
176 if (gwarea
->current
[0] == '-') {
179 } else if (gwarea
->current
[0] == '+') {
183 for(x
=0;isdigit(gwarea
->current
[x
]);x
++) {
184 *number
=(*number
* 10) + gwarea
->current
[x
]-'0';
186 if(gwarea
->current
[x
] && gwarea
->current
[x
]!=stop
) {
187 printf("SARG: getword_atoll loop detected after %d bytes.\n",x
);
188 printf("SARG: Line=\"%s\"\n",gwarea
->beginning
);
189 printf("SARG: Record=\"%s\"\n",gwarea
->current
);
190 printf("SARG: searching for \'x%x\'\n",stop
);
191 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
192 #if USE_GETWORD_BACKTRACE
199 if (gwarea
->current
[x
]) ++x
;
205 int getword_ptr(char *orig_line
,char **word
, struct getwordstruct
*gwarea
, char stop
)
208 \note Why pass the original buffer to the function ? Because we must modify it to
209 insert the terminating ASCII zero for the word we return and that's not compatible
210 with getword_restart(). Moreover, getword_start() sometime works on constant strings
211 so this function require the original buffer to detect any missuse.
217 if (orig_line
&& orig_line
!=gwarea
->beginning
) {
218 debuga(_("Invalid buffer passed to getword_ptr\n"));
222 start
=(gwarea
->current
-gwarea
->beginning
);
223 if (word
&& orig_line
) *word
=orig_line
+start
;
224 for(x
=0;((gwarea
->current
[x
]) && (gwarea
->current
[x
] != stop
));x
++);
225 sep
=(gwarea
->current
[x
]!='\0');
226 if (word
&& orig_line
) orig_line
[start
+x
] = '\0';
233 #define MAXLLL 30 //!< Maximum number of digits in long long (a guess).
234 long long int my_atoll (const char *nptr
)
236 long long int returnval
=0LL;
237 int max_digits
= MAXLLL
;
239 // Soak up all the white space
240 while (isspace( *nptr
)) {
244 //For each character left to right
245 //change the character to a single digit
246 //multiply what we had before by 10 and add the new digit
248 while (--max_digits
&& isdigit( *nptr
))
250 returnval
= ( returnval
* 10 ) + ( *nptr
++ - '0' ) ;
256 int is_absolute(const char *path
)
258 if (*path
=='/') return(1);
260 if (isalpha(path
[0]) && path
[1]==':') return(1);
265 void my_mkdir(const char *name
)
271 if(!is_absolute(name
)) {
272 debuga(_("Invalid path (%s). Please, use absolute paths only.\n"),name
);
273 debuga(_("process aborted.\n"));
278 for (i
=0 ; name
[i
] ; i
++) {
280 debuga(_("directory name too long: %s\n"),name
);
283 if (chars
>0 && name
[i
] == '/') {
285 if (access(w0
, R_OK
) != 0) {
286 if (mkdir(w0
,0755)) {
287 debuga(_("Cannot create directory %s - %s\n"),w0
,strerror(errno
));
288 debuga(_("process aborted.\n"));
293 if (name
[i
] != '/') chars
++;
297 if (access(name
, R_OK
) != 0) {
298 if (mkdir(name
,0755)) {
299 debuga(_("Cannot create directory %s - %s\n"),name
,strerror(errno
));
300 debuga(_("process aborted.\n"));
307 void my_lltoa(unsigned long long int n
, char *s
, int ssize
, int len
)
316 debuga(_("The requested number of digits passed to my_lltoa (%d) is bigger than the output buffer size (%d)\n"),len
,ssize
);
321 s
[slen
++] = (n
% 10) + '0';
322 } while ((n
/= 10) > 0 && slen
<ssize
);
325 for (i
= 0, j
= slen
-1; i
<j
; i
++, j
--) {
333 for(j
=slen
; j
>=0; j
--)
340 int month2num(const char *month
)
344 for(m
=0 ; m
<12 && strcmp(mtab1
[m
],month
) != 0; m
++);
348 int builddia(int day
, int month
, int year
)
350 return(year
*10000+month
*100+day
);
354 void buildymd(const char *dia
, const char *mes
, const char *ano
, char *wdata
)
359 sprintf(wdata
,"%04d%02d%02d",atoi(ano
),nmes
+1,atoi(dia
));
363 int conv_month(const char *month
)
367 for(x
=0; x
<12 && strncmp(mtab1
[x
],month
,3)!=0; x
++);
372 const char *conv_month_name(int month
)
376 if (month
<1 || month
>12) {
377 snprintf(str
,sizeof(str
),"%03d",month
);
380 return(mtab1
[month
-1]);
384 void name_month(char *month
,int month_len
)
386 int x
, z
=atoi(month
)-1;
389 struct getwordstruct gwarea
;
391 strcpy(m
,_("January,February,March,April,May,June,July,August,September,October,November,December"));
392 getword_start(&gwarea
,m
);
395 if (getword_multisep(w
,sizeof(w
),&gwarea
,',')<0) {
396 printf("SARG: Maybe you have a broken record or garbage in the names of the months.\n");
399 if (getword_multisep(month
,month_len
,&gwarea
,',')<0) {
400 printf("SARG: Maybe you have a broken record or garbage in the name of the months.\n");
406 void debuga(const char *msg
,...)
410 fputs(_("SARG: "),stderr
);
412 vfprintf(stderr
,msg
,ap
);
417 void debugaz(const char *head
, const char *msg
)
419 fprintf(stderr
, "SARG: (util) %s=%s\n",head
, msg
);
423 char *fixnum(long long int value
, int n
)
425 #define MAXLEN_FIXNUM 256
426 char num
[MAXLEN_FIXNUM
]="";
427 char buf
[MAXLEN_FIXNUM
* 2];
429 static char ret
[MAXLEN_FIXNUM
* 2];
431 register int i
, j
, k
;
433 static char abbrev
[30];
435 my_lltoa(value
, num
, sizeof(num
), 0);
437 if(DisplayedValues
==DISPLAY_ABBREV
) {
438 numlen
= strlen(num
);
440 sprintf(abbrev
,"%s",num
);
441 if(numlen
== 4 || numlen
== 7 || numlen
== 10 || numlen
== 13) {
442 snprintf(abbrev
,2,"%s",num
);
443 strncat(abbrev
,".",1);
444 strncat(abbrev
,num
+1,2);
445 if(!n
) return(abbrev
);
447 strncat(abbrev
,"K",1);
449 strncat(abbrev
,"M",1);
450 else if(numlen
== 10)
451 strncat(abbrev
,"G",1);
452 else if(numlen
== 13)
453 strncat(abbrev
,"T",1);
455 if(numlen
== 5 || numlen
== 8 || numlen
== 11 || numlen
== 14) {
456 snprintf(abbrev
,3,"%s",num
);
457 strncat(abbrev
,".",1);
458 strncat(abbrev
,num
+2,2);
459 if(!n
) return(abbrev
);
461 strncat(abbrev
,"K",1);
463 strncat(abbrev
,"M",1);
464 else if(numlen
== 11)
465 strncat(abbrev
,"G",1);
466 else if(numlen
== 14)
467 strncat(abbrev
,"T",1);
469 if(numlen
== 6 || numlen
== 9 || numlen
== 12 || numlen
== 15) {
470 snprintf(abbrev
,4,"%s",num
);
471 strncat(abbrev
,".",1);
472 strncat(abbrev
,num
+3,2);
473 if(!n
) return(abbrev
);
475 strncat(abbrev
,"K",1);
477 strncat(abbrev
,"M",1);
478 else if(numlen
== 12)
479 strncat(abbrev
,"G",1);
480 else if(numlen
== 15)
481 strncat(abbrev
,"T",1);
487 bzero(buf
, MAXLEN_FIXNUM
*2);
493 for ( i
= strlen(num
) - 1, j
= 0 ; i
> -1; i
--) {
494 if ( k
== 2 && i
!= 0 ) {
497 pbuf
[j
++] = (UseComma
) ? ',' : '.';
507 for ( i
= strlen(pbuf
) - 1, j
= 0 ; i
> -1; i
--, j
++)
516 char *fixnum2(long long int value
, int n
)
518 #define MAXLEN_FIXNUM2 1024
519 char num
[MAXLEN_FIXNUM2
];
520 char buf
[MAXLEN_FIXNUM2
* 2];
522 static char ret
[MAXLEN_FIXNUM2
* 2];
524 register int i
, j
, k
;
526 my_lltoa(value
, num
, sizeof(num
), 0);
527 bzero(buf
, MAXLEN_FIXNUM2
*2);
533 for ( i
= strlen(num
) - 1, j
= 0 ; i
> -1; i
--) {
534 if ( k
== 2 && i
!= 0 ) {
537 pbuf
[j
++] = (UseComma
) ? ',' : '.';
547 for ( i
= strlen(pbuf
) - 1, j
= 0 ; i
> -1; i
--, j
++)
556 char *buildtime(long long int elap
)
558 int num
= elap
/ 1000;
567 min
=(num
% 3600) / 60;
569 sprintf(buf
,"%02d:%02d:%02d",hor
,min
,sec
);
575 void obtdate(const char *dirname
, const char *name
, char *data
)
580 sprintf(wdir
,"%s%s/sarg-date",dirname
,name
);
581 if ((fp_in
= fopen(wdir
, "rt")) == 0) {
582 sprintf(wdir
,"%s%s/date",dirname
,name
);
583 if ((fp_in
= fopen(wdir
, "rt")) == 0) {
589 if (!fgets(data
,80,fp_in
)) {
590 debuga(_("Failed to read the date in %s\n"),wdir
);
600 void formatdate(char *date
,int date_size
,int year
,int month
,int day
,int hour
,int minute
,int second
,int dst
)
606 memset(<m
,0,sizeof(ltm
));
607 if (year
>=1900) ltm
.tm_year
=year
-1900;
608 if (month
>=1 && month
<=12) ltm
.tm_mon
=month
-1;
609 if (day
>=1 && day
<=31) ltm
.tm_mday
=day
;
610 if (hour
>=0 && hour
<24) ltm
.tm_hour
=hour
;
611 if (minute
>=0 && minute
<60) ltm
.tm_min
=minute
;
612 if (second
>=0 && second
<60) ltm
.tm_sec
=second
;
614 unixtime
=mktime(<m
); //fill the missing entries
615 fulltm
=localtime(&unixtime
);
616 //strftime(date,date_size,"%a %b %d %H:%M:%S %Z %Y",fulltm);
617 strftime(date
,date_size
,"%c",fulltm
);
621 void computedate(int year
,int month
,int day
,struct tm
*t
)
623 memset(t
,0,sizeof(*t
));
624 t
->tm_year
=year
-1900;
630 int obtuser(const char *dirname
, const char *name
)
637 sprintf(wdir
,"%s%s/sarg-users",dirname
,name
);
638 if((fp_in
=fopen(wdir
,"r"))==NULL
) {
639 sprintf(wdir
,"%s%s/users",dirname
,name
);
640 if((fp_in
=fopen(wdir
,"r"))==NULL
) {
645 if (!fgets(tuser
,sizeof(tuser
),fp_in
)) {
646 debuga(_("Failed to read the number of users in %s\n"),wdir
);
656 void obttotal(const char *dirname
, const char *name
, int nuser
, long long int *tbytes
, long long int *media
)
661 char user
[MAX_USER_LEN
];
663 struct getwordstruct gwarea
;
669 sprintf(wdir
,"%s%s/sarg-general",dirname
,name
);
670 if ((fp_in
= fopen(wdir
, "r")) == 0) {
671 sprintf(wdir
,"%s%s/general",dirname
,name
);
672 if ((fp_in
= fopen(wdir
, "r")) == 0) {
677 if ((line
=longline_create())==NULL
) {
678 debuga(_("Not enough memory to read the file %s\n"),wdir
);
682 while((buf
=longline_read(fp_in
,line
))!=NULL
) {
683 if (strncmp(buf
,"TOTAL\t",6) == 0)
685 else if (strncmp(buf
,"TOTAL ",6) == 0)
689 getword_start(&gwarea
,buf
);
690 if (getword(user
,sizeof(user
),&gwarea
,sep
)<0) {
691 debuga(_("There is a invalid user in file %s\n"),wdir
);
694 if(strcmp(user
,"TOTAL") != 0)
696 if (getword_skip(MAXLEN
,&gwarea
,sep
)<0) {
697 debuga(_("There a broken total number of access in file %s\n"),wdir
);
700 if (getword_atoll(tbytes
,&gwarea
,sep
)<0) {
701 debuga(_("There is a broken number of bytes in file %s\n"),wdir
);
707 longline_destroy(&line
);
712 *media
=*tbytes
/ nuser
;
716 int getperiod_fromsarglog(const char *arqtt
,struct periodstruct
*period
)
719 int day0
, month0
, year0
, hour0
, minute0
;
720 int day1
, month1
, year1
, hour1
, minute1
;
723 memset(period
,0,sizeof(*period
));
726 while((str
=strstr(str
,"sarg-"))!=NULL
) {
728 if (!isdigit(str
[0]) || !isdigit(str
[1])) continue;
729 day0
=(str
[0]-'0')*10+(str
[1]-'0');
731 month0
=(str
[0]-'0')*10+(str
[1]-'0');
732 if (month0
>=12) continue;
735 for (i
=0 ; isdigit(str
[i
]) && i
<4 ; i
++) year0
=year0
*10+(str
[i
]-'0');
738 if (str
[0]!='_') continue;
741 if (!isdigit(str
[0]) || !isdigit(str
[1])) continue;
742 hour0
=(str
[0]-'0')*10+(str
[1]-'0');
744 if (!isdigit(str
[0]) || !isdigit(str
[1])) continue;
745 minute0
=(str
[0]-'0')*10+(str
[1]-'0');
748 if (*str
!= '-') continue;
751 if (!isdigit(str
[0]) || !isdigit(str
[1])) continue;
752 day1
=(str
[0]-'0')*10+(str
[1]-'0');
754 month1
=(str
[0]-'0')*10+(str
[1]-'0');
755 if (month1
>=12) continue;
758 for (i
=0 ; isdigit(str
[i
]) && i
<4 ; i
++) year1
=year1
*10+(str
[i
]-'0');
762 if (str
[0]!='_') continue;
765 if (!isdigit(str
[0]) || !isdigit(str
[1])) continue;
766 hour1
=(str
[0]-'0')*10+(str
[1]-'0');
768 if (!isdigit(str
[0]) || !isdigit(str
[1])) continue;
769 minute1
=(str
[0]-'0')*10+(str
[1]-'0');
772 period
->start
.tm_mday
=day0
;
773 period
->start
.tm_mon
=month0
;
774 period
->start
.tm_year
=year0
-1900;
775 period
->start
.tm_hour
=hour0
;
776 period
->start
.tm_min
=minute0
;
777 period
->end
.tm_mday
=day1
;
778 period
->end
.tm_mon
=month1
;
779 period
->end
.tm_year
=year1
-1900;
780 period
->end
.tm_hour
=hour1
;
781 period
->end
.tm_min
=minute1
;
787 void getperiod_fromrange(struct periodstruct
*period
,int dfrom
,int duntil
)
789 memset(&period
->start
,0,sizeof(period
->start
));
790 period
->start
.tm_mday
=dfrom
%100;
791 period
->start
.tm_mon
=(dfrom
/100)%100-1;
792 period
->start
.tm_year
=(dfrom
/10000)-1900;
794 memset(&period
->end
,0,sizeof(period
->end
));
795 period
->end
.tm_mday
=duntil
%100;
796 period
->end
.tm_mon
=(duntil
/100)%100-1;
797 period
->end
.tm_year
=(duntil
/10000)-1900;
800 int getperiod_buildtext(struct periodstruct
*period
)
804 char text1
[40], text2
[40];
807 i
=strftime(text1
, sizeof(text1
), "%Y %b %d", &period
->start
);
808 }else if(df
[0]=='e') {
809 i
=strftime(text1
, sizeof(text1
), "%d %b %Y", &period
->start
);
810 } else /*if(df[0]=='w')*/ {
811 IndexTree
=INDEX_TREE_FILE
;
812 i
=strftime(text1
, sizeof(text1
), "%Y.%U", &period
->start
);
814 if (i
== 0) return(-1);
816 range
=(period
->start
.tm_year
!=period
->end
.tm_year
||
817 period
->start
.tm_mon
!=period
->end
.tm_mon
||
818 period
->start
.tm_mday
!=period
->end
.tm_mday
);
821 i
=strftime(text2
, sizeof(text2
)-i
, "%Y %b %d", &period
->end
);
822 } else if(df
[0]=='e') {
823 i
=strftime(text2
, sizeof(text2
)-i
, "%d %b %Y", &period
->end
);
825 i
=strftime(text2
, sizeof(text2
)-i
, "%Y.%U", &period
->end
);
827 if (i
== 0) return(-1);
831 snprintf(period
->text
,sizeof(period
->text
),"%s-%s",text1
,text2
);
832 snprintf(period
->html
,sizeof(period
->html
),"%s—%s",text1
,text2
);
834 strncpy(period
->text
,text1
,sizeof(period
->text
)-1);
835 period
->text
[sizeof(period
->text
)-1]='\0';
836 strncpy(period
->html
,text1
,sizeof(period
->html
)-1);
837 period
->html
[sizeof(period
->html
)-1]='\0';
842 static void copy_images(void)
844 FILE *img_in
, *img_ou
;
847 char srcfile
[MAXLEN
];
848 char dstfile
[MAXLEN
];
850 struct dirent
*direntp
;
855 if (snprintf(images
,sizeof(images
),"%simages",outdir
)>=sizeof(images
)) {
856 debuga(_("Cannot copy images to target directory %simages\n"),outdir
);
859 if (access(images
,R_OK
)!=0) {
860 if (mkdir(images
,0755)) {
861 debuga(_("Cannot create directory %s - %s\n"),images
,strerror(errno
));
866 strcpy(imgdir
,IMAGEDIR
);
867 dirp
= opendir(imgdir
);
869 debuga(_("(util) Can't open directory %s: %s\n"),imgdir
,strerror(errno
));
872 while ((direntp
= readdir( dirp
)) != NULL
){
873 if(direntp
->d_name
[0]=='.')
875 sprintf(srcfile
,"%s/%s",imgdir
,direntp
->d_name
);
876 if (stat(srcfile
,&info
)) {
877 debuga(_("Cannot stat \"%s\" - %s\n"),srcfile
,strerror(errno
));
880 if (S_ISREG(info
.st_mode
)) {
881 sprintf(dstfile
,"%s/%s",images
,direntp
->d_name
);
882 img_in
= fopen(srcfile
, "rb");
884 img_ou
= fopen(dstfile
, "wb");
886 while ((nread
= fread(buffer
,1,sizeof(buffer
),img_in
))>0) {
887 if (fwrite(buffer
,1,nread
,img_ou
)!=nread
) {
888 debuga(_("Failed to copy image %s to %s\n"),srcfile
,dstfile
);
894 fprintf(stderr
,"SARG: (util): %s %s: %s\n", _("Cannot open file")?_("Cannot open file"):"Can't open/create file", dstfile
, strerror(errno
));
897 fprintf(stderr
,"SARG: (util): %s %s: %s\n", _("Cannot open file")?_("Cannot open file"):"Can't open file", srcfile
, strerror(errno
));
900 (void) closedir(dirp
);
905 int vrfydir(const struct periodstruct
*per1
, const char *addr
, const char *site
, const char *us
, const char *form
)
910 char dirname2
[MAXLEN
];
920 y1
=per1
->start
.tm_year
+1900;
921 y2
=per1
->end
.tm_year
+1900;
922 m1
=per1
->start
.tm_mon
+1;
923 m2
=per1
->end
.tm_mon
+1;
924 d1
=per1
->start
.tm_mday
;
925 d2
=per1
->end
.tm_mday
;
926 if(IndexTree
== INDEX_TREE_DATE
) {
927 wlen
+=sprintf(wdir
+wlen
,"%04d",y1
);
928 if(y1
!=y2
) wlen
+=sprintf(wdir
+wlen
,"-%04d",y2
);
929 if(access(wdir
, R_OK
) != 0)
932 wlen
+=sprintf(wdir
+wlen
,"/%02d",m1
);
933 if(m1
!= m2
) wlen
+=sprintf(wdir
+wlen
,"-%02d",m2
);
934 if(access(wdir
, R_OK
) != 0)
937 wlen
+=sprintf(wdir
+wlen
,"/%02d",d1
);
938 if(d1
!=d2
) wlen
+=sprintf(wdir
+wlen
,"-%02d",d2
);
941 wlen
=snprintf(wdir
+wlen
,sizeof(wdir
)-wlen
,"%04d%s%02d-%04d%s%02d",y1
,
942 conv_month_name(m1
),d1
,y2
,conv_month_name(m2
),d2
);
943 } else if(df
[0] == 'e') {
944 wlen
=snprintf(wdir
+wlen
,sizeof(wdir
)-wlen
,"%02d%s%04d-%02d%s%04d",d1
,
945 conv_month_name(m1
),y1
,d2
,conv_month_name(m2
),y2
);
946 } else if(df
[0] == 'w') {
947 wlen2
=strftime(wdir
+wlen
, sizeof(wdir
)-wlen
, "%Y.%U", &per1
->start
);
948 if (wlen2
==0) return(-1);
954 struct userinfostruct
*uinfo
=userinfo_find_from_id(us
);
957 strcat(wdir
,uinfo
->filename
);
960 if(addr
[0] != '\0') {
964 if(site
[0] != '\0') {
969 strcpy(outdirname
,wdir
);
971 if(IndexTree
!= INDEX_TREE_DATE
) {
972 if(!OverwriteReport
) {
974 if(access(wdir
,R_OK
) == 0) {
975 sprintf(wdir
,"%s.%d",outdirname
,num
);
984 debuga(_("File %s already exists, moved to %s\n"),outdirname
,wdir
);
985 rename(outdirname
,wdir
);
988 if(access(outdirname
,R_OK
) == 0) {
989 unlinkdir(outdirname
,1);
992 my_mkdir(outdirname
);
994 strcpy(dirname2
,wdir
);
995 if(!OverwriteReport
) {
997 if(access(wdir
,R_OK
) == 0) {
998 sprintf(wdir
,"%s.%d",dirname2
,num
);
1007 debuga(_("File %s already exists, moved to %s\n"),dirname2
,wdir
);
1008 rename(dirname2
,wdir
);
1009 strcpy(dirname2
,wdir
);
1012 if(access(wdir
,R_OK
) == 0) {
1017 if(access(wdir
, R_OK
) != 0)
1021 strcpy(dirname2
,wdir
);
1023 sprintf(wdir
,"%s/sarg-date",outdirname
);
1024 if ((fp_ou
= fopen(wdir
, "wt")) == 0) {
1025 debuga(_("cannot open %s for writing\n"),wdir
);
1030 //strftime(wdir,sizeof(wdir),"%a %b %d %H:%M:%S %Z %Y",localtime(&curtime));
1031 loctm
=localtime(&curtime
);
1032 strftime(wdir
,sizeof(wdir
),"%Y-%m-%d %H:%M:%S",loctm
);
1033 if (fprintf(fp_ou
,"%s %d\n",wdir
,loctm
->tm_isdst
)<0) {
1034 debuga(_("Failed to write the date in %s\n"),wdir
);
1038 if (fclose(fp_ou
)==EOF
) {
1039 debuga(_("Failed to write the date in %s\n"),wdir
);
1048 void strip_latin(char *line
)
1055 for (i
=0;line
[i
];i
++){
1057 if (line
[i
]==';') skip
=0;
1069 void zdate(char *ftime
,int ftimesize
, const char *DateFormat
)
1075 local
= localtime(&t
);
1076 if(strcmp(DateFormat
,"u") == 0)
1077 strftime(ftime
, ftimesize
, "%b/%d/%Y %H:%M", local
);
1078 if(strcmp(DateFormat
,"e") == 0)
1079 strftime(ftime
, ftimesize
, "%d/%b/%Y-%H:%M", local
);
1080 if(strcmp(DateFormat
,"w") == 0)
1081 strftime(ftime
, ftimesize
, "%W-%H-%M", local
);
1086 char *fixtime(long long int elap
)
1088 int num
= elap
/ 1000;
1092 static char buf
[12];
1095 min
=(num
% 3600) / 60;
1098 if(hor
==0 && min
==0 && sec
==0)
1101 sprintf(buf
,"%d:%02d:%02d",hor
,min
,sec
);
1107 void date_from(char *date
, int *dfrom
, int *duntil
)
1116 if (isdigit(date
[0])) {
1119 if (sscanf(date
,"%d/%d/%d%n",&d0
,&m0
,&y0
,&next
)!=3 || y0
<100 || m0
<1 || m0
>12 || d0
<1 || d0
>31 || next
<0) {
1120 debuga(_("The date passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n"));
1123 if (date
[next
]=='-') {
1124 if (sscanf(date
+next
+1,"%d/%d/%d",&d1
,&m1
,&y1
)!=3 || y1
<100 || m1
<1 || m1
>12 || d1
<1 || d1
>31) {
1125 debuga(_("The date range passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n"));
1128 } else if (date
[next
]!='\0') {
1129 debuga(_("The date range passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n"));
1139 struct tm
*Date0
,Date1
;
1141 if (time(&Today
)==(time_t)-1) {
1142 debuga(_("Failed to get the current time\n"));
1145 if (sscanf(date
,"day-%d",&i
)==1) {
1147 debuga(_("Invalid number of days in -d parameter\n"));
1151 Date0
=localtime(&Today
);
1153 debuga(_("Cannot convert local time: %s\n"),strerror(errno
));
1156 y0
=y1
=Date0
->tm_year
+1900;
1157 m0
=m1
=Date0
->tm_mon
+1;
1158 d0
=d1
=Date0
->tm_mday
;
1159 } else if (sscanf(date
,"week-%d",&i
)==1) {
1161 There is no portable way to find the first day of the week even though the
1162 information is available in the locale. nl_langinfo has the unofficial
1163 parameters _NL_TIME_FIRST_WEEKDAY and _NL_TIME_WEEK_1STDAY but they are
1164 undocumented as is their return value and it is discouraged to use them.
1165 Beside, nl_langinfo isn't available on windows and the first day of the
1166 week isn't available at all on that system.
1168 const int FirstWeekDay
=1;
1172 debuga(_("Invalid number of weeks in -d parameter\n"));
1175 Date0
=localtime(&Today
);
1177 debuga(_("Cannot convert local time: %s\n"),strerror(errno
));
1180 WeekBegin
=Today
-((Date0
->tm_wday
-FirstWeekDay
+7)%7)*24*60*60;
1181 WeekBegin
-=i
*7*24*60*60;
1182 Date0
=localtime(&WeekBegin
);
1184 debuga(_("Cannot convert local time: %s\n"),strerror(errno
));
1187 y0
=Date0
->tm_year
+1900;
1190 WeekBegin
+=6*24*60*60;
1191 Date0
=localtime(&WeekBegin
);
1193 debuga(_("Cannot convert local time: %s\n"),strerror(errno
));
1196 y1
=Date0
->tm_year
+1900;
1199 } else if (sscanf(date
,"month-%d",&i
)==1) {
1201 debuga(_("Invalid number of months in -d parameter\n"));
1204 Date0
=localtime(&Today
);
1206 debuga(_("Cannot convert local time: %s\n"),strerror(errno
));
1209 if (Date0
->tm_mon
<i
%12) {
1210 y0
=Date0
->tm_year
+1900-i
/12-1;
1211 m0
=(Date0
->tm_mon
+12-i
%12)%12+1;
1214 y0
=Date0
->tm_year
+1900-i
/12;
1215 m0
=Date0
->tm_mon
-i
%12+1;
1218 memcpy(&Date1
,Date0
,sizeof(struct tm
));
1223 Date1
.tm_year
=y0
-1900;
1226 Date1
.tm_year
=y0
-1900+1;
1230 Date0
=localtime(&t1
);
1231 y1
=Date0
->tm_year
+1900;
1235 debuga(_("Invalid date range passed on command line\n"));
1240 *dfrom
=y0
*10000+m0
*100+d0
;
1241 *duntil
=y1
*10000+m1
*100+d1
;
1242 sprintf(date
,"%02d/%02d/%04d-%02d/%02d/%04d",d0
,m0
,y0
,d1
,m1
,y1
);
1247 char *strlow(char *string
)
1253 for (s
= string
; *s
; ++s
)
1263 char *strup(char *string
)
1269 for (s
= string
; *s
; ++s
)
1277 void removetmp(const char *outdir
)
1282 if(!RemoveTempFiles
)
1286 debuga(_("Purging temporary file sarg-general\n"));
1288 if (snprintf(filename
,sizeof(filename
),"%s/sarg-general",outdir
)>=sizeof(filename
)) {
1289 debuga(_("(removetmp) directory too long to remove %s/sarg-period\n"),outdir
);
1292 if((fp_gen
=fopen(filename
,"w"))==NULL
){
1293 debuga(_("(removetmp) Cannot open file %s\n"),filename
);
1296 totalger(fp_gen
,filename
);
1297 if (fclose(fp_gen
)==EOF
) {
1298 debuga(_("Failed to close %s after writing the total line - %s\n"),filename
,strerror(errno
));
1303 void load_excludecodes(const char *ExcludeCodes
)
1311 if(ExcludeCodes
[0] == '\0')
1314 if((fp_in
=fopen(ExcludeCodes
,"r"))==NULL
) {
1315 debuga(_("(util) Cannot open file %s (exclude_codes)\n"),ExcludeCodes
);
1319 if (fseek(fp_in
, 0, SEEK_END
)==-1) {
1320 debuga(_("Failed to move till the end of the excluded codes file %s: %s\n"),ExcludeCodes
,strerror(errno
));
1323 MemSize
= ftell(fp_in
);
1325 debuga(_("Cannot get the size of file %s\n"),ExcludeCodes
);
1328 if (fseek(fp_in
, 0, SEEK_SET
)==-1) {
1329 debuga(_("Failed to rewind the excluded codes file %s: %s\n"),ExcludeCodes
,strerror(errno
));
1334 if((excludecode
=(char *) malloc(MemSize
))==NULL
) {
1335 debuga(_("malloc error (%ld)\n"),MemSize
);
1338 memset(excludecode
,0,MemSize
);
1341 while(fgets(data
,sizeof(data
),fp_in
)!=NULL
) {
1342 if (data
[0]=='#') continue;
1343 for (i
=strlen(data
)-1 ; i
>=0 && (unsigned char)data
[i
]<=' ' ; i
--) data
[i
]='\0';
1345 if (Stored
+i
+2>=MemSize
) {
1346 debuga(_("Too many codes to exclude in file %s\n"),ExcludeCodes
);
1349 strcat(excludecode
,data
);
1350 strcat(excludecode
,";");
1358 void free_excludecodes(void)
1366 int vercode(const char *code
)
1371 if (excludecode
&& excludecode
[0]!='\0') {
1375 if (strncmp(code
,cod
,clen
)==0 && cod
[clen
]==';')
1377 cod
=strchr(cod
,';');
1384 void fixnone(char *str
)
1388 for (i
=strlen(str
)-1 ; i
>=0 && (unsigned char)str
[i
]<=' ' ; i
--);
1389 if(i
==3 && strncmp(str
,"none",4) == 0)
1395 void fixendofline(char *str
)
1399 for (i
=strlen(str
)-1 ; i
>=0 && (unsigned char)str
[i
]<=' ' ; i
--) str
[i
]=0;
1402 #ifdef LEGACY_TESTVALIDUSERCHAR
1403 int testvaliduserchar(const char *user
)
1408 for (y
=0; y
<strlen(UserInvalidChar
); y
++) {
1409 for (x
=0; x
<strlen(user
); x
++) {
1410 if(user
[x
] == UserInvalidChar
[y
])
1417 int testvaliduserchar(const char *user
)
1419 char * p_UserInvalidChar
= UserInvalidChar
;
1420 const char * p_user
;
1422 while( *p_UserInvalidChar
) {
1425 if( *p_UserInvalidChar
== *p_user
)
1429 p_UserInvalidChar
++ ;
1435 int compar( const void *a
, const void *b
)
1437 if( *(int *)a
> *(int *)b
) return 1;
1438 if( *(int *)a
< *(int *)b
) return -1;
1442 int getnumlist( char *buf
, numlist
*list
, const int len
, const int maxvalue
)
1444 int i
, j
, d
, flag
, r1
, r2
;
1445 char *pbuf
, **bp
, *strbufs
[ 24 ];
1448 strtok( buf
, " \t" );
1449 for( *bp
= strtok( NULL
, "," ), list
->len
= 0; *bp
; *bp
= strtok( NULL
, "," ) ) {
1450 if( ++bp
>= &strbufs
[ 24 ] )
1457 for( i
= 0; i
< list
->len
; i
++ ) {
1458 if( strchr( strbufs
[ i
], '-' ) != 0 ) {
1459 pbuf
= strbufs
[ i
];
1460 strtok( pbuf
, "-" );
1461 pbuf
= strtok( NULL
, "\0" );
1462 r1
= atoi( strbufs
[ i
] );
1463 if( ( r2
= atoi( pbuf
) ) >= maxvalue
|| r1
>= r2
)
1465 if( i
+ d
+ ( r2
- r1
) + 1 <= len
) {
1466 for( j
= r1
; j
<= r2
; j
++ )
1467 list
->list
[ i
+ d
++ ] = j
;
1472 if( ( list
->list
[ i
+ d
] = atoi( strbufs
[ i
] ) ) >= maxvalue
)
1476 qsort( list
->list
, list
->len
, sizeof( int ), compar
);
1479 for( i
= 0; i
< list
->len
- 1; i
++ )
1480 if( list
->list
[ i
] == list
->list
[ i
+ 1 ] ) {
1481 for( j
= i
+ 1; j
< list
->len
; j
++ )
1482 list
->list
[ j
- 1 ] = list
->list
[ j
];
1492 char *get_size(const char *path
, const char *file
)
1495 static char response
[255];
1499 if (snprintf(cmd
,sizeof(cmd
),"du -skh %s%s",path
,file
)>=sizeof(cmd
)) {
1500 debuga(_("Cannot get disk space because the path %s%s is too long\n"),path
,file
);
1503 if ((fp
= popen(cmd
, "r")) == NULL
) {
1504 debuga(_("Cannot get disk space with command %s\n"),cmd
);
1507 if (!fgets(response
, sizeof(response
), fp
)) {
1508 debuga(_("Cannot get disk size with command %s\n"),cmd
);
1511 ptr
=strchr(response
,'\t');
1513 debuga(_("The command %s failed\n"),cmd
);
1522 void show_info(FILE *fp_ou
)
1526 if(!ShowSargInfo
) return;
1527 zdate(ftime
, sizeof(ftime
), DateFormat
);
1528 fprintf(fp_ou
,"<div class=\"info\">%s <a href='%s'>%s-%s</a> %s %s</div>\n",_("Generated by"),URL
,PGM
,VERSION
,_("on"),ftime
);
1531 void show_sarg(FILE *fp_ou
, int depth
)
1535 if(!ShowSargLogo
) return;
1536 fputs("<div class=\"logo\"><a href=\"http://sarg.sourceforge.net\"><img src=\"",fp_ou
);
1537 for (i
=0 ; i
<depth
; i
++)
1539 fputs("images/sarg.png\" title=\"SARG, Squid Analysis Report Generator. Logo by Osamu Matsuzaki\" alt=\"Sarg\"></a> Squid Analysis Report Generator</div>\n",fp_ou
);
1542 void write_logo_image(FILE *fp_ou
)
1544 if(LogoImage
[0]!='\0')
1545 fprintf(fp_ou
, "<div class=\"logo\"><img src=\"%s\" width=\"%s\" height=\"%s\" alt=\"Logo\"> %s</div>\n",LogoImage
,Width
,Height
,LogoText
);
1548 void write_html_head(FILE *fp_ou
, int depth
, const char *page_title
,int javascript
)
1552 fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n<html>\n",fp_ou
);
1553 fprintf(fp_ou
, "<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n",CharSet
);
1554 if (page_title
) fprintf(fp_ou
,"<title>%s</title>\n",page_title
);
1556 if ((javascript
& HTML_JS_SORTTABLE
)!=0 && SortTableJs
[0]) {
1557 fputs("<script type=\"text/javascript\" src=\"",fp_ou
);
1558 if (strncmp(SortTableJs
,"../",3)==0) {
1559 for (i
=0 ; i
<depth
; i
++) fputs("../",fp_ou
);
1561 fputs(SortTableJs
,fp_ou
);
1562 fputs("\"></script>\n",fp_ou
);
1564 fputs("</head>\n<body>\n",fp_ou
);
1567 void write_html_header(FILE *fp_ou
, int depth
, const char *page_title
,int javascript
)
1569 write_html_head(fp_ou
,depth
,page_title
,javascript
);
1570 write_logo_image(fp_ou
);
1571 show_sarg(fp_ou
, depth
);
1572 fprintf(fp_ou
,"<div class=\"title\"><table cellpadding=\"0\" cellspacing=\"0\">\n<tr><th class=\"title_c\">%s</th></tr>\n",Title
);
1575 void close_html_header(FILE *fp_ou
)
1577 fputs("</table></div>\n",fp_ou
);
1580 int write_html_trailer(FILE *fp_ou
)
1583 if (fputs("</body>\n</html>\n",fp_ou
)==EOF
) return(-1);
1587 void output_html_string(FILE *fp_ou
,const char *str
,int maxlen
)
1591 while (*str
&& (maxlen
<=0 || i
<maxlen
)) {
1594 fputs("&",fp_ou
);
1597 fputs("<",fp_ou
);
1600 fputs(">",fp_ou
);
1603 fputs(""",fp_ou
);
1606 fputs("'",fp_ou
);
1614 if (maxlen
>0 && i
>=maxlen
)
1615 fputs("…",fp_ou
);
1618 void output_html_url(FILE *fp_ou
,const char *url
)
1622 fputs("&",fp_ou
);
1629 void url_hostname(const char *url
,char *hostname
,int hostsize
)
1634 for (i
=0 ; i
<hostsize
&& url
[i
] && url
[i
]!='/' ; i
++)
1639 void url_module(const char *url
, char *w2
)
1645 for(x
=strlen(url
)-1; x
>=0; x
--) {
1646 if(url
[x
] == '/' || y
>=sizeof(w
)-1) break;
1655 for(y
=y
-1; y
>=0; y
--) {
1661 void url_to_file(const char *url
,char *file
,int filesize
)
1667 for(i
=0; i
<filesize
&& *url
; url
++) {
1668 if(isalnum(*url
) || *url
=='-' || *url
=='_' || *url
=='.' || *url
=='%') {
1672 if (!skip
) file
[i
++]='_';
1681 printf(_("SARG Version: %s\n"),VERSION
);
1685 char *get_param_value(const char *param
,char *line
)
1689 while (*line
==' ' || *line
=='\t') line
++;
1691 if (strncasecmp(line
,param
,plen
)) return(NULL
);
1692 if (line
[plen
]!=' ' && line
[plen
]!='\t') return(NULL
);
1694 while (*line
==' ' || *line
=='\t') line
++;
1698 void unlinkdir(const char *dir
,int contentonly
)
1702 struct dirent
*direntp
;
1708 while ((direntp
= readdir(dirp
)) != NULL
) {
1709 if (direntp
->d_name
[0] == '.' && (direntp
->d_name
[1] == '\0' ||
1710 (direntp
->d_name
[1] == '.' && direntp
->d_name
[2] == '\0')))
1712 if (snprintf(dname
,sizeof(dname
),"%s/%s",dir
,direntp
->d_name
)>=sizeof(dname
)) {
1713 debuga(_("directory name to delete too long: %s/%s\n"),dir
,direntp
->d_name
);
1717 err
=lstat(dname
,&st
);
1719 err
=stat(dname
,&st
);
1722 debuga(_("cannot stat %s\n"),dname
);
1725 if (S_ISREG(st
.st_mode
)) {
1726 if (unlink(dname
)) {
1727 debuga(_("cannot delete %s - %s\n"),dname
,strerror(errno
));
1730 } else if (S_ISDIR(st
.st_mode
)) {
1733 debuga(_("unknown path type %s\n"),dname
);
1740 debuga(_("cannot delete %s - %s\n"),dir
,strerror(errno
));