]>
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 /*void fgetword(char *word, char *line, int stop)
49 for (x=0; line[x] && (line[x] != stop); x++) word[x] = line[x];
56 tchar = strchr(line, stop);
57 if (tchar == NULL) strcpy(word, line);
60 difflen = tchar - line;
61 strncpy(word, line, difflen);
66 #if USE_GETWORD_BACKTRACE
67 static void getword_backtrace(void)
73 n
=backtrace(buffer
,sizeof(buffer
)/sizeof(buffer
[0]));
75 calls
=backtrace_symbols(buffer
,n
);
77 debuga(_("getword backtrace:\n"));
78 for (i
=0 ; i
<n
; i
++) {
79 fprintf(stderr
,"SARG: %d:%s\n",i
+1,calls
[i
]);
84 #endif //USE_GETWORD_BACKTRACE
86 void getword_start(struct getwordstruct
*gwarea
, const char *line
)
88 gwarea
->beginning
=line
;
93 void getword_restart(struct getwordstruct
*gwarea
)
95 if (gwarea
->modified
) {
96 debuga(_("Cannot parse again the line as it was modified\n"));
99 gwarea
->current
=gwarea
->beginning
;
102 int getword(char *word
, int limit
, struct getwordstruct
*gwarea
, char stop
)
106 for(x
=0;((gwarea
->current
[x
]) && (gwarea
->current
[x
] != stop
));x
++) {
108 printf("SARG: getword loop detected after %d bytes.\n",x
);
109 printf("SARG: Line=\"%s\"\n",gwarea
->beginning
);
110 printf("SARG: Record=\"%s\"\n",gwarea
->current
);
111 printf("SARG: searching for \'x%x\'\n",stop
);
112 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
113 word
[(limit
>0) ? limit
-1 : 0]='\0';
114 #if USE_GETWORD_BACKTRACE
119 word
[x
] = gwarea
->current
[x
];
123 if (gwarea
->current
[x
]) ++x
;
128 int getword_limit(char *word
, int limit
, struct getwordstruct
*gwarea
, char stop
)
133 for(x
=0; x
<limit
&& gwarea
->current
[x
] && gwarea
->current
[x
] != stop
;x
++) {
134 word
[x
] = gwarea
->current
[x
];
138 while (*gwarea
->current
&& *gwarea
->current
!= stop
) gwarea
->current
++;
139 if (*gwarea
->current
) ++gwarea
->current
;
143 int getword_multisep(char *word
, int limit
, struct getwordstruct
*gwarea
, char stop
)
147 for(x
=0;((gwarea
->current
[x
]) && (gwarea
->current
[x
] != stop
));x
++) {
149 printf("SARG: getword_multisep loop detected.\n");
150 printf("SARG: Line=\"%s\"\n",gwarea
->beginning
);
151 printf("SARG: Record=\"%s\"\n",gwarea
->current
);
152 printf("SARG: searching for \'x%x\'\n",stop
);
153 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
154 if (limit
>0) word
[limit
-1]='\0';
155 #if USE_GETWORD_BACKTRACE
158 //exit(EXIT_FAILURE);
161 word
[x
] = gwarea
->current
[x
];
165 while (gwarea
->current
[x
] && gwarea
->current
[x
]==stop
) ++x
;
170 int getword_skip(int limit
, struct getwordstruct
*gwarea
, char stop
)
174 for(x
=0;(gwarea
->current
[x
] && (gwarea
->current
[x
] != stop
));x
++) {
176 printf("SARG: getword_skip loop detected after %d bytes.\n",x
);
177 printf("SARG: Line=\"%s\"\n",gwarea
->beginning
);
178 printf("SARG: Record=\"%s\"\n",gwarea
->current
);
179 printf("SARG: searching for \'x%x\'\n",stop
);
180 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
181 #if USE_GETWORD_BACKTRACE
188 if (gwarea
->current
[x
]) ++x
;
193 int getword_atoll(long long int *number
, struct getwordstruct
*gwarea
, char stop
)
198 if (gwarea
->current
[0] == '-') {
201 } else if (gwarea
->current
[0] == '+') {
205 for(x
=0;isdigit(gwarea
->current
[x
]);x
++) {
206 *number
=(*number
* 10) + gwarea
->current
[x
]-'0';
208 if(gwarea
->current
[x
] && gwarea
->current
[x
]!=stop
) {
209 printf("SARG: getword_atoll loop detected after %d bytes.\n",x
);
210 printf("SARG: Line=\"%s\"\n",gwarea
->beginning
);
211 printf("SARG: Record=\"%s\"\n",gwarea
->current
);
212 printf("SARG: searching for \'x%x\'\n",stop
);
213 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
214 #if USE_GETWORD_BACKTRACE
221 if (gwarea
->current
[x
]) ++x
;
227 int getword_ptr(char *orig_line
,char **word
, struct getwordstruct
*gwarea
, char stop
)
230 \note Why pass the original buffer to the function ? Because we must modify it to
231 insert the terminating ASCII zero for the word we return and that's not compatible
232 with getword_restart(). Moreover, getword_start() sometime works on constant strings
233 so this function require the original buffer to detect any missuse.
239 if (orig_line
&& orig_line
!=gwarea
->beginning
) {
240 debuga(_("Invalid buffer passed to getword_ptr\n"));
244 start
=(gwarea
->current
-gwarea
->beginning
);
245 if (word
&& orig_line
) *word
=orig_line
+start
;
246 for(x
=0;((gwarea
->current
[x
]) && (gwarea
->current
[x
] != stop
));x
++);
247 sep
=(gwarea
->current
[x
]!='\0');
248 if (word
&& orig_line
) orig_line
[start
+x
] = '\0';
255 #define MAXLLL 30 //!< Maximum number of digits in long long (a guess).
256 long long int my_atoll (const char *nptr
)
258 long long int returnval
=0LL;
259 int max_digits
= MAXLLL
;
261 // Soak up all the white space
262 while (isspace( *nptr
)) {
266 //For each character left to right
267 //change the character to a single digit
268 //multiply what we had before by 10 and add the new digit
270 while (--max_digits
&& isdigit( *nptr
))
272 returnval
= ( returnval
* 10 ) + ( *nptr
++ - '0' ) ;
278 int is_absolute(const char *path
)
280 if (*path
=='/') return(1);
282 if (isalpha(path
[0]) && path
[1]==':') return(1);
287 void my_mkdir(const char *name
)
293 if(!is_absolute(name
)) {
294 debuga(_("Invalid path (%s). Please, use absolute paths only.\n"),name
);
295 debuga(_("process aborted.\n"));
300 for (i
=0 ; name
[i
] ; i
++) {
302 debuga(_("directory name too long: %s\n"),name
);
305 if (chars
>0 && name
[i
] == '/') {
307 if(access(w0
, R_OK
) != 0) {
309 debuga(_("mkdir %s %s\n"),w0
,strerror(errno
));
310 debuga(_("process aborted.\n"));
315 if (name
[i
] != '/') chars
++;
319 if(access(name
, R_OK
) != 0) {
320 if(mkdir(name
,0755)) {
321 debuga(_("mkdir %s %s\n"),name
,strerror(errno
));
322 debuga(_("process aborted.\n"));
329 void my_lltoa(unsigned long long int n
, char *s
, int ssize
, int len
)
338 debuga(_("The requested number of digits passed to my_lltoa (%d) is bigger than the output buffer size (%d)\n"),len
,ssize
);
343 s
[slen
++] = (n
% 10) + '0';
344 } while ((n
/= 10) > 0 && slen
<ssize
);
347 for (i
= 0, j
= slen
-1; i
<j
; i
++, j
--) {
355 for(j
=slen
; j
>=0; j
--)
362 int month2num(const char *month
)
366 for(m
=0 ; m
<12 && strcmp(mtab1
[m
],month
) != 0; m
++);
370 int builddia(int day
, int month
, int year
)
372 return(year
*10000+month
*100+day
);
376 void buildymd(const char *dia
, const char *mes
, const char *ano
, char *wdata
)
381 sprintf(wdata
,"%04d%02d%02d",atoi(ano
),nmes
+1,atoi(dia
));
385 int conv_month(const char *month
)
389 for(x
=0; x
<12 && strncmp(mtab1
[x
],month
,3)!=0; x
++);
394 const char *conv_month_name(int month
)
398 if (month
<1 || month
>12) {
399 snprintf(str
,sizeof(str
),"%03d",month
);
402 return(mtab1
[month
-1]);
406 void name_month(char *month
,int month_len
)
408 int x
, z
=atoi(month
)-1;
411 struct getwordstruct gwarea
;
413 strcpy(m
,_("January,February,March,April,May,June,July,August,September,October,November,December"));
414 getword_start(&gwarea
,m
);
417 if (getword_multisep(w
,sizeof(w
),&gwarea
,',')<0) {
418 printf("SARG: Maybe you have a broken record or garbage in the names of the months.\n");
421 if (getword_multisep(month
,month_len
,&gwarea
,',')<0) {
422 printf("SARG: Maybe you have a broken record or garbage in the name of the months.\n");
428 void debuga(const char *msg
,...)
432 fputs(_("SARG: "),stderr
);
434 vfprintf(stderr
,msg
,ap
);
439 void debugaz(const char *head
, const char *msg
)
441 fprintf(stderr
, "SARG: (util) %s=%s\n",head
, msg
);
446 char *fixnum(long long int value
, int n
)
448 #define MAXLEN_FIXNUM 256
449 char num
[MAXLEN_FIXNUM
]="";
450 char buf
[MAXLEN_FIXNUM
* 2];
452 static char ret
[MAXLEN_FIXNUM
* 2];
454 register int i
, j
, k
;
456 static char abbrev
[30];
458 my_lltoa(value
, num
, sizeof(num
), 0);
460 if(DisplayedValues
==DISPLAY_ABBREV
) {
461 numlen
= strlen(num
);
463 sprintf(abbrev
,"%s",num
);
464 if(numlen
== 4 || numlen
== 7 || numlen
== 10 || numlen
== 13) {
465 snprintf(abbrev
,2,"%s",num
);
466 strncat(abbrev
,".",1);
467 strncat(abbrev
,num
+1,2);
468 if(!n
) return(abbrev
);
470 strncat(abbrev
,"K",1);
472 strncat(abbrev
,"M",1);
473 else if(numlen
== 10)
474 strncat(abbrev
,"G",1);
475 else if(numlen
== 13)
476 strncat(abbrev
,"T",1);
478 if(numlen
== 5 || numlen
== 8 || numlen
== 11 || numlen
== 14) {
479 snprintf(abbrev
,3,"%s",num
);
480 strncat(abbrev
,".",1);
481 strncat(abbrev
,num
+2,2);
482 if(!n
) return(abbrev
);
484 strncat(abbrev
,"K",1);
486 strncat(abbrev
,"M",1);
487 else if(numlen
== 11)
488 strncat(abbrev
,"G",1);
489 else if(numlen
== 14)
490 strncat(abbrev
,"T",1);
492 if(numlen
== 6 || numlen
== 9 || numlen
== 12 || numlen
== 15) {
493 snprintf(abbrev
,4,"%s",num
);
494 strncat(abbrev
,".",1);
495 strncat(abbrev
,num
+3,2);
496 if(!n
) return(abbrev
);
498 strncat(abbrev
,"K",1);
500 strncat(abbrev
,"M",1);
501 else if(numlen
== 12)
502 strncat(abbrev
,"G",1);
503 else if(numlen
== 15)
504 strncat(abbrev
,"T",1);
510 bzero(buf
, MAXLEN_FIXNUM
*2);
516 for ( i
= strlen(num
) - 1, j
= 0 ; i
> -1; i
--) {
517 if ( k
== 2 && i
!= 0 ) {
520 pbuf
[j
++] = (UseComma
) ? ',' : '.';
530 for ( i
= strlen(pbuf
) - 1, j
= 0 ; i
> -1; i
--, j
++)
539 char *fixnum2(long long int value
, int n
)
541 #define MAXLEN_FIXNUM2 1024
542 char num
[MAXLEN_FIXNUM2
];
543 char buf
[MAXLEN_FIXNUM2
* 2];
545 static char ret
[MAXLEN_FIXNUM2
* 2];
547 register int i
, j
, k
;
549 my_lltoa(value
, num
, sizeof(num
), 0);
550 bzero(buf
, MAXLEN_FIXNUM2
*2);
556 for ( i
= strlen(num
) - 1, j
= 0 ; i
> -1; i
--) {
557 if ( k
== 2 && i
!= 0 ) {
560 pbuf
[j
++] = (UseComma
) ? ',' : '.';
570 for ( i
= strlen(pbuf
) - 1, j
= 0 ; i
> -1; i
--, j
++)
579 char *buildtime(long long int elap
)
582 int num
= elap
/ 1000;
591 min
=(num
% 3600) / 60;
593 sprintf(buf
,"%02d:%02d:%02d",hor
,min
,sec
);
600 void obtdate(const char *dirname
, const char *name
, char *data
)
606 sprintf(wdir
,"%s%s/sarg-date",dirname
,name
);
607 if ((fp_in
= fopen(wdir
, "rt")) == 0) {
608 sprintf(wdir
,"%s%s/date",dirname
,name
);
609 if ((fp_in
= fopen(wdir
, "rt")) == 0) {
615 if (!fgets(data
,80,fp_in
)) {
616 debuga(_("Failed to read the date in %s\n"),wdir
);
627 void formatdate(char *date
,int date_size
,int year
,int month
,int day
,int hour
,int minute
,int second
,int dst
)
633 memset(<m
,0,sizeof(ltm
));
634 if (year
>=1900) ltm
.tm_year
=year
-1900;
635 if (month
>=1 && month
<=12) ltm
.tm_mon
=month
-1;
636 if (day
>=1 && day
<=31) ltm
.tm_mday
=day
;
637 if (hour
>=0 && hour
<24) ltm
.tm_hour
=hour
;
638 if (minute
>=0 && minute
<60) ltm
.tm_min
=minute
;
639 if (second
>=0 && second
<60) ltm
.tm_sec
=second
;
641 unixtime
=mktime(<m
); //fill the missing entries
642 fulltm
=localtime(&unixtime
);
643 //strftime(date,date_size,"%a %b %d %H:%M:%S %Z %Y",fulltm);
644 strftime(date
,date_size
,"%c",fulltm
);
648 void computedate(int year
,int month
,int day
,struct tm
*t
)
650 memset(t
,0,sizeof(*t
));
651 t
->tm_year
=year
-1900;
657 int obtuser(const char *dirname
, const char *name
)
665 sprintf(wdir
,"%s%s/sarg-users",dirname
,name
);
666 if((fp_in
=fopen(wdir
,"r"))==NULL
) {
667 sprintf(wdir
,"%s%s/users",dirname
,name
);
668 if((fp_in
=fopen(wdir
,"r"))==NULL
) {
673 if (!fgets(tuser
,sizeof(tuser
),fp_in
)) {
674 debuga(_("Failed to read the number of users in %s\n"),wdir
);
684 void obttotal(const char *dirname
, const char *name
, int nuser
, long long int *tbytes
, long long int *media
)
689 char user
[MAX_USER_LEN
];
691 struct getwordstruct gwarea
;
697 sprintf(wdir
,"%s%s/sarg-general",dirname
,name
);
698 if ((fp_in
= fopen(wdir
, "r")) == 0) {
699 sprintf(wdir
,"%s%s/general",dirname
,name
);
700 if ((fp_in
= fopen(wdir
, "r")) == 0) {
705 if ((line
=longline_create())==NULL
) {
706 debuga(_("Not enough memory to read the file %s\n"),wdir
);
710 while((buf
=longline_read(fp_in
,line
))!=NULL
) {
711 if (strncmp(buf
,"TOTAL\t",6) == 0)
713 else if (strncmp(buf
,"TOTAL ",6) == 0)
717 getword_start(&gwarea
,buf
);
718 if (getword(user
,sizeof(user
),&gwarea
,sep
)<0) {
719 debuga(_("There is a invalid user in file %s\n"),wdir
);
722 if(strcmp(user
,"TOTAL") != 0)
724 if (getword_skip(MAXLEN
,&gwarea
,sep
)<0) {
725 debuga(_("There a broken total number of access in file %s\n"),wdir
);
728 if (getword_atoll(tbytes
,&gwarea
,sep
)<0) {
729 debuga(_("There is a broken number of bytes in file %s\n"),wdir
);
735 longline_destroy(&line
);
740 *media
=*tbytes
/ nuser
;
744 int getperiod_fromsarglog(const char *arqtt
,struct periodstruct
*period
)
747 int day0
, month0
, year0
, hour0
, minute0
;
748 int day1
, month1
, year1
, hour1
, minute1
;
752 memset(period
,0,sizeof(*period
));
755 while((str
=strstr(str
,"sarg-"))!=NULL
) {
757 if (!isdigit(str
[0]) || !isdigit(str
[1])) continue;
758 day0
=(str
[0]-'0')*10+(str
[1]-'0');
760 strncpy(month
,str
,3);
762 month0
=month2num(month
);
763 if (month0
>=12) continue;
766 for (i
=0 ; isdigit(str
[i
]) && i
<4 ; i
++) year0
=year0
*10+(str
[i
]-'0');
769 if (str
[0]!='_') continue;
772 if (!isdigit(str
[0]) || !isdigit(str
[1])) continue;
773 hour0
=(str
[0]-'0')*10+(str
[1]-'0');
775 if (!isdigit(str
[0]) || !isdigit(str
[1])) continue;
776 minute0
=(str
[0]-'0')*10+(str
[1]-'0');
779 if (*str
!= '-') continue;
782 if (!isdigit(str
[0]) || !isdigit(str
[1])) continue;
783 day1
=(str
[0]-'0')*10+(str
[1]-'0');
785 strncpy(month
,str
,3);
787 month1
=month2num(month
);
788 if (month1
>=12) continue;
791 for (i
=0 ; isdigit(str
[i
]) && i
<4 ; i
++) year1
=year1
*10+(str
[i
]-'0');
795 if (str
[0]!='_') continue;
798 if (!isdigit(str
[0]) || !isdigit(str
[1])) continue;
799 hour1
=(str
[0]-'0')*10+(str
[1]-'0');
801 if (!isdigit(str
[0]) || !isdigit(str
[1])) continue;
802 minute1
=(str
[0]-'0')*10+(str
[1]-'0');
805 period
->start
.tm_mday
=day0
;
806 period
->start
.tm_mon
=month0
;
807 period
->start
.tm_year
=year0
-1900;
808 period
->start
.tm_hour
=hour0
;
809 period
->start
.tm_min
=minute0
;
810 period
->end
.tm_mday
=day1
;
811 period
->end
.tm_mon
=month1
;
812 period
->end
.tm_year
=year1
-1900;
813 period
->end
.tm_hour
=hour1
;
814 period
->end
.tm_min
=minute1
;
820 void getperiod_fromrange(struct periodstruct
*period
,int dfrom
,int duntil
)
822 memset(&period
->start
,0,sizeof(period
->start
));
823 period
->start
.tm_mday
=dfrom
%100;
824 period
->start
.tm_mon
=(dfrom
/100)%100-1;
825 period
->start
.tm_year
=(dfrom
/10000)-1900;
827 memset(&period
->end
,0,sizeof(period
->end
));
828 period
->end
.tm_mday
=duntil
%100;
829 period
->end
.tm_mon
=(duntil
/100)%100-1;
830 period
->end
.tm_year
=(duntil
/10000)-1900;
833 int getperiod_buildtext(struct periodstruct
*period
)
837 char text1
[40], text2
[40];
840 i
=strftime(text1
, sizeof(text1
), "%Y %b %d", &period
->start
);
841 }else if(df
[0]=='e') {
842 i
=strftime(text1
, sizeof(text1
), "%d %b %Y", &period
->start
);
843 } else /*if(df[0]=='w')*/ {
844 IndexTree
=INDEX_TREE_FILE
;
845 i
=strftime(text1
, sizeof(text1
), "%Y.%U", &period
->start
);
847 if (i
== 0) return(-1);
849 range
=(period
->start
.tm_year
!=period
->end
.tm_year
||
850 period
->start
.tm_mon
!=period
->end
.tm_mon
||
851 period
->start
.tm_mday
!=period
->end
.tm_mday
);
854 i
=strftime(text2
, sizeof(text2
)-i
, "%Y %b %d", &period
->end
);
855 } else if(df
[0]=='e') {
856 i
=strftime(text2
, sizeof(text2
)-i
, "%d %b %Y", &period
->end
);
858 i
=strftime(text2
, sizeof(text2
)-i
, "%Y.%U", &period
->end
);
860 if (i
== 0) return(-1);
864 snprintf(period
->text
,sizeof(period
->text
),"%s-%s",text1
,text2
);
865 snprintf(period
->html
,sizeof(period
->html
),"%s—%s",text1
,text2
);
867 strncpy(period
->text
,text1
,sizeof(period
->text
)-1);
868 period
->text
[sizeof(period
->text
)-1]='\0';
869 strncpy(period
->html
,text1
,sizeof(period
->html
)-1);
870 period
->html
[sizeof(period
->html
)-1]='\0';
875 static void copy_images(void)
877 FILE *img_in
, *img_ou
;
880 char srcfile
[MAXLEN
];
881 char dstfile
[MAXLEN
];
883 struct dirent
*direntp
;
888 if (snprintf(images
,sizeof(images
),"%simages",outdir
)>=sizeof(images
)) {
889 debuga(_("Cannot copy images to target directory %simages\n"),outdir
);
892 if (access(images
,R_OK
)!=0) {
896 strcpy(imgdir
,IMAGEDIR
);
897 dirp
= opendir(imgdir
);
899 debuga(_("(util) Can't open directory %s: %s\n"),imgdir
,strerror(errno
));
902 while ((direntp
= readdir( dirp
)) != NULL
){
903 if(direntp
->d_name
[0]=='.')
905 sprintf(srcfile
,"%s/%s",imgdir
,direntp
->d_name
);
906 if (stat(srcfile
,&info
)) {
907 debuga(_("Cannot stat \"%s\" - %s\n"),srcfile
,strerror(errno
));
910 if (S_ISREG(info
.st_mode
)) {
911 sprintf(dstfile
,"%s/%s",images
,direntp
->d_name
);
912 img_in
= fopen(srcfile
, "rb");
914 img_ou
= fopen(dstfile
, "wb");
916 while ((nread
= fread(buffer
,1,sizeof(buffer
),img_in
))>0) {
917 if (fwrite(buffer
,1,nread
,img_ou
)!=nread
) {
918 debuga(_("Failed to copy image %s to %s\n"),srcfile
,dstfile
);
924 fprintf(stderr
,"SARG: (util): %s %s: %s\n", _("Cannot open file")?_("Cannot open file"):"Can't open/create file", dstfile
, strerror(errno
));
927 fprintf(stderr
,"SARG: (util): %s %s: %s\n", _("Cannot open file")?_("Cannot open file"):"Can't open file", srcfile
, strerror(errno
));
930 (void) closedir(dirp
);
935 int vrfydir(const struct periodstruct
*per1
, const char *addr
, const char *site
, const char *us
, const char *form
)
940 char dirname2
[MAXLEN
];
950 y1
=per1
->start
.tm_year
+1900;
951 y2
=per1
->end
.tm_year
+1900;
952 m1
=per1
->start
.tm_mon
+1;
953 m2
=per1
->end
.tm_mon
+1;
954 d1
=per1
->start
.tm_mday
;
955 d2
=per1
->end
.tm_mday
;
956 if(IndexTree
== INDEX_TREE_DATE
) {
957 wlen
+=sprintf(wdir
+wlen
,"%04d",y1
);
958 if(y1
!=y2
) wlen
+=sprintf(wdir
+wlen
,"-%04d",y2
);
959 if(access(wdir
, R_OK
) != 0)
962 wlen
+=sprintf(wdir
+wlen
,"/%02d",m1
);
963 if(m1
!= m2
) wlen
+=sprintf(wdir
+wlen
,"-%02d",m2
);
964 if(access(wdir
, R_OK
) != 0)
967 wlen
+=sprintf(wdir
+wlen
,"/%02d",d1
);
968 if(d1
!=d2
) wlen
+=sprintf(wdir
+wlen
,"-%02d",d2
);
971 wlen
=snprintf(wdir
+wlen
,sizeof(wdir
)-wlen
,"%04d%s%02d-%04d%s%02d",y1
,
972 conv_month_name(m1
),d1
,y2
,conv_month_name(m2
),d2
);
973 } else if(df
[0] == 'e') {
974 wlen
=snprintf(wdir
+wlen
,sizeof(wdir
)-wlen
,"%02d%s%04d-%02d%s%04d",d1
,
975 conv_month_name(m1
),y1
,d2
,conv_month_name(m2
),y2
);
976 } else if(df
[0] == 'w') {
977 wlen2
=strftime(wdir
+wlen
, sizeof(wdir
)-wlen
, "%Y.%U", &per1
->start
);
978 if (wlen2
==0) return(-1);
984 struct userinfostruct
*uinfo
=userinfo_find_from_id(us
);
987 strcat(wdir
,uinfo
->filename
);
990 if(addr
[0] != '\0') {
994 if(site
[0] != '\0') {
999 strcpy(outdirname
,wdir
);
1001 if(IndexTree
!= INDEX_TREE_DATE
) {
1002 if(!OverwriteReport
) {
1004 if(access(wdir
,R_OK
) == 0) {
1005 sprintf(wdir
,"%s.%d",outdirname
,num
);
1014 debuga(_("File %s already exists, moved to %s\n"),outdirname
,wdir
);
1015 rename(outdirname
,wdir
);
1018 if(access(outdirname
,R_OK
) == 0) {
1019 unlinkdir(outdirname
,1);
1022 my_mkdir(outdirname
);
1024 strcpy(dirname2
,wdir
);
1025 if(!OverwriteReport
) {
1027 if(access(wdir
,R_OK
) == 0) {
1028 sprintf(wdir
,"%s.%d",dirname2
,num
);
1037 debuga(_("File %s already exists, moved to %s\n"),dirname2
,wdir
);
1038 rename(dirname2
,wdir
);
1039 strcpy(dirname2
,wdir
);
1042 if(access(wdir
,R_OK
) == 0) {
1047 if(access(wdir
, R_OK
) != 0)
1051 strcpy(dirname2
,wdir
);
1053 sprintf(wdir
,"%s/sarg-date",outdirname
);
1054 if ((fp_ou
= fopen(wdir
, "wt")) == 0) {
1055 debuga(_("cannot open %s for writing\n"),wdir
);
1060 //strftime(wdir,sizeof(wdir),"%a %b %d %H:%M:%S %Z %Y",localtime(&curtime));
1061 loctm
=localtime(&curtime
);
1062 strftime(wdir
,sizeof(wdir
),"%Y-%m-%d %H:%M:%S",loctm
);
1063 if (fprintf(fp_ou
,"%s %d\n",wdir
,loctm
->tm_isdst
)<0) {
1064 debuga(_("Failed to write the date in %s\n"),wdir
);
1068 if (fclose(fp_ou
)==EOF
) {
1069 debuga(_("Failed to write the date in %s\n"),wdir
);
1078 void strip_latin(char *line
)
1085 for (i
=0;line
[i
];i
++){
1087 if (line
[i
]==';') skip
=0;
1100 void zdate(char *ftime
,int ftimesize
, const char *DateFormat
)
1107 local
= localtime(&t
);
1108 if(strcmp(DateFormat
,"u") == 0)
1109 strftime(ftime
, ftimesize
, "%b/%d/%Y %H:%M", local
);
1110 if(strcmp(DateFormat
,"e") == 0)
1111 strftime(ftime
, ftimesize
, "%d/%b/%Y-%H:%M", local
);
1112 if(strcmp(DateFormat
,"w") == 0)
1113 strftime(ftime
, ftimesize
, "%W-%H-%M", local
);
1118 char *fixtime(long long int elap
)
1120 int num
= elap
/ 1000;
1124 static char buf
[12];
1127 min
=(num
% 3600) / 60;
1130 if(hor
==0 && min
==0 && sec
==0)
1133 sprintf(buf
,"%d:%02d:%02d",hor
,min
,sec
);
1139 void date_from(char *date
, int *dfrom
, int *duntil
)
1148 if (isdigit(date
[0])) {
1151 if (sscanf(date
,"%d/%d/%d%n",&d0
,&m0
,&y0
,&next
)!=3 || y0
<100 || m0
<1 || m0
>12 || d0
<1 || d0
>31 || next
<0) {
1152 debuga(_("The date passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n"));
1155 if (date
[next
]=='-') {
1156 if (sscanf(date
+next
+1,"%d/%d/%d",&d1
,&m1
,&y1
)!=3 || y1
<100 || m1
<1 || m1
>12 || d1
<1 || d1
>31) {
1157 debuga(_("The date range passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n"));
1160 } else if (date
[next
]!='\0') {
1161 debuga(_("The date range passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n"));
1171 struct tm
*Date0
,Date1
;
1173 if (time(&Today
)==(time_t)-1) {
1174 debuga(_("Failed to get the current time\n"));
1177 if (sscanf(date
,"day-%d",&i
)==1) {
1179 debuga(_("Invalid number of days in -d parameter\n"));
1183 Date0
=localtime(&Today
);
1185 debuga(_("Cannot convert local time: %s\n"),strerror(errno
));
1188 y0
=y1
=Date0
->tm_year
+1900;
1189 m0
=m1
=Date0
->tm_mon
+1;
1190 d0
=d1
=Date0
->tm_mday
;
1191 } else if (sscanf(date
,"week-%d",&i
)==1) {
1193 There is no portable way to find the first day of the week even though the
1194 information is available in the locale. nl_langinfo has the unofficial
1195 parameters _NL_TIME_FIRST_WEEKDAY and _NL_TIME_WEEK_1STDAY but they are
1196 undocumented as is their return value and it is discouraged to use them.
1197 Beside, nl_langinfo isn't available on windows and the first day of the
1198 week isn't available at all on that system.
1200 const int FirstWeekDay
=1;
1204 debuga(_("Invalid number of weeks in -d parameter\n"));
1207 Date0
=localtime(&Today
);
1209 debuga(_("Cannot convert local time: %s\n"),strerror(errno
));
1212 WeekBegin
=Today
-((Date0
->tm_wday
-FirstWeekDay
+7)%7)*24*60*60;
1213 WeekBegin
-=i
*7*24*60*60;
1214 Date0
=localtime(&WeekBegin
);
1216 debuga(_("Cannot convert local time: %s\n"),strerror(errno
));
1219 y0
=Date0
->tm_year
+1900;
1222 WeekBegin
+=6*24*60*60;
1223 Date0
=localtime(&WeekBegin
);
1225 debuga(_("Cannot convert local time: %s\n"),strerror(errno
));
1228 y1
=Date0
->tm_year
+1900;
1231 } else if (sscanf(date
,"month-%d",&i
)==1) {
1233 debuga(_("Invalid number of months in -d parameter\n"));
1236 Date0
=localtime(&Today
);
1238 debuga(_("Cannot convert local time: %s\n"),strerror(errno
));
1241 if (Date0
->tm_mon
<i
%12) {
1242 y0
=Date0
->tm_year
+1900-i
/12-1;
1243 m0
=(Date0
->tm_mon
+12-i
%12)%12+1;
1246 y0
=Date0
->tm_year
+1900-i
/12;
1247 m0
=Date0
->tm_mon
-i
%12+1;
1250 memcpy(&Date1
,Date0
,sizeof(struct tm
));
1255 Date1
.tm_year
=y0
-1900;
1258 Date1
.tm_year
=y0
-1900+1;
1262 Date0
=localtime(&t1
);
1263 y1
=Date0
->tm_year
+1900;
1267 debuga(_("Invalid date range passed on command line\n"));
1272 *dfrom
=y0
*10000+m0
*100+d0
;
1273 *duntil
=y1
*10000+m1
*100+d1
;
1274 sprintf(date
,"%02d/%02d/%04d-%02d/%02d/%04d",d0
,m0
,y0
,d1
,m1
,y1
);
1279 char *strlow(char *string
)
1285 for (s
= string
; *s
; ++s
)
1295 char *strup(char *string
)
1301 for (s
= string
; *s
; ++s
)
1309 void removetmp(const char *outdir
)
1316 if(!RemoveTempFiles
)
1320 debuga(_("Purging temporary file sarg-general\n"));
1322 if (snprintf(warea
,sizeof(warea
),"%s/sarg-general",outdir
)>=sizeof(warea
)) {
1323 debuga(_("(removetmp) directory too long to remove %s/sarg-period\n"),outdir
);
1326 if((fp_in
=fopen(warea
,"r+"))==NULL
){
1327 debuga(_("(removetmp) Cannot open file %s\n"),warea
);
1330 while(fgets(buf
,sizeof(buf
),fp_in
)!=NULL
) {
1331 if(strncmp(buf
,"TOTAL",5) == 0 && (buf
[6]=='\t' || buf
[6]==' '))
1334 if (fseek(fp_in
,0,SEEK_SET
)==-1) {
1335 debuga(_("Failed to rewind to the beginning of the file %s: %s\n"),warea
,strerror(errno
));
1339 if (fputs(buf
,fp_in
)==EOF
) {
1340 debuga(_("Failed to write the total line in %s - %s\n"),warea
,strerror(errno
));
1344 if (pos
>0 && ftruncate(fileno(fp_in
),pos
)==-1) {
1345 debuga(_("Failed to truncate %s: %s\n"),warea
,strerror(errno
));
1348 if (fclose(fp_in
)==EOF
) {
1349 debuga(_("Failed to close %s after writing the total line - %s\n"),warea
,strerror(errno
));
1356 void load_excludecodes(const char *ExcludeCodes
)
1365 if(ExcludeCodes
[0] == '\0')
1368 if((fp_in
=fopen(ExcludeCodes
,"r"))==NULL
) {
1369 debuga(_("(util) Cannot open file %s (exclude_codes)\n"),ExcludeCodes
);
1373 if (fseek(fp_in
, 0, SEEK_END
)==-1) {
1374 debuga(_("Failed to move till the end of the excluded codes file %s: %s\n"),ExcludeCodes
,strerror(errno
));
1377 MemSize
= ftell(fp_in
);
1379 debuga(_("Cannot get the size of file %s\n"),ExcludeCodes
);
1382 if (fseek(fp_in
, 0, SEEK_SET
)==-1) {
1383 debuga(_("Failed to rewind the excluded codes file %s: %s\n"),ExcludeCodes
,strerror(errno
));
1388 if((excludecode
=(char *) malloc(MemSize
))==NULL
) {
1389 debuga(_("malloc error (%ld)\n"),MemSize
);
1392 memset(excludecode
,0,MemSize
);
1395 while(fgets(data
,sizeof(data
),fp_in
)!=NULL
) {
1396 if (data
[0]=='#') continue;
1397 for (i
=strlen(data
)-1 ; i
>=0 && (unsigned char)data
[i
]<=' ' ; i
--) data
[i
]='\0';
1399 if (Stored
+i
+2>=MemSize
) {
1400 debuga(_("Too many codes to exclude in file %s\n"),ExcludeCodes
);
1403 strcat(excludecode
,data
);
1404 strcat(excludecode
,";");
1412 void free_excludecodes(void)
1420 int vercode(const char *code
)
1425 if (excludecode
&& excludecode
[0]!='\0') {
1429 if (strncmp(code
,cod
,clen
)==0 && cod
[clen
]==';')
1431 cod
=strchr(cod
,';');
1438 void fixnone(char *str
)
1442 for (i
=strlen(str
)-1 ; i
>=0 && (unsigned char)str
[i
]<=' ' ; i
--);
1443 if(i
==3 && strncmp(str
,"none",4) == 0)
1449 void fixendofline(char *str
)
1453 for (i
=strlen(str
)-1 ; i
>=0 && (unsigned char)str
[i
]<=' ' ; i
--) str
[i
]=0;
1456 #ifdef LEGACY_TESTVALIDUSERCHAR
1457 int testvaliduserchar(const char *user
)
1463 for (y
=0; y
<strlen(UserInvalidChar
); y
++) {
1464 for (x
=0; x
<strlen(user
); x
++) {
1465 if(user
[x
] == UserInvalidChar
[y
])
1472 int testvaliduserchar(const char *user
)
1475 char * p_UserInvalidChar
= UserInvalidChar
;
1476 const char * p_user
;
1478 while( *p_UserInvalidChar
) {
1481 if( *p_UserInvalidChar
== *p_user
)
1485 p_UserInvalidChar
++ ;
1491 int compar( const void *a
, const void *b
)
1492 { if( *(int *)a
> *(int *)b
) return 1;
1493 if( *(int *)a
< *(int *)b
) return -1;
1497 int getnumlist( char *buf
, numlist
*list
, const int len
, const int maxvalue
)
1499 int i
, j
, d
, flag
, r1
, r2
;
1500 char *pbuf
, **bp
, *strbufs
[ 24 ];
1503 strtok( buf
, " \t" );
1504 for( *bp
= strtok( NULL
, "," ), list
->len
= 0; *bp
; *bp
= strtok( NULL
, "," ) ) {
1505 if( ++bp
>= &strbufs
[ 24 ] )
1512 for( i
= 0; i
< list
->len
; i
++ ) {
1513 if( strchr( strbufs
[ i
], '-' ) != 0 ) {
1514 pbuf
= strbufs
[ i
];
1515 strtok( pbuf
, "-" );
1516 pbuf
= strtok( NULL
, "\0" );
1517 r1
= atoi( strbufs
[ i
] );
1518 if( ( r2
= atoi( pbuf
) ) >= maxvalue
|| r1
>= r2
)
1520 if( i
+ d
+ ( r2
- r1
) + 1 <= len
) {
1521 for( j
= r1
; j
<= r2
; j
++ )
1522 list
->list
[ i
+ d
++ ] = j
;
1527 if( ( list
->list
[ i
+ d
] = atoi( strbufs
[ i
] ) ) >= maxvalue
)
1531 qsort( list
->list
, list
->len
, sizeof( int ), compar
);
1534 for( i
= 0; i
< list
->len
- 1; i
++ )
1535 if( list
->list
[ i
] == list
->list
[ i
+ 1 ] ) {
1536 for( j
= i
+ 1; j
< list
->len
; j
++ )
1537 list
->list
[ j
- 1 ] = list
->list
[ j
];
1547 char *get_size(const char *path
, const char *file
)
1550 static char response
[255];
1554 if (snprintf(cmd
,sizeof(cmd
),"du -skh %s%s",path
,file
)>=sizeof(cmd
)) {
1555 debuga(_("Cannot get disk space because the path %s%s is too long\n"),path
,file
);
1558 if ((fp
= popen(cmd
, "r")) == NULL
) {
1559 debuga(_("Cannot get disk space with command %s\n"),cmd
);
1562 if (!fgets(response
, sizeof(response
), fp
)) {
1563 debuga(_("Cannot get disk size with command %s\n"),cmd
);
1566 ptr
=strchr(response
,'\t');
1568 debuga(_("The command %s failed\n"),cmd
);
1577 void show_info(FILE *fp_ou
)
1581 if(!ShowSargInfo
) return;
1582 zdate(ftime
, sizeof(ftime
), DateFormat
);
1583 fprintf(fp_ou
,"<div class=\"info\">%s <a href='%s'>%s-%s</a> %s %s</div>\n",_("Generated by"),URL
,PGM
,VERSION
,_("on"),ftime
);
1586 void show_sarg(FILE *fp_ou
, int depth
)
1590 if(!ShowSargLogo
) return;
1591 fputs("<div class=\"logo\"><a href=\"http://sarg.sourceforge.net\"><img src=\"",fp_ou
);
1592 for (i
=0 ; i
<depth
; i
++)
1594 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
);
1597 void write_logo_image(FILE *fp_ou
)
1599 if(LogoImage
[0]!='\0')
1600 fprintf(fp_ou
, "<div class=\"logo\"><img src=\"%s\" width=\"%s\" height=\"%s\" alt=\"Logo\"> %s</div>\n",LogoImage
,Width
,Height
,LogoText
);
1603 void write_html_head(FILE *fp_ou
, int depth
, const char *page_title
,int javascript
)
1607 fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n<html>\n",fp_ou
);
1608 fprintf(fp_ou
, "<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n",CharSet
);
1609 if (page_title
) fprintf(fp_ou
,"<title>%s</title>\n",page_title
);
1611 if ((javascript
& HTML_JS_SORTTABLE
)!=0 && SortTableJs
[0]) {
1612 fputs("<script type=\"text/javascript\" src=\"",fp_ou
);
1613 if (strncmp(SortTableJs
,"../",3)==0) {
1614 for (i
=0 ; i
<depth
; i
++) fputs("../",fp_ou
);
1616 fputs(SortTableJs
,fp_ou
);
1617 fputs("\"></script>\n",fp_ou
);
1619 fputs("</head>\n<body>\n",fp_ou
);
1622 void write_html_header(FILE *fp_ou
, int depth
, const char *page_title
,int javascript
)
1624 write_html_head(fp_ou
,depth
,page_title
,javascript
);
1625 write_logo_image(fp_ou
);
1626 show_sarg(fp_ou
, depth
);
1627 fprintf(fp_ou
,"<div class=\"title\"><table cellpadding=\"0\" cellspacing=\"0\">\n<tr><th class=\"title_c\">%s</th></tr>\n",Title
);
1630 void close_html_header(FILE *fp_ou
)
1632 fputs("</table></div>\n",fp_ou
);
1635 int write_html_trailer(FILE *fp_ou
)
1638 if (fputs("</body>\n</html>\n",fp_ou
)==EOF
) return(-1);
1642 void output_html_string(FILE *fp_ou
,const char *str
,int maxlen
)
1646 while (*str
&& (maxlen
<=0 || i
<maxlen
)) {
1649 fputs("&",fp_ou
);
1652 fputs("<",fp_ou
);
1655 fputs(">",fp_ou
);
1658 fputs(""",fp_ou
);
1661 fputs("'",fp_ou
);
1669 if (maxlen
>0 && i
>=maxlen
)
1670 fputs("…",fp_ou
);
1673 void output_html_url(FILE *fp_ou
,const char *url
)
1677 fputs("&",fp_ou
);
1684 void url_hostname(const char *url
,char *hostname
,int hostsize
)
1689 for (i
=0 ; i
<hostsize
&& url
[i
] && url
[i
]!='/' ; i
++)
1694 void url_module(const char *url
, char *w2
)
1700 for(x
=strlen(url
)-1; x
>=0; x
--) {
1701 if(url
[x
] == '/' || y
>=sizeof(w
)-1) break;
1710 for(y
=y
-1; y
>=0; y
--) {
1716 void url_to_file(const char *url
,char *file
,int filesize
)
1722 for(i
=0; i
<filesize
&& *url
; url
++) {
1723 if(isalnum(*url
) || *url
=='-' || *url
=='_' || *url
=='.' || *url
=='%') {
1727 if (!skip
) file
[i
++]='_';
1736 printf(_("SARG Version: %s\n"),VERSION
);
1740 char *get_param_value(const char *param
,char *line
)
1744 while (*line
==' ' || *line
=='\t') line
++;
1746 if (strncasecmp(line
,param
,plen
)) return(NULL
);
1747 if (line
[plen
]!=' ' && line
[plen
]!='\t') return(NULL
);
1749 while (*line
==' ' || *line
=='\t') line
++;
1753 void unlinkdir(const char *dir
,int contentonly
)
1757 struct dirent
*direntp
;
1763 while ((direntp
= readdir(dirp
)) != NULL
) {
1764 if (direntp
->d_name
[0] == '.' && (direntp
->d_name
[1] == '\0' ||
1765 (direntp
->d_name
[1] == '.' && direntp
->d_name
[2] == '\0')))
1767 if (snprintf(dname
,sizeof(dname
),"%s/%s",dir
,direntp
->d_name
)>=sizeof(dname
)) {
1768 debuga(_("directory name to delete too long: %s/%s\n"),dir
,direntp
->d_name
);
1772 err
=lstat(dname
,&st
);
1774 err
=stat(dname
,&st
);
1777 debuga(_("cannot stat %s\n"),dname
);
1780 if (S_ISREG(st
.st_mode
)) {
1781 if (unlink(dname
)) {
1782 debuga(_("cannot delete %s - %s\n"),dname
,strerror(errno
));
1785 } else if (S_ISDIR(st
.st_mode
)) {
1788 debuga(_("unknown path type %s\n"),dname
);
1795 debuga(_("cannot delete %s - %s\n"),dir
,strerror(errno
));