]>
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 1024
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(strcmp(DisplayedValues
,"abbreviation") == 0) {
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
++)
580 void buildhref(char * href
)
584 if(strcmp(href
,"./") == 0){
586 strcat(href
,"<a href='");
590 href
[strlen(href
)-1]='\0';
591 sprintf(whref
,"%s",strrchr(href
,'/'));
593 strcpy(href
,"<a href='");
602 char *buildtime(long long int elap
)
605 int num
= elap
/ 1000;
614 min
=(num
% 3600) / 60;
616 sprintf(buf
,"%02d:%02d:%02d",hor
,min
,sec
);
623 void obtdate(const char *dirname
, const char *name
, char *data
)
629 sprintf(wdir
,"%s%s/sarg-date",dirname
,name
);
630 if ((fp_in
= fopen(wdir
, "rt")) == 0) {
631 sprintf(wdir
,"%s%s/date",dirname
,name
);
632 if ((fp_in
= fopen(wdir
, "rt")) == 0) {
638 if (!fgets(data
,80,fp_in
)) {
639 debuga(_("Failed to read the date in %s\n"),wdir
);
650 void formatdate(char *date
,int date_size
,int year
,int month
,int day
,int hour
,int minute
,int second
,int dst
)
656 memset(<m
,0,sizeof(ltm
));
657 if (year
>=1900) ltm
.tm_year
=year
-1900;
658 if (month
>=1 && month
<=12) ltm
.tm_mon
=month
-1;
659 if (day
>=1 && day
<=31) ltm
.tm_mday
=day
;
660 if (hour
>=0 && hour
<24) ltm
.tm_hour
=hour
;
661 if (minute
>=0 && minute
<60) ltm
.tm_min
=minute
;
662 if (second
>=0 && second
<60) ltm
.tm_sec
=second
;
664 unixtime
=mktime(<m
); //fill the missing entries
665 fulltm
=localtime(&unixtime
);
666 //strftime(date,date_size,"%a %b %d %H:%M:%S %Z %Y",fulltm);
667 strftime(date
,date_size
,"%c",fulltm
);
671 void computedate(int year
,int month
,int day
,struct tm
*t
)
673 memset(t
,0,sizeof(*t
));
674 t
->tm_year
=year
-1900;
680 int obtuser(const char *dirname
, const char *name
)
688 sprintf(wdir
,"%s%s/sarg-users",dirname
,name
);
689 if((fp_in
=fopen(wdir
,"r"))==NULL
) {
690 sprintf(wdir
,"%s%s/users",dirname
,name
);
691 if((fp_in
=fopen(wdir
,"r"))==NULL
) {
696 if (!fgets(tuser
,sizeof(tuser
),fp_in
)) {
697 debuga(_("Failed to read the number of users in %s\n"),wdir
);
707 void obttotal(const char *dirname
, const char *name
, char *tbytes
, int nuser
, char *media
)
712 char user
[MAX_USER_LEN
];
715 long long int twork
=0;
716 struct getwordstruct gwarea
;
723 sprintf(wdir
,"%s%s/sarg-general",dirname
,name
);
724 if ((fp_in
= fopen(wdir
, "r")) == 0) {
725 sprintf(wdir
,"%s%s/general",dirname
,name
);
726 if ((fp_in
= fopen(wdir
, "r")) == 0) {
731 if ((line
=longline_create())==NULL
) {
732 debuga(_("Not enough memory to read the file %s\n"),wdir
);
736 while((buf
=longline_read(fp_in
,line
))!=NULL
) {
737 if (strncmp(buf
,"TOTAL\t",6) == 0)
739 else if (strncmp(buf
,"TOTAL ",6) == 0)
743 getword_start(&gwarea
,buf
);
744 if (getword(user
,sizeof(user
),&gwarea
,sep
)<0) {
745 debuga(_("There is a invalid user in file %s\n"),wdir
);
748 if(strcmp(user
,"TOTAL") != 0)
750 if (getword_skip(MAXLEN
,&gwarea
,sep
)<0) {
751 debuga(_("There a broken total number of access in file %s\n"),wdir
);
754 if (getword_atoll(&twork
,&gwarea
,sep
)<0) {
755 debuga(_("There is a broken number of bytes in file %s\n"),wdir
);
758 strcpy(tbytes
,fixnum(twork
,1));
762 longline_destroy(&line
);
770 strcpy(media
,fixnum(med
,1));
775 int getperiod_fromsarglog(const char *arqtt
,struct periodstruct
*period
)
778 int day0
, month0
, year0
, hour0
, minute0
;
779 int day1
, month1
, year1
, hour1
, minute1
;
783 memset(period
,0,sizeof(*period
));
786 while((str
=strstr(str
,"sarg-"))!=NULL
) {
788 if (!isdigit(str
[0]) || !isdigit(str
[1])) continue;
789 day0
=(str
[0]-'0')*10+(str
[1]-'0');
791 strncpy(month
,str
,3);
793 month0
=month2num(month
);
794 if (month0
>=12) continue;
797 for (i
=0 ; isdigit(str
[i
]) && i
<4 ; i
++) year0
=year0
*10+(str
[i
]-'0');
801 if (!isdigit(str
[0]) || !isdigit(str
[1])) continue;
802 hour0
=(str
[0]-'0')*10+(str
[1]-'0');
804 if (!isdigit(str
[0]) || !isdigit(str
[1])) continue;
805 minute0
=(str
[0]-'0')*10+(str
[1]-'0');
808 if (*str
!= '_') continue;
810 if (!isdigit(str
[0]) || !isdigit(str
[1])) continue;
811 day1
=(str
[0]-'0')*10+(str
[1]-'0');
813 strncpy(month
,str
,3);
815 month1
=month2num(month
);
816 if (month1
>=12) continue;
819 for (i
=0 ; isdigit(str
[i
]) && i
<4 ; i
++) year1
=year1
*10+(str
[i
]-'0');
822 if (!isdigit(str
[0]) || !isdigit(str
[1])) continue;
823 hour1
=(str
[0]-'0')*10+(str
[1]-'0');
825 if (!isdigit(str
[0]) || !isdigit(str
[1])) continue;
826 minute1
=(str
[0]-'0')*10+(str
[1]-'0');
829 period
->start
.tm_mday
=day0
;
830 period
->start
.tm_mon
=month0
;
831 period
->start
.tm_year
=year0
-1900;
832 period
->start
.tm_hour
=hour0
;
833 period
->start
.tm_min
=minute0
;
834 period
->end
.tm_mday
=day1
;
835 period
->end
.tm_mon
=month1
;
836 period
->end
.tm_year
=year1
-1900;
837 period
->end
.tm_hour
=hour1
;
838 period
->end
.tm_min
=minute1
;
844 int getperiod_buildtext(struct periodstruct
*period
)
849 i
=strftime(period
->text
, sizeof(period
->text
), "%Y %b %d", &period
->start
);
851 i
=strftime(period
->text
, sizeof(period
->text
), "%d %b %Y", &period
->start
);
852 else /*if(df[0]=='w')*/ {
853 IndexTree
=INDEX_TREE_FILE
;
854 i
=strftime(period
->text
, sizeof(period
->text
), "%Y.%U", &period
->start
);
857 if (period
->start
.tm_year
!=period
->end
.tm_year
||
858 period
->start
.tm_mon
!=period
->end
.tm_mon
||
859 period
->start
.tm_mday
!=period
->end
.tm_mday
) {
860 period
->text
[i
++]='-';
862 i
=strftime(period
->text
+i
, sizeof(period
->text
)-i
, "%Y %b %d", &period
->end
);
864 i
=strftime(period
->text
+i
, sizeof(period
->text
)-i
, "%d %b %Y", &period
->end
);
866 i
=strftime(period
->text
+i
, sizeof(period
->text
)-i
, "%Y.%U", &period
->end
);
867 if (i
== 0) return(-1);
872 static void copy_images(void)
874 FILE *img_in
, *img_ou
;
877 char srcfile
[MAXLEN
];
878 char dstfile
[MAXLEN
];
880 struct dirent
*direntp
;
885 if (snprintf(images
,sizeof(images
),"%simages",outdir
)>=sizeof(images
)) {
886 debuga(_("Cannot copy images to target directory %simages\n"),outdir
);
889 if (access(images
,R_OK
)!=0) {
893 strcpy(imgdir
,IMAGEDIR
);
894 dirp
= opendir(imgdir
);
896 debuga(_("(util) Can't open directory %s: %s\n"),imgdir
,strerror(errno
));
899 while ((direntp
= readdir( dirp
)) != NULL
){
900 if(direntp
->d_name
[0]=='.')
902 sprintf(srcfile
,"%s/%s",imgdir
,direntp
->d_name
);
903 if (stat(srcfile
,&info
)) {
904 debuga(_("Cannot stat \"%s\" - %s\n"),srcfile
,strerror(errno
));
907 if (S_ISREG(info
.st_mode
)) {
908 sprintf(dstfile
,"%s/%s",images
,direntp
->d_name
);
909 img_in
= fopen(srcfile
, "rb");
911 img_ou
= fopen(dstfile
, "wb");
913 while ((nread
= fread(buffer
,1,sizeof(buffer
),img_in
))>0) {
914 if (fwrite(buffer
,1,nread
,img_ou
)!=nread
) {
915 debuga(_("Failed to copy image %s to %s\n"),srcfile
,dstfile
);
921 fprintf(stderr
,"SARG: (util): %s %s: %s\n", _("Cannot open file")?_("Cannot open file"):"Can't open/create file", dstfile
, strerror(errno
));
924 fprintf(stderr
,"SARG: (util): %s %s: %s\n", _("Cannot open file")?_("Cannot open file"):"Can't open file", srcfile
, strerror(errno
));
927 (void) closedir(dirp
);
932 int vrfydir(const struct periodstruct
*per1
, const char *addr
, const char *site
, const char *us
, const char *form
)
937 char dirname2
[MAXLEN
];
947 y1
=per1
->start
.tm_year
+1900;
948 y2
=per1
->end
.tm_year
+1900;
949 m1
=per1
->start
.tm_mon
+1;
950 m2
=per1
->end
.tm_mon
+1;
951 d1
=per1
->start
.tm_mday
;
952 d2
=per1
->end
.tm_mday
;
953 if(IndexTree
== INDEX_TREE_DATE
) {
954 wlen
+=sprintf(wdir
+wlen
,"%04d",y1
);
955 if(y1
!=y2
) wlen
+=sprintf(wdir
+wlen
,"-%04d",y2
);
956 if(access(wdir
, R_OK
) != 0)
959 wlen
+=sprintf(wdir
+wlen
,"/%02d",m1
);
960 if(m1
!= m2
) wlen
+=sprintf(wdir
+wlen
,"-%02d",m2
);
961 if(access(wdir
, R_OK
) != 0)
964 wlen
+=sprintf(wdir
+wlen
,"/%02d",d1
);
965 if(d1
!=d2
) wlen
+=sprintf(wdir
+wlen
,"-%02d",d2
);
968 wlen
=snprintf(wdir
+wlen
,sizeof(wdir
)-wlen
,"%04d%s%02d-%04d%s%02d",y1
,
969 conv_month_name(m1
),d1
,y2
,conv_month_name(m2
),d2
);
970 } else if(df
[0] == 'e') {
971 wlen
=snprintf(wdir
+wlen
,sizeof(wdir
)-wlen
,"%02d%s%04d-%02d%s%04d",d1
,
972 conv_month_name(m1
),y1
,d2
,conv_month_name(m2
),y2
);
973 } else if(df
[0] == 'w') {
974 wlen2
=strftime(wdir
+wlen
, sizeof(wdir
)-wlen
, "%Y.%U", &per1
->start
);
975 if (wlen2
==0) return(-1);
984 if(addr
[0] != '\0') {
988 if(site
[0] != '\0') {
993 strcpy(outdirname
,wdir
);
995 if(IndexTree
!= INDEX_TREE_DATE
) {
996 if(!OverwriteReport
) {
998 if(access(wdir
,R_OK
) == 0) {
999 sprintf(wdir
,"%s.%d",outdirname
,num
);
1008 debuga(_("File %s already exists, moved to %s\n"),outdirname
,wdir
);
1009 rename(outdirname
,wdir
);
1012 if(access(outdirname
,R_OK
) == 0) {
1013 unlinkdir(outdirname
,1);
1016 my_mkdir(outdirname
);
1018 strcpy(dirname2
,wdir
);
1019 if(!OverwriteReport
) {
1021 if(access(wdir
,R_OK
) == 0) {
1022 sprintf(wdir
,"%s.%d",dirname2
,num
);
1031 debuga(_("File %s already exists, moved to %s\n"),dirname2
,wdir
);
1032 rename(dirname2
,wdir
);
1033 strcpy(dirname2
,wdir
);
1036 if(access(wdir
,R_OK
) == 0) {
1041 if(access(wdir
, R_OK
) != 0)
1045 strcpy(dirname2
,wdir
);
1047 sprintf(wdir
,"%s/sarg-date",outdirname
);
1048 if ((fp_ou
= fopen(wdir
, "wt")) == 0) {
1049 debuga(_("cannot open %s for writing\n"),wdir
);
1054 //strftime(wdir,sizeof(wdir),"%a %b %d %H:%M:%S %Z %Y",localtime(&curtime));
1055 loctm
=localtime(&curtime
);
1056 strftime(wdir
,sizeof(wdir
),"%Y-%m-%d %H:%M:%S",loctm
);
1057 if (fprintf(fp_ou
,"%s %d\n",wdir
,loctm
->tm_isdst
)<0) {
1058 debuga(_("failed to write the date in %s\n"),wdir
);
1062 if (fclose(fp_ou
)==EOF
) {
1063 debuga(_("failed to write the date in %s\n"),wdir
);
1072 void strip_latin(char *line
)
1079 for (i
=0;line
[i
];i
++){
1081 if (line
[i
]==';') skip
=0;
1094 void zdate(char *ftime
,int ftimesize
, const char *DateFormat
)
1101 local
= localtime(&t
);
1102 if(strcmp(DateFormat
,"u") == 0)
1103 strftime(ftime
, ftimesize
, "%b/%d/%Y %H:%M", local
);
1104 if(strcmp(DateFormat
,"e") == 0)
1105 strftime(ftime
, ftimesize
, "%d/%b/%Y-%H:%M", local
);
1106 if(strcmp(DateFormat
,"w") == 0)
1107 strftime(ftime
, ftimesize
, "%V-%H-%M", local
);
1112 char *fixtime(long int elap
)
1115 int num
= elap
/ 1000;
1119 static char buf
[12];
1121 if(strcmp(datetimeby
,"bytes") == 0) {
1122 strcpy(buf
,fixnum(elap
,1));
1127 sprintf(buf
,"00:00:%02ld",elap
);
1132 min
=(num
% 3600) / 60;
1135 if(hor
==0 && min
==0 && sec
==0)
1138 sprintf(buf
,"%01d:%02d:%02d",hor
,min
,sec
);
1145 void date_from(char *date
, char *dfrom
, char *duntil
)
1156 strncpy(wdate
,date
,sizeof(wdate
)-1);
1157 wdate
[sizeof(wdate
)-1]='\0';
1158 if(strchr(wdate
,'-') == NULL
) {
1159 if (strlen(wdate
)*2+1>=sizeof(wdate
)) {
1160 debuga(_("Invalid date range passed as argument\n"));
1168 if (sscanf(wdate
,"%d/%d/%d-%d/%d/%d",&diaf
,&mesf
,&anof
,&diau
,&mesu
,&anou
)!=6) {
1169 debuga(_("The date range passed as argument is not formated as dd/mm/yyyy-dd/mm/yyyy\n"));
1173 sprintf(dfrom
,"%04d%02d%02d",anof
,mesf
,diaf
);
1174 sprintf(duntil
,"%04d%02d%02d",anou
,mesu
,diau
);
1179 char *strlow(char *string
)
1185 for (s
= string
; *s
; ++s
)
1195 char *strup(char *string
)
1201 for (s
= string
; *s
; ++s
)
1209 void removetmp(const char *outdir
)
1216 if(!RemoveTempFiles
)
1220 debuga(_("Removing temporary files sarg-general, sarg-period\n"));
1222 if (snprintf(warea
,sizeof(warea
),"%s/sarg-general",outdir
)>=sizeof(warea
)) {
1223 debuga(_("(removetmp) directory too long to remove %s/sarg-period\n"),outdir
);
1226 if((fp_in
=fopen(warea
,"r"))==NULL
){
1227 debuga(_("(removetmp) Cannot open file %s\n"),warea
);
1230 while(fgets(buf
,sizeof(buf
),fp_in
)!=NULL
) {
1231 if(strncmp(buf
,"TOTAL",5) == 0 && (buf
[6]=='\t' || buf
[6]==' '))
1236 if((fp_in
=fopen(warea
,"w"))==NULL
){
1237 debuga(_("(removetmp) Cannot open file %s\n"),warea
);
1240 if (fputs(buf
,fp_in
)==EOF
) {
1241 debuga(_("Failed to write the total line in %s - %s\n"),warea
,strerror(errno
));
1244 if (fclose(fp_in
)==EOF
) {
1245 debuga(_("Failed to close %s after writing the total line - %s\n"),warea
,strerror(errno
));
1252 void load_excludecodes(const char *ExcludeCodes
)
1259 if(ExcludeCodes
[0] == '\0')
1262 if((excludecode
=(char *) malloc(1024))==NULL
) {
1263 debuga(_("malloc error (1024)\n"));
1266 bzero(excludecode
,1024);
1268 if((fp_in
=fopen(ExcludeCodes
,"r"))==NULL
) {
1269 debuga(_("(util) Cannot open file %s (exclude_codes)\n"),ExcludeCodes
);
1273 while(fgets(data
,sizeof(data
),fp_in
)!=NULL
) {
1274 for (i
=strlen(data
)-1 ; i
>=0 && (unsigned char)data
[i
]<=' ' ; i
--) data
[i
]=0;
1276 strcat(excludecode
,data
);
1277 strcat(excludecode
,";");
1285 void free_excludecodes(void)
1293 int vercode(const char *code
)
1298 if (excludecode
&& excludecode
[0]!=0) {
1300 for (cod
=excludecode
; cod
; cod
=strchr(cod
+1,';')) {
1301 if (strncmp(code
,cod
,clen
)==0 && cod
[clen
]==';')
1308 void fixnone(char *str
)
1312 for (i
=strlen(str
)-1 ; i
>=0 && (unsigned char)str
[i
]<=' ' ; i
--);
1313 if(i
==3 && strncmp(str
,"none",4) == 0)
1319 void fixendofline(char *str
)
1323 for (i
=strlen(str
)-1 ; i
>=0 && (unsigned char)str
[i
]<=' ' ; i
--) str
[i
]=0;
1326 #ifdef LEGACY_TESTVALIDUSERCHAR
1327 int testvaliduserchar(const char *user
)
1333 for (y
=0; y
<strlen(UserInvalidChar
); y
++) {
1334 for (x
=0; x
<strlen(user
); x
++) {
1335 if(user
[x
] == UserInvalidChar
[y
])
1342 int testvaliduserchar(const char *user
)
1345 char * p_UserInvalidChar
= UserInvalidChar
;
1346 const char * p_user
;
1348 while( *p_UserInvalidChar
) {
1351 if( *p_UserInvalidChar
== *p_user
)
1355 p_UserInvalidChar
++ ;
1361 int compar( const void *a
, const void *b
)
1362 { if( *(int *)a
> *(int *)b
) return 1;
1363 if( *(int *)a
< *(int *)b
) return -1;
1367 int getnumlist( char *buf
, numlist
*list
, const int len
, const int maxvalue
)
1369 int i
, j
, d
, flag
, r1
, r2
;
1370 char *pbuf
, **bp
, *strbufs
[ 24 ];
1373 strtok( buf
, " \t" );
1374 for( *bp
= strtok( NULL
, "," ), list
->len
= 0; *bp
; *bp
= strtok( NULL
, "," ) ) {
1375 if( ++bp
>= &strbufs
[ 24 ] )
1382 for( i
= 0; i
< list
->len
; i
++ ) {
1383 if( strchr( strbufs
[ i
], '-' ) != 0 ) {
1384 pbuf
= strbufs
[ i
];
1385 strtok( pbuf
, "-" );
1386 pbuf
= strtok( NULL
, "\0" );
1387 r1
= atoi( strbufs
[ i
] );
1388 if( ( r2
= atoi( pbuf
) ) >= maxvalue
|| r1
>= r2
)
1390 if( i
+ d
+ ( r2
- r1
) + 1 <= len
) {
1391 for( j
= r1
; j
<= r2
; j
++ )
1392 list
->list
[ i
+ d
++ ] = j
;
1397 if( ( list
->list
[ i
+ d
] = atoi( strbufs
[ i
] ) ) >= maxvalue
)
1401 qsort( list
->list
, list
->len
, sizeof( int ), compar
);
1404 for( i
= 0; i
< list
->len
- 1; i
++ )
1405 if( list
->list
[ i
] == list
->list
[ i
+ 1 ] ) {
1406 for( j
= i
+ 1; j
< list
->len
; j
++ )
1407 list
->list
[ j
- 1 ] = list
->list
[ j
];
1417 char *get_size(const char *path
, const char *file
)
1420 static char response
[255];
1424 if (snprintf(cmd
,sizeof(cmd
),"du -skh %s%s",path
,file
)>=sizeof(cmd
)) {
1425 debuga(_("Cannot get disk space because the path %s%s is too long\n"),path
,file
);
1428 if ((fp
= popen(cmd
, "r")) == NULL
) {
1429 debuga(_("Cannot get disk space with command %s\n"),cmd
);
1432 if (!fgets(response
, sizeof(response
), fp
)) {
1433 debuga(_("Cannot get disk size with command %s\n"),cmd
);
1436 ptr
=strchr(response
,'\t');
1438 debuga(_("The command %s failed\n"),cmd
);
1447 void show_info(FILE *fp_ou
)
1451 if(!ShowSargInfo
) return;
1452 zdate(ftime
, sizeof(ftime
), DateFormat
);
1453 fprintf(fp_ou
,"<div class=\"info\">%s <a href='%s'>%s-%s</a> %s %s</div>\n",_("Generated by"),URL
,PGM
,VERSION
,_("on"),ftime
);
1456 void show_sarg(FILE *fp_ou
, int depth
)
1460 if(!ShowSargLogo
) return;
1461 fputs("<div class=\"logo\"><a href=\"http://sarg.sourceforge.net\"><img src=\"",fp_ou
);
1462 for (i
=0 ; i
<depth
; i
++)
1464 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
);
1467 void write_logo_image(FILE *fp_ou
)
1469 if(LogoImage
[0]!='\0')
1470 fprintf(fp_ou
, "<div class=\"logo\"><img src=\"%s\" width=\"%s\" height=\"%s\" alt=\"Logo\"> %s</div>\n",LogoImage
,Width
,Height
,LogoText
);
1473 void write_html_header(FILE *fp_ou
, int depth
, const char *page_title
)
1475 //fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n",fp_ou);
1476 fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n<html>\n",fp_ou
);
1477 fprintf(fp_ou
, "<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n",CharSet
);
1478 if (page_title
) fprintf(fp_ou
,"<title>%s</title>\n",page_title
);
1480 fprintf(fp_ou
,"</head>\n<body style=\"font-family:%s;font-size:%s;background-color:%s;background-image:url(%s)\">\n",FontFace
,TitleFontSize
,BgColor
,BgImage
);
1481 write_logo_image(fp_ou
);
1482 show_sarg(fp_ou
, depth
);
1483 fprintf(fp_ou
,"<div class=\"title\"><table cellpadding=\"0\" cellspacing=\"0\">\n<tr><th class=\"title_c\">%s</th></tr>\n",Title
);
1486 void close_html_header(FILE *fp_ou
)
1488 fputs("</table></div>\n",fp_ou
);
1491 int write_html_trailer(FILE *fp_ou
)
1494 if (fputs("</body>\n</html>\n",fp_ou
)==EOF
) return(-1);
1498 void output_html_string(FILE *fp_ou
,const char *str
,int maxlen
)
1502 while (*str
&& (maxlen
<=0 || i
<maxlen
)) {
1505 fputs("&",fp_ou
);
1508 fputs("<",fp_ou
);
1511 fputs(">",fp_ou
);
1514 fputs(""",fp_ou
);
1517 fputs("'",fp_ou
);
1525 if (maxlen
>0 && i
>=maxlen
)
1526 fputs("…",fp_ou
);
1529 void output_html_url(FILE *fp_ou
,const char *url
)
1533 fputs("&",fp_ou
);
1544 printf("SARG: ------------------------------------------------------------------------------\n");
1545 printf(_("SARG: MALICIUS CODE DETECTED.\n"));
1546 printf(_("SARG: I think someone is trying to execute arbitrary code in your system using sarg.\n"));
1547 printf(_("SARG: please review your access.log and/or your useragent.log file.\n"));
1548 printf(_("SARG: process stoped. No actions taken.\n"));
1549 printf("SARG: ------------------------------------------------------------------------------\n");
1551 if (snprintf(dir
,sizeof(dir
),"%s/sarg",tmp
)>=sizeof(dir
)) {
1552 debuga(_("temporary directory too long: %s/sarg\n"),tmp
);
1556 unlinkdir(outdirname
,0);
1561 void url_hostname(const char *url
,char *hostname
,int hostsize
)
1566 for (i
=0 ; i
<hostsize
&& url
[i
] && url
[i
]!='/' ; i
++)
1571 void url_module(const char *url
, char *w2
)
1577 for(x
=strlen(url
)-1; x
>=0; x
--) {
1578 if(url
[x
] == '/' || y
>=sizeof(w
)-1) break;
1587 for(y
=y
-1; y
>=0; y
--) {
1593 void url_to_file(const char *url
,char *file
,int filesize
)
1599 for(i
=0; i
<filesize
&& *url
; url
++) {
1600 if(*url
=='?' || *url
=='-' || *url
=='.' || *url
==':' || *url
=='/' || *url
=='\\' ||
1601 *url
=='*' || *url
=='\'' || *url
=='\"' || *url
=='$') {
1602 if (!skip
) file
[i
++]='_';
1614 printf(_("SARG Version: %s\n"),VERSION
);
1618 char *get_param_value(const char *param
,char *line
)
1622 while (*line
==' ' || *line
=='\t') line
++;
1624 if (strncasecmp(line
,param
,plen
)) return(NULL
);
1625 if (line
[plen
]!=' ' && line
[plen
]!='\t') return(NULL
);
1627 while (*line
==' ' || *line
=='\t') line
++;
1631 void unlinkdir(const char *dir
,int contentonly
)
1635 struct dirent
*direntp
;
1641 while ((direntp
= readdir(dirp
)) != NULL
) {
1642 if (direntp
->d_name
[0] == '.' && (direntp
->d_name
[1] == '\0' ||
1643 (direntp
->d_name
[1] == '.' && direntp
->d_name
[2] == '\0')))
1645 if (snprintf(dname
,sizeof(dname
),"%s/%s",dir
,direntp
->d_name
)>=sizeof(dname
)) {
1646 debuga(_("directory name to delete too long: %s/%s\n"),dir
,direntp
->d_name
);
1650 err
=lstat(dname
,&st
);
1652 err
=stat(dname
,&st
);
1655 debuga(_("cannot stat %s\n"),dname
);
1658 if (S_ISREG(st
.st_mode
)) {
1659 if (unlink(dname
)) {
1660 debuga(_("cannot delete %s - %s\n"),dname
,strerror(errno
));
1663 } else if (S_ISDIR(st
.st_mode
)) {
1666 debuga(_("unknown path type %s\n"),dname
);
1673 debuga(_("cannot delete %s - %s\n"),dir
,strerror(errno
));