]>
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 #define INITIAL_LINE_BUFFER_SIZE 32768
41 static char mtab1
[12][4]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
43 //! The list of the HTTP codes to exclude from the report.
44 static char *excludecode
=NULL
;
46 /*void fgetword(char *word, char *line, int stop)
51 for (x=0; line[x] && (line[x] != stop); x++) word[x] = line[x];
58 tchar = strchr(line, stop);
59 if (tchar == NULL) strcpy(word, line);
62 difflen = tchar - line;
63 strncpy(word, line, difflen);
68 #if USE_GETWORD_BACKTRACE
69 static void getword_backtrace(void)
75 n
=backtrace(buffer
,sizeof(buffer
)/sizeof(buffer
[0]));
77 calls
=backtrace_symbols(buffer
,n
);
79 debuga(_("getword backtrace:\n"));
80 for (i
=0 ; i
<n
; i
++) {
81 fprintf(stderr
,"SARG: %d:%s\n",i
+1,calls
[i
]);
86 #endif //USE_GETWORD_BACKTRACE
88 void getword_start(struct getwordstruct
*gwarea
, const char *line
)
90 gwarea
->beginning
=line
;
95 void getword_restart(struct getwordstruct
*gwarea
)
97 if (gwarea
->modified
) {
98 debuga(_("Cannot parse again the line as it was modified\n"));
101 gwarea
->current
=gwarea
->beginning
;
104 int getword(char *word
, int limit
, struct getwordstruct
*gwarea
, int stop
)
108 for(x
=0;((gwarea
->current
[x
]) && (gwarea
->current
[x
] != stop
));x
++) {
110 printf("SARG: getword loop detected after %d bytes.\n",x
);
111 printf("SARG: Line=\"%s\"\n",gwarea
->beginning
);
112 printf("SARG: Record=\"%s\"\n",gwarea
->current
);
113 printf("SARG: searching for \'x%x\'\n",stop
);
114 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
115 word
[(limit
>0) ? limit
-1 : 0]='\0';
116 #if USE_GETWORD_BACKTRACE
121 word
[x
] = gwarea
->current
[x
];
125 if (gwarea
->current
[x
]) ++x
;
130 int getword_limit(char *word
, int limit
, struct getwordstruct
*gwarea
, int stop
)
135 for(x
=0; x
<limit
&& gwarea
->current
[x
] && gwarea
->current
[x
] != stop
;x
++) {
136 word
[x
] = gwarea
->current
[x
];
140 while (*gwarea
->current
&& *gwarea
->current
!= stop
) gwarea
->current
++;
141 if (*gwarea
->current
) ++gwarea
->current
;
145 int getword_multisep(char *word
, int limit
, struct getwordstruct
*gwarea
, int stop
)
149 for(x
=0;((gwarea
->current
[x
]) && (gwarea
->current
[x
] != stop
));x
++) {
151 printf("SARG: getword_multisep loop detected.\n");
152 printf("SARG: Line=\"%s\"\n",gwarea
->beginning
);
153 printf("SARG: Record=\"%s\"\n",gwarea
->current
);
154 printf("SARG: searching for \'x%x\'\n",stop
);
155 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
156 if (limit
>0) word
[limit
-1]='\0';
157 #if USE_GETWORD_BACKTRACE
163 word
[x
] = gwarea
->current
[x
];
167 while (gwarea
->current
[x
] && gwarea
->current
[x
]==stop
) ++x
;
172 int getword_skip(int limit
, struct getwordstruct
*gwarea
, int stop
)
176 for(x
=0;(gwarea
->current
[x
] && (gwarea
->current
[x
] != stop
));x
++) {
178 printf("SARG: getword_skip loop detected after %d bytes.\n",x
);
179 printf("SARG: Line=\"%s\"\n",gwarea
->beginning
);
180 printf("SARG: Record=\"%s\"\n",gwarea
->current
);
181 printf("SARG: searching for \'x%x\'\n",stop
);
182 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
183 #if USE_GETWORD_BACKTRACE
190 if (gwarea
->current
[x
]) ++x
;
195 int getword_atoll(long long int *number
, struct getwordstruct
*gwarea
, int stop
)
200 if (gwarea
->current
[0] == '-') {
203 } else if (gwarea
->current
[0] == '+') {
207 for(x
=0;isdigit(gwarea
->current
[x
]);x
++) {
208 *number
=(*number
* 10) + gwarea
->current
[x
]-'0';
210 if(gwarea
->current
[x
] && gwarea
->current
[x
]!=stop
) {
211 printf("SARG: getword_atoll loop detected after %d bytes.\n",x
);
212 printf("SARG: Line=\"%s\"\n",gwarea
->beginning
);
213 printf("SARG: Record=\"%s\"\n",gwarea
->current
);
214 printf("SARG: searching for \'x%x\'\n",stop
);
215 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
216 #if USE_GETWORD_BACKTRACE
223 if (gwarea
->current
[x
]) ++x
;
229 int getword_ptr(char *orig_line
,char **word
, struct getwordstruct
*gwarea
, int stop
)
232 \note Why pass the original buffer to the function ? Because we must modify it to
233 insert the terminating ASCII zero for the word we return and that's not compatible
234 with getword_restart(). Moreover, getword_start() sometime works on constant strings
235 so this function require the original buffer to detect any missuse.
241 if (orig_line
&& orig_line
!=gwarea
->beginning
) {
242 debuga(_("Invalid buffer passed to getword_ptr\n"));
246 start
=(gwarea
->current
-gwarea
->beginning
);
247 if (word
&& orig_line
) *word
=orig_line
+start
;
248 for(x
=0;((gwarea
->current
[x
]) && (gwarea
->current
[x
] != stop
));x
++);
249 sep
=(gwarea
->current
[x
]!='\0');
250 if (word
&& orig_line
) orig_line
[start
+x
] = '\0';
257 #define MAXLLL 30 //!< Maximum number of digits in long long (a guess).
258 long long int my_atoll (const char *nptr
)
260 long long int returnval
=0LL;
261 int max_digits
= MAXLLL
;
263 // Soak up all the white space
264 while (isspace( *nptr
)) {
268 //For each character left to right
269 //change the character to a single digit
270 //multiply what we had before by 10 and add the new digit
272 while (--max_digits
&& isdigit( *nptr
))
274 returnval
= ( returnval
* 10 ) + ( *nptr
++ - '0' ) ;
280 int is_absolute(const char *path
)
282 if (*path
=='/') return(1);
284 if (isalpha(path
[0]) && path
[1]==':') return(1);
289 void my_mkdir(const char *name
)
295 if(!is_absolute(name
)) {
296 fprintf(stderr
,"SARG: Invalid path (%s). Please, use absolute paths only.\n",name
);
297 fprintf(stderr
,"SARG: process aborted.\n");
302 for (i
=0 ; name
[i
] ; i
++) {
304 fprintf(stderr
,"SARG: directory name too long %s\n",name
);
307 if (chars
>0 && name
[i
] == '/') {
309 if(access(w0
, R_OK
) != 0) {
311 fprintf(stderr
,"SARG: mkdir %s %s\n",w0
,strerror(errno
));
312 fprintf(stderr
,"SARG: process aborted.\n");
317 if (name
[i
] != '/') chars
++;
321 if(access(name
, R_OK
) != 0) {
322 if(mkdir(name
,0755)) {
323 fprintf(stderr
,"SARG: mkdir %s %s\n",name
,strerror(errno
));
324 fprintf(stderr
,"SARG: process aborted.\n");
331 void my_lltoa(unsigned long long int n
, char *s
, int ssize
, int len
)
340 debuga(_("The requested number length passed to my_lltoa (%d) is bigger than the output buffer size (%d)\n"),len
,ssize
);
345 s
[slen
++] = (n
% 10) + '0';
346 } while ((n
/= 10) > 0 && slen
<ssize
);
349 for (i
= 0, j
= slen
-1; i
<j
; i
++, j
--) {
357 for(j
=slen
; j
>=0; j
--)
365 void builddia(char *dia
, const char *mes
, const char *ano
, const char *df
, char *wdata
)
370 if(strlen(dia
) < 1) return;
372 for(nmes
=0; nmes
<12; nmes
++) {
373 if(strcmp(mtab1
[nmes
],mes
) == 0) {
379 snprintf(wdata
,9,"%s%02d%s",ano
,nmes
,dia
);
382 snprintf(ndia
,sizeof(ndia
),"%s/%02d/%s",dia
,nmes
,ano
);
384 snprintf(ndia
,sizeof(ndia
),"%02d/%s/%s",nmes
,dia
,ano
);
391 void buildymd(const char *dia
, const char *mes
, const char *ano
, char *wdata
)
395 for(nmes
=0; nmes
<12; nmes
++) {
396 if(strcmp(mtab1
[nmes
],mes
) == 0)
400 sprintf(wdata
,"%04d%02d%02d",atoi(ano
),nmes
+1,atoi(dia
));
405 void conv_month(char *month
)
409 for(x
=0; x
<12 && strcmp(mtab1
[x
],month
)!=0; x
++);
410 sprintf(month
,"%02d",x
+1);
414 void conv_month_name(char *month
)
420 strcpy(month
,mtab1
[x
-1]);
424 void name_month(char *month
,int month_len
)
426 int x
, z
=atoi(month
)-1;
429 struct getwordstruct gwarea
;
431 strcpy(m
,_("January,February,March,April,May,June,July,August,September,October,November,December"));
432 getword_start(&gwarea
,m
);
435 if (getword_multisep(w
,sizeof(w
),&gwarea
,',')<0) {
436 printf("SARG: Maybe you have a broken record or garbage in the names of the months.\n");
439 if (getword_multisep(month
,month_len
,&gwarea
,',')<0) {
440 printf("SARG: Maybe you have a broken record or garbage in the name of the months.\n");
446 void fixper(char *tbuf
, char *period
, const char *duntil
)
449 char dia
[5], mes
[5], ano
[5];
452 strncpy(dia
,duntil
+6,2);
454 strncpy(mes
,duntil
+4,2);
456 strncpy(ano
,duntil
,4);
461 strcpy(mes
,mtab1
[x
-1]);
463 if(strcmp(df
,"e") == 0)
464 sprintf(warea
,"%s%s%s",dia
,mes
,ano
);
465 else if(strcmp(df
,"u") == 0)
466 sprintf(warea
,"%s%s%s",ano
,mes
,dia
);
470 strcat(period
,warea
);
474 void debuga(const char *msg
,...)
478 fputs(_("SARG: "),stderr
);
480 vfprintf(stderr
,msg
,ap
);
485 void debugaz(const char *head
, const char *msg
)
487 fprintf(stderr
, "SARG: (util) %s=%s\n",head
, msg
);
492 char *fixnum(long long int value
, int n
)
494 #define MAXLEN_FIXNUM 1024
495 char num
[MAXLEN_FIXNUM
]="";
496 char buf
[MAXLEN_FIXNUM
* 2];
498 static char ret
[MAXLEN_FIXNUM
* 2];
500 register int i
, j
, k
;
502 static char abbrev
[30];
504 my_lltoa(value
, num
, sizeof(num
), 0);
506 if(strcmp(DisplayedValues
,"abbreviation") == 0) {
507 numlen
= strlen(num
);
509 sprintf(abbrev
,"%s",num
);
510 if(numlen
== 4 || numlen
== 7 || numlen
== 10 || numlen
== 13) {
511 snprintf(abbrev
,2,"%s",num
);
512 strncat(abbrev
,".",1);
513 strncat(abbrev
,num
+1,2);
514 if(!n
) return(abbrev
);
516 strncat(abbrev
,"K",1);
518 strncat(abbrev
,"M",1);
519 else if(numlen
== 10)
520 strncat(abbrev
,"G",1);
521 else if(numlen
== 13)
522 strncat(abbrev
,"T",1);
524 if(numlen
== 5 || numlen
== 8 || numlen
== 11 || numlen
== 14) {
525 snprintf(abbrev
,3,"%s",num
);
526 strncat(abbrev
,".",1);
527 strncat(abbrev
,num
+2,2);
528 if(!n
) return(abbrev
);
530 strncat(abbrev
,"K",1);
532 strncat(abbrev
,"M",1);
533 else if(numlen
== 11)
534 strncat(abbrev
,"G",1);
535 else if(numlen
== 14)
536 strncat(abbrev
,"T",1);
538 if(numlen
== 6 || numlen
== 9 || numlen
== 12 || numlen
== 15) {
539 snprintf(abbrev
,4,"%s",num
);
540 strncat(abbrev
,".",1);
541 strncat(abbrev
,num
+3,2);
542 if(!n
) return(abbrev
);
544 strncat(abbrev
,"K",1);
546 strncat(abbrev
,"M",1);
547 else if(numlen
== 12)
548 strncat(abbrev
,"G",1);
549 else if(numlen
== 15)
550 strncat(abbrev
,"T",1);
556 bzero(buf
, MAXLEN_FIXNUM
*2);
562 for ( i
= strlen(num
) - 1, j
= 0 ; i
> -1; i
--) {
563 if ( k
== 2 && i
!= 0 ) {
566 pbuf
[j
++] = (UseComma
) ? ',' : '.';
576 for ( i
= strlen(pbuf
) - 1, j
= 0 ; i
> -1; i
--, j
++)
585 char *fixnum2(long long int value
, int n
)
587 #define MAXLEN_FIXNUM2 1024
588 char num
[MAXLEN_FIXNUM2
];
589 char buf
[MAXLEN_FIXNUM2
* 2];
591 static char ret
[MAXLEN_FIXNUM2
* 2];
593 register int i
, j
, k
;
595 my_lltoa(value
, num
, sizeof(num
), 0);
596 bzero(buf
, MAXLEN_FIXNUM2
*2);
602 for ( i
= strlen(num
) - 1, j
= 0 ; i
> -1; i
--) {
603 if ( k
== 2 && i
!= 0 ) {
606 pbuf
[j
++] = (UseComma
) ? ',' : '.';
616 for ( i
= strlen(pbuf
) - 1, j
= 0 ; i
> -1; i
--, j
++)
626 void buildhref(char * href
)
630 if(strcmp(href
,"./") == 0){
632 strcat(href
,"<a href='");
636 href
[strlen(href
)-1]='\0';
637 sprintf(whref
,"%s",strrchr(href
,'/'));
639 strcpy(href
,"<a href='");
648 char *buildtime(long long int elap
)
651 int num
= elap
/ 1000;
660 min
=(num
% 3600) / 60;
662 sprintf(buf
,"%02d:%02d:%02d",hor
,min
,sec
);
669 void obtdate(const char *dirname
, const char *name
, char *data
)
675 sprintf(wdir
,"%s%s/sarg-date",dirname
,name
);
676 if ((fp_in
= fopen(wdir
, "rt")) == 0) {
677 sprintf(wdir
,"%s%s/date",dirname
,name
);
678 if ((fp_in
= fopen(wdir
, "rt")) == 0) {
684 if (!fgets(data
,80,fp_in
)) {
685 fprintf(stderr
,"Failed to read the date in %s\n",wdir
);
696 void formatdate(char *date
,int date_size
,int year
,int month
,int day
,int hour
,int minute
,int second
,int dst
)
702 memset(<m
,0,sizeof(ltm
));
703 if (year
>=1900) ltm
.tm_year
=year
-1900;
704 if (month
>=1 && month
<=12) ltm
.tm_mon
=month
-1;
705 if (day
>=1 && day
<=31) ltm
.tm_mday
=day
;
706 if (hour
>=0 && hour
<24) ltm
.tm_hour
=hour
;
707 if (minute
>=0 && minute
<60) ltm
.tm_min
=minute
;
708 if (second
>=0 && second
<60) ltm
.tm_sec
=second
;
710 unixtime
=mktime(<m
); //fill the missing entries
711 fulltm
=localtime(&unixtime
);
712 //strftime(date,date_size,"%a %b %d %H:%M:%S %Z %Y",fulltm);
713 strftime(date
,date_size
,"%c",fulltm
);
717 time_t computedate(const char *year
,const char *month
,const char *day
)
723 for(m
=0; m
<12 && strcmp(mtab1
[m
],month
)!=0; m
++);
726 memset(<m
,0,sizeof(ltm
));
730 ltm
.tm_hour
=12; //be sure to cope with dst
732 return(mktime(<m
));
736 int obtuser(const char *dirname
, const char *name
)
744 sprintf(wdir
,"%s%s/sarg-users",dirname
,name
);
745 if((fp_in
=fopen(wdir
,"r"))==NULL
) {
746 sprintf(wdir
,"%s%s/users",dirname
,name
);
747 if((fp_in
=fopen(wdir
,"r"))==NULL
) {
752 if (!fgets(tuser
,sizeof(tuser
),fp_in
)) {
753 debuga(_("Failed to read the number of users in %s\n"),wdir
);
763 void obttotal(const char *dirname
, const char *name
, char *tbytes
, int nuser
, char *media
)
768 char user
[MAX_USER_LEN
];
771 long long int twork
=0;
772 struct getwordstruct gwarea
;
773 struct longlinestruct line
;
779 sprintf(wdir
,"%s%s/sarg-general",dirname
,name
);
780 if ((fp_in
= fopen(wdir
, "r")) == 0) {
781 sprintf(wdir
,"%s%s/general",dirname
,name
);
782 if ((fp_in
= fopen(wdir
, "r")) == 0) {
787 if (longline_prepare(&line
)<0) {
788 debuga(_("Not enough memory to read the file %s\n"),wdir
);
792 while((buf
=longline_read(fp_in
,&line
))!=NULL
) {
793 if (strncmp(buf
,"TOTAL\t",6) == 0)
795 else if (strncmp(buf
,"TOTAL ",6) == 0)
799 getword_start(&gwarea
,buf
);
800 if (getword(user
,sizeof(user
),&gwarea
,sep
)<0) {
801 debuga(_("There is a invalid user in file %s\n"),wdir
);
804 if(strcmp(user
,"TOTAL") != 0)
806 if (getword_skip(MAXLEN
,&gwarea
,sep
)<0) {
807 debuga(_("There a broken total number of access in file %s\n"),wdir
);
810 if (getword_atoll(&twork
,&gwarea
,sep
)<0) {
811 debuga(_("There is a broken number of bytes in file %s\n"),wdir
);
814 strcpy(tbytes
,fixnum(twork
,1));
818 longline_free(&line
);
826 strcpy(media
,fixnum(med
,1));
832 void gperiod(const char *dirname
, const char *period
)
836 char wdirname
[MAXLEN
];
838 strcpy(wdirname
,dirname
);
839 strcat(wdirname
,"/sarg-period");
841 if((fp_ou
=fopen(wdirname
,"w"))==NULL
){
842 fprintf(stderr
, "SARG: (report) %s: %s\n",_("Cannot open file"),wdirname
);
850 debuga(_("Making period file\n"));
856 static void copy_images(void)
858 FILE *img_in
, *img_ou
;
861 char srcfile
[MAXLEN
];
862 char dstfile
[MAXLEN
];
864 struct dirent
*direntp
;
869 if (snprintf(images
,sizeof(images
),"%simages",outdir
)>=sizeof(images
)) {
870 debuga(_("Cannot copy images to target directory %simages\n"),outdir
);
873 if (access(images
,R_OK
)!=0) {
877 strcpy(imgdir
,IMAGEDIR
);
878 dirp
= opendir(imgdir
);
880 debuga(_("(util) Can't open directory %s: %s\n"),imgdir
,strerror(errno
));
883 while ((direntp
= readdir( dirp
)) != NULL
){
884 if(direntp
->d_name
[0]=='.')
886 sprintf(srcfile
,"%s/%s",imgdir
,direntp
->d_name
);
887 if (stat(srcfile
,&info
)) {
888 debuga(_("Cannot stat \"%s\" - %s\n"),srcfile
,strerror(errno
));
891 if (S_ISREG(info
.st_mode
)) {
892 sprintf(dstfile
,"%s/%s",images
,direntp
->d_name
);
893 img_in
= fopen(srcfile
, "rb");
895 img_ou
= fopen(dstfile
, "wb");
897 while ((nread
= fread(buffer
,1,sizeof(buffer
),img_in
))>0) {
898 if (fwrite(buffer
,1,nread
,img_ou
)!=nread
) {
899 debuga(_("Failed to copy image %s to %s\n"),srcfile
,dstfile
);
905 fprintf(stderr
,"SARG: (util): %s %s: %s\n", _("Cannot open file")?_("Cannot open file"):"Can't open/create file", dstfile
, strerror(errno
));
908 fprintf(stderr
,"SARG: (util): %s %s: %s\n", _("Cannot open file")?_("Cannot open file"):"Can't open file", srcfile
, strerror(errno
));
911 (void) closedir(dirp
);
916 void vrfydir(const char *per1
, const char *addr
, const char *site
, const char *us
, const char *form
)
922 char dirname2
[MAXLEN
];
929 if(IndexTree
== INDEX_TREE_DATE
) {
930 bzero(y1
,sizeof(y1
));
931 bzero(y2
,sizeof(y2
));
932 bzero(d1
,sizeof(d1
));
933 bzero(d2
,sizeof(d2
));
934 bzero(m1
,sizeof(m1
));
935 bzero(m2
,sizeof(m2
));
936 if(strncmp(df
,"u",1) == 0) {
937 strncpy(y1
,period
,4);
938 strncpy(y2
,period
+10,4);
939 strncpy(m1
,period
+4,3);
940 strncpy(m2
,period
+14,3);
941 strncpy(d1
,period
+7,2);
942 strncpy(d2
,period
+17,2);
943 } else if(strncmp(df
,"e",1) == 0) {
944 strncpy(d1
,period
+0,2);
945 strncpy(d2
,period
+10,2);
946 strncpy(m1
,period
+2,3);
947 strncpy(m2
,period
+12,3);
948 strncpy(y1
,period
+5,4);
949 strncpy(y2
,period
+15,4);
954 sprintf(wdir
,"%s%s",outdir
,y1
);
955 if(strcmp(y1
,y2
) != 0) {
959 if(access(wdir
, R_OK
) != 0)
964 if(strcmp(m1
,m2
) != 0) {
968 if(access(wdir
, R_OK
) != 0)
973 if(strcmp(d1
,d2
) != 0) {
978 sprintf(wdir
, "%s%s", outdir
, per1
);
985 if(addr
[0] != '\0') {
989 if(site
[0] != '\0') {
994 strcpy(dirname
,wdir
);
996 if(IndexTree
!= INDEX_TREE_DATE
) {
997 if(!OverwriteReport
) {
999 if(access(wdir
,R_OK
) == 0) {
1000 sprintf(wdir
,"%s.%d",dirname
,num
);
1001 sprintf(per2
,"%s.%d",per1
,num
);
1010 fprintf(stderr
, "SARG: %s: %s %s %s\n",_("File"),dirname
,_("already exists, moved to"),wdir
);
1011 rename(dirname
,wdir
);
1014 if(access(dirname
,R_OK
) == 0) {
1015 unlinkdir(dirname
,1);
1020 strcpy(dirname2
,wdir
);
1021 if(!OverwriteReport
) {
1023 if(access(wdir
,R_OK
) == 0) {
1024 sprintf(wdir
,"%s.%d",dirname2
,num
);
1025 sprintf(per2
,"%s.%d",per1
,num
);
1034 fprintf(stderr
, "SARG: %s: %s %s %s\n",_("File"),dirname2
,_("already exists, moved to"),wdir
);
1035 rename(dirname2
,wdir
);
1036 strcpy(dirname2
,wdir
);
1039 if(access(wdir
,R_OK
) == 0) {
1044 if(access(wdir
, R_OK
) != 0)
1048 strcpy(dirname2
,wdir
);
1050 sprintf(wdir
,"%s/sarg-date",dirname
);
1051 if ((fp_ou
= fopen(wdir
, "wt")) == 0) {
1052 fprintf(stderr
, "SARG: cannot open %s for writing\n",wdir
);
1057 //strftime(wdir,sizeof(wdir),"%a %b %d %H:%M:%S %Z %Y",localtime(&curtime));
1058 loctm
=localtime(&curtime
);
1059 strftime(wdir
,sizeof(wdir
),"%Y-%m-%d %H:%M:%S",loctm
);
1060 fprintf(fp_ou
,"%s %d\n",wdir
,loctm
->tm_isdst
);
1066 void strip_latin(char *line
)
1073 for (i
=0;line
[i
];i
++){
1075 if (line
[i
]==';') skip
=0;
1088 void zdate(char *ftime
,int ftimesize
, const char *DateFormat
)
1095 local
= localtime(&t
);
1096 if(strcmp(DateFormat
,"u") == 0)
1097 strftime(ftime
, ftimesize
, "%b/%d/%Y %H:%M", local
);
1098 if(strcmp(DateFormat
,"e") == 0)
1099 strftime(ftime
, ftimesize
, "%d/%b/%Y-%H:%M", local
);
1100 if(strcmp(DateFormat
,"w") == 0)
1101 strftime(ftime
, ftimesize
, "%V-%H-%M", local
);
1106 char *fixtime(long int elap
)
1109 int num
= elap
/ 1000;
1113 static char buf
[12];
1115 if(strcmp(datetimeby
,"bytes") == 0) {
1116 strcpy(buf
,fixnum(elap
,1));
1121 sprintf(buf
,"00:00:%02ld",elap
);
1126 min
=(num
% 3600) / 60;
1129 if(hor
==0 && min
==0 && sec
==0)
1132 sprintf(buf
,"%01d:%02d:%02d",hor
,min
,sec
);
1139 void date_from(char *date
, char *dfrom
, char *duntil
)
1150 strncpy(wdate
,date
,sizeof(wdate
)-1);
1151 wdate
[sizeof(wdate
)-1]='\0';
1152 if(strchr(wdate
,'-') == NULL
) {
1153 if (strlen(wdate
)*2+1>=sizeof(wdate
)) {
1154 debuga(_("Invalid date range passed as argument\n"));
1162 if (sscanf(wdate
,"%d/%d/%d-%d/%d/%d",&diaf
,&mesf
,&anof
,&diau
,&mesu
,&anou
)!=6) {
1163 debuga(_("The date range passed as argument is not formated as dd/mm/yyyy-dd/mm/yyyy\n"));
1167 sprintf(dfrom
,"%04d%02d%02d",anof
,mesf
,diaf
);
1168 sprintf(duntil
,"%04d%02d%02d",anou
,mesu
,diau
);
1173 char *strlow(char *string
)
1179 for (s
= string
; *s
; ++s
)
1189 char *strup(char *string
)
1195 for (s
= string
; *s
; ++s
)
1203 void removetmp(const char *outdir
)
1209 if(!RemoveTempFiles
)
1213 debuga("%s: sarg-general, sarg-period",_("Removing temporary files\n"));
1215 if (snprintf(warea
,sizeof(warea
),"%s/sarg-general",outdir
)>=sizeof(warea
)) {
1216 debuga(_("(removetmp) directory too long to remove: %s/sarg-period\n"),outdir
);
1219 if((fp_in
=fopen(warea
,"r"))==NULL
){
1220 fprintf(stderr
, "===SARG: (removetmp) %s: %s\n",_("Cannot open file"),warea
);
1223 while(fgets(buf
,sizeof(buf
),fp_in
)!=NULL
) {
1224 if(strncmp(buf
,"TOTAL",5) == 0 && (buf
[6]=='\t' || buf
[6]==' '))
1228 if((fp_in
=fopen(warea
,"w"))==NULL
){
1229 fprintf(stderr
, "SARG: (removetmp) %s: %s\n",_("Cannot open file"),warea
);
1234 if (snprintf(warea
,sizeof(warea
),"%s/sarg-period",outdir
)>=sizeof(warea
)) {
1235 debuga(_("(removetmp) directory too long to remove: %s/sarg-period\n"),outdir
);
1243 void load_excludecodes(const char *ExcludeCodes
)
1250 if(ExcludeCodes
[0] == '\0')
1253 if((excludecode
=(char *) malloc(1024))==NULL
) {
1254 fprintf(stderr
, "SARG: %s (1024):\n",_("malloc error"));
1257 bzero(excludecode
,1024);
1259 if((fp_in
=fopen(ExcludeCodes
,"r"))==NULL
) {
1260 debuga(_("(util) Cannot open file: %s (exclude_codes)\n"),ExcludeCodes
);
1264 while(fgets(data
,sizeof(data
),fp_in
)!=NULL
) {
1265 for (i
=strlen(data
)-1 ; i
>=0 && (unsigned char)data
[i
]<=' ' ; i
--) data
[i
]=0;
1267 strcat(excludecode
,data
);
1268 strcat(excludecode
,";");
1276 void free_excludecodes(void)
1284 int vercode(const char *code
)
1289 if (excludecode
&& excludecode
[0]!=0) {
1291 for (cod
=excludecode
; cod
; cod
=strchr(cod
+1,';')) {
1292 if (strncmp(code
,cod
,clen
)==0 && cod
[clen
]==';')
1299 void fixnone(char *str
)
1303 for (i
=strlen(str
)-1 ; i
>=0 && (unsigned char)str
[i
]<=' ' ; i
--);
1304 if(i
==3 && strncmp(str
,"none",4) == 0)
1310 void fixendofline(char *str
)
1314 for (i
=strlen(str
)-1 ; i
>=0 && (unsigned char)str
[i
]<=' ' ; i
--) str
[i
]=0;
1317 #ifdef LEGACY_TESTVALIDUSERCHAR
1318 int testvaliduserchar(const char *user
)
1324 for (y
=0; y
<strlen(UserInvalidChar
); y
++) {
1325 for (x
=0; x
<strlen(user
); x
++) {
1326 if(user
[x
] == UserInvalidChar
[y
])
1333 int testvaliduserchar(const char *user
)
1336 char * p_UserInvalidChar
= UserInvalidChar
;
1337 const char * p_user
;
1339 while( *p_UserInvalidChar
) {
1342 if( *p_UserInvalidChar
== *p_user
)
1346 p_UserInvalidChar
++ ;
1352 int compar( const void *a
, const void *b
)
1353 { if( *(int *)a
> *(int *)b
) return 1;
1354 if( *(int *)a
< *(int *)b
) return -1;
1358 int getnumlist( char *buf
, numlist
*list
, const int len
, const int maxvalue
)
1360 int i
, j
, d
, flag
, r1
, r2
;
1361 char *pbuf
, **bp
, *strbufs
[ 24 ];
1364 strtok( buf
, " \t" );
1365 for( *bp
= strtok( NULL
, "," ), list
->len
= 0; *bp
; *bp
= strtok( NULL
, "," ) ) {
1366 if( ++bp
>= &strbufs
[ 24 ] )
1373 for( i
= 0; i
< list
->len
; i
++ ) {
1374 if( strchr( strbufs
[ i
], '-' ) != 0 ) {
1375 pbuf
= strbufs
[ i
];
1376 strtok( pbuf
, "-" );
1377 pbuf
= strtok( NULL
, "\0" );
1378 r1
= atoi( strbufs
[ i
] );
1379 if( ( r2
= atoi( pbuf
) ) >= maxvalue
|| r1
>= r2
)
1381 if( i
+ d
+ ( r2
- r1
) + 1 <= len
) {
1382 for( j
= r1
; j
<= r2
; j
++ )
1383 list
->list
[ i
+ d
++ ] = j
;
1388 if( ( list
->list
[ i
+ d
] = atoi( strbufs
[ i
] ) ) >= maxvalue
)
1392 qsort( list
->list
, list
->len
, sizeof( int ), compar
);
1395 for( i
= 0; i
< list
->len
- 1; i
++ )
1396 if( list
->list
[ i
] == list
->list
[ i
+ 1 ] ) {
1397 for( j
= i
+ 1; j
< list
->len
; j
++ )
1398 list
->list
[ j
- 1 ] = list
->list
[ j
];
1408 char *get_size(const char *path
, const char *file
)
1411 static char response
[255];
1415 if (snprintf(cmd
,sizeof(cmd
),"du -skh %s%s",path
,file
)>=sizeof(cmd
)) {
1416 debuga(_("Cannot get disk space because the path %s%s is too long\n"),path
,file
);
1419 fp
= popen(cmd
, "r");
1420 if (!fgets(response
, sizeof(response
), fp
)) {
1421 debuga(_("Cannot get disk size with command %s\n"),cmd
);
1424 ptr
=strchr(response
,'\t');
1426 debuga(_("The command %s failed\n"),cmd
);
1435 void show_info(FILE *fp_ou
)
1439 if(!ShowSargInfo
) return;
1440 zdate(ftime
, sizeof(ftime
), DateFormat
);
1441 fprintf(fp_ou
,"<div class=\"info\">%s <a href='%s'>%s-%s</a> %s %s</div>\n",_("Generated by"),URL
,PGM
,VERSION
,_("on"),ftime
);
1444 void show_sarg(FILE *fp_ou
, int depth
)
1448 if(!ShowSargLogo
) return;
1449 fputs("<div class=\"logo\"><a href=\"http://sarg.sourceforge.net\"><img src=\"",fp_ou
);
1450 for (i
=0 ; i
<depth
; i
++)
1452 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
);
1455 void write_logo_image(FILE *fp_ou
)
1457 if(LogoImage
[0]!='\0')
1458 fprintf(fp_ou
, "<div class=\"logo\"><img src=\"%s\" width=\"%s\" height=\"%s\" alt=\"Logo\"> %s</div>\n",LogoImage
,Width
,Height
,LogoText
);
1461 void write_html_header(FILE *fp_ou
, int depth
, const char *page_title
)
1463 //fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n",fp_ou);
1464 fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n<html>\n",fp_ou
);
1465 fprintf(fp_ou
, "<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n",CharSet
);
1466 if (page_title
) fprintf(fp_ou
,"<title>%s</title>\n",page_title
);
1468 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
);
1469 write_logo_image(fp_ou
);
1470 show_sarg(fp_ou
, depth
);
1471 fprintf(fp_ou
,"<div class=\"title\"><table cellpadding=\"0\" cellspacing=\"0\">\n<tr><th class=\"title_c\">%s</th></tr>\n",Title
);
1474 void close_html_header(FILE *fp_ou
)
1476 fputs("</table></div>\n",fp_ou
);
1479 void write_html_trailer(FILE *fp_ou
)
1482 fputs("</body>\n</html>\n",fp_ou
);
1485 void output_html_string(FILE *fp_ou
,const char *str
,int maxlen
)
1489 while (*str
&& (maxlen
<=0 || i
<maxlen
)) {
1492 fputs("&",fp_ou
);
1495 fputs("<",fp_ou
);
1498 fputs(">",fp_ou
);
1501 fputs(""",fp_ou
);
1504 fputs("'",fp_ou
);
1512 if (maxlen
>0 && i
>=maxlen
)
1513 fputs("…",fp_ou
);
1516 void output_html_url(FILE *fp_ou
,const char *url
)
1520 fputs("&",fp_ou
);
1531 printf("SARG: ------------------------------------------------------------------------------\n");
1532 printf(_("SARG: MALICIUS CODE DETECTED.\n"));
1533 printf(_("SARG: I think someone is trying to execute arbitrary code in your system using sarg.\n"));
1534 printf(_("SARG: please review your access.log and/or your useragent.log file.\n"));
1535 printf(_("SARG: process stoped. No actions taken.\n"));
1536 printf("SARG: ------------------------------------------------------------------------------\n");
1538 if (snprintf(dir
,sizeof(dir
),"%s/sarg",tmp
)>=sizeof(dir
)) {
1539 debuga(_("temporary directory too long: %s/sarg\n"),tmp
);
1543 unlinkdir(dirname
,0);
1548 void url_hostname(const char *url
,char *hostname
,int hostsize
)
1553 for (i
=0 ; i
<hostsize
&& url
[i
] && url
[i
]!='/' ; i
++)
1558 void url_module(const char *url
, char *w2
)
1564 for(x
=strlen(url
)-1; x
>=0; x
--) {
1565 if(url
[x
] == '/' || y
>=sizeof(w
)-1) break;
1574 for(y
=y
-1; y
>=0; y
--) {
1580 void url_to_file(const char *url
,char *file
,int filesize
)
1586 for(i
=0; i
<filesize
&& *url
; url
++) {
1587 if(*url
=='?' || *url
=='-' || *url
=='.' || *url
==':' || *url
=='/' || *url
=='\\' ||
1588 *url
=='*' || *url
=='\'' || *url
=='\"' || *url
=='$') {
1589 if (!skip
) file
[i
++]='_';
1601 printf(_("SARG Version: %s\n"),VERSION
);
1605 char *get_param_value(const char *param
,char *line
)
1609 while (*line
==' ' || *line
=='\t') line
++;
1611 if (strncasecmp(line
,param
,plen
)) return(NULL
);
1612 if (line
[plen
]!=' ' && line
[plen
]!='\t') return(NULL
);
1614 while (*line
==' ' || *line
=='\t') line
++;
1618 void unlinkdir(const char *dir
,int contentonly
)
1622 struct dirent
*direntp
;
1628 while ((direntp
= readdir(dirp
)) != NULL
) {
1629 if (direntp
->d_name
[0] == '.' && (direntp
->d_name
[1] == '\0' ||
1630 (direntp
->d_name
[1] == '.' && direntp
->d_name
[2] == '\0')))
1632 if (snprintf(dname
,sizeof(dname
),"%s/%s",dir
,direntp
->d_name
)>=sizeof(dname
)) {
1633 debuga(_("directory name to delete too long: %s/%s\n"),dir
,direntp
->d_name
);
1637 err
=lstat(dname
,&st
);
1639 err
=stat(dname
,&st
);
1642 debuga(_("cannot stat %s\n"),dname
);
1645 if (S_ISREG(st
.st_mode
)) {
1646 if (unlink(dname
)) {
1647 debuga(_("cannot delete %s - %s\n"),dname
,strerror(errno
));
1650 } else if (S_ISDIR(st
.st_mode
)) {
1653 debuga(_("unknown path type %s\n"),dname
);
1660 debuga(_("cannot delete %s - %s\n"),dir
,strerror(errno
));
1666 int longline_prepare(struct longlinestruct
*line
)
1668 line
->size
=INITIAL_LINE_BUFFER_SIZE
;
1669 line
->buffer
=malloc(line
->size
);
1678 char *longline_read(FILE *fp_in
,struct longlinestruct
*line
)
1684 if (!line
->buffer
) return(NULL
);
1687 for (i
=line
->end
; i
<line
->length
&& (line
->buffer
[i
]=='\n' || line
->buffer
[i
]=='\r') ; i
++);
1688 if (i
<line
->length
) {
1692 nread
=(feof(fp_in
)) ? 0 : fread(line
->buffer
,1,line
->size
,fp_in
);
1693 if (nread
==0) return(NULL
);
1698 line
->start
=line
->end
;
1700 for (i
=line
->end
; i
<line
->length
&& line
->buffer
[i
]!='\n' && line
->buffer
[i
]!='\r' ; i
++);
1702 if (line
->end
<line
->length
) break;
1704 if (line
->start
>0) {
1705 for (i
=line
->start
; i
<line
->length
; i
++) line
->buffer
[i
-line
->start
]=line
->buffer
[i
];
1706 line
->length
-=line
->start
;
1707 line
->end
-=line
->start
;
1710 if (line
->length
>=line
->size
) {
1712 newbuf
=realloc(line
->buffer
,line
->size
);
1714 debuga(_("Not enough memory to read one more line from the input log file\n"));
1717 line
->buffer
=newbuf
;
1719 nread
=(feof(fp_in
)) ? 0 : fread(line
->buffer
+line
->length
,1,line
->size
-line
->length
,fp_in
);
1721 if (line
->end
<=line
->start
) return(NULL
);
1722 if (line
->end
>=line
->size
) {
1723 line
->end
=line
->size
;
1725 newbuf
=realloc(line
->buffer
,line
->size
);
1727 debuga(_("Not enough memory to read one more line from the input log file\n"));
1730 line
->buffer
=newbuf
;
1732 line
->buffer
[line
->end
]='\0';
1733 return(line
->buffer
+line
->start
);
1735 line
->length
+=nread
;
1737 line
->buffer
[line
->end
++]='\0';
1738 return(line
->buffer
+line
->start
);
1741 void longline_free(struct longlinestruct
*line
)