]>
git.ipfire.org Git - thirdparty/sarg.git/blob - util.c
2 * AUTHOR: Pedro Lineu Orso pedro.orso@gmail.com
4 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
7 * please look at http://sarg.sourceforge.net/donations.php
8 * ---------------------------------------------------------------------
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
26 // #define LEGACY_MY_ATOLL
27 // #define LEGACY_TESTVALIDUSERCHAR
29 #include "include/conf.h"
30 #include "include/defs.h"
32 #if defined(HAVE_BACKTRACE)
33 #define USE_GETWORD_BACKTRACE 1
35 #define USE_GETWORD_BACKTRACE 0
38 static char mtab1
[ 12 ][ 4 ]={ "Jan" , "Feb" , "Mar" , "Apr" , "May" , "Jun" , "Jul" , "Aug" , "Sep" , "Oct" , "Nov" , "Dec" };
40 //! The list of the HTTP codes to exclude from the report.
41 static char * excludecode
= NULL
;
43 /*void fgetword(char *word, char *line, int stop)
48 for (x=0; line[x] && (line[x] != stop); x++) word[x] = line[x];
55 tchar = strchr(line, stop);
56 if (tchar == NULL) strcpy(word, line);
59 difflen = tchar - line;
60 strncpy(word, line, difflen);
65 #if USE_GETWORD_BACKTRACE
66 static void getword_backtrace ( void )
72 n
= backtrace ( buffer
, sizeof ( buffer
)/ sizeof ( buffer
[ 0 ]));
74 calls
= backtrace_symbols ( buffer
, n
);
76 fprintf ( stderr
, "SARG: getword backtrace: \n " );
77 for ( i
= 0 ; i
< n
; i
++) {
78 fprintf ( stderr
, "SARG: %d:%s \n " , i
+ 1 , calls
[ i
]);
83 #endif //USE_GETWORD_BACKTRACE
85 void getword_start ( struct getwordstruct
* gwarea
, const char * line
)
87 gwarea
-> beginning
= line
;
91 void getword_restart ( struct getwordstruct
* gwarea
)
93 gwarea
-> current
= gwarea
-> beginning
;
96 int getword ( char * word
, int limit
, struct getwordstruct
* gwarea
, int stop
)
100 for ( x
= 0 ;(( gwarea
-> current
[ x
]) && ( gwarea
-> current
[ x
] != stop
)); x
++) {
102 printf ( "SARG: getword loop detected after %d bytes. \n " , x
);
103 printf ( "SARG: Line= \" %s \"\n " , gwarea
-> beginning
);
104 printf ( "SARG: Record= \" %s \"\n " , gwarea
-> current
);
105 printf ( "SARG: searching for \' x%x \'\n " , stop
);
106 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
107 word
[( limit
> 0 ) ? limit
- 1 : 0 ]= '\0' ;
108 #if USE_GETWORD_BACKTRACE
113 word
[ x
] = gwarea
-> current
[ x
];
117 if ( gwarea
-> current
[ x
]) ++ x
;
122 int getword_multisep ( char * word
, int limit
, struct getwordstruct
* gwarea
, int stop
)
126 for ( x
= 0 ;(( gwarea
-> current
[ x
]) && ( gwarea
-> current
[ x
] != stop
)); x
++) {
128 printf ( "SARG: getword_multisep loop detected. \n " );
129 printf ( "SARG: Line= \" %s \"\n " , gwarea
-> beginning
);
130 printf ( "SARG: Record= \" %s \"\n " , gwarea
-> current
);
131 printf ( "SARG: searching for \' x%x \'\n " , stop
);
132 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
133 if ( limit
> 0 ) word
[ limit
- 1 ]= '\0' ;
134 #if USE_GETWORD_BACKTRACE
140 word
[ x
] = gwarea
-> current
[ x
];
144 while ( gwarea
-> current
[ x
] && gwarea
-> current
[ x
]== stop
) ++ x
;
149 int getword_skip ( int limit
, struct getwordstruct
* gwarea
, int stop
)
153 for ( x
= 0 ;( gwarea
-> current
[ x
] && ( gwarea
-> current
[ x
] != stop
)); x
++) {
155 printf ( "SARG: getword_skip loop detected after %d bytes. \n " , x
);
156 printf ( "SARG: Line= \" %s \"\n " , gwarea
-> beginning
);
157 printf ( "SARG: Record= \" %s \"\n " , gwarea
-> current
);
158 printf ( "SARG: searching for \' x%x \'\n " , stop
);
159 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
160 #if USE_GETWORD_BACKTRACE
167 if ( gwarea
-> current
[ x
]) ++ x
;
172 int getword_atoll ( long long int * number
, struct getwordstruct
* gwarea
, int stop
)
177 if ( gwarea
-> current
[ 0 ] == '-' ) {
180 } else if ( gwarea
-> current
[ 0 ] == '+' ) {
184 for ( x
= 0 ; isdigit ( gwarea
-> current
[ x
]); x
++) {
185 * number
=(* number
* 10 ) + gwarea
-> current
[ x
]- '0' ;
187 if ( gwarea
-> current
[ x
] && gwarea
-> current
[ x
]!= stop
) {
188 printf ( "SARG: getword_atoll loop detected after %d bytes. \n " , x
);
189 printf ( "SARG: Line= \" %s \"\n " , gwarea
-> beginning
);
190 printf ( "SARG: Record= \" %s \"\n " , gwarea
-> current
);
191 printf ( "SARG: searching for \' x%x \'\n " , stop
);
192 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
193 #if USE_GETWORD_BACKTRACE
200 if ( gwarea
-> current
[ x
]) ++ x
;
206 #define MAXLLL 30 //!< Maximum number of digits in long long (a guess).
207 long long int my_atoll ( const char * nptr
)
209 long long int returnval
= 0LL ;
210 int max_digits
= MAXLLL
;
212 // Soak up all the white space
213 while ( isspace ( * nptr
)) {
217 //For each character left to right
218 //change the character to a single digit
219 //multiply what we had before by 10 and add the new digit
221 while (-- max_digits
&& isdigit ( * nptr
))
223 returnval
= ( returnval
* 10 ) + ( * nptr
++ - '0' ) ;
229 int is_absolute ( const char * path
)
231 if (* path
== '/' ) return ( 1 );
233 if ( isalpha ( path
[ 0 ]) && path
[ 1 ]== ':' ) return ( 1 );
238 void my_mkdir ( const char * name
)
244 if (! is_absolute ( name
)) {
245 fprintf ( stderr
, "SARG: Invalid path (%s). Please, use absolute paths only. \n " , name
);
246 fprintf ( stderr
, "SARG: process aborted. \n " );
251 for ( i
= 0 ; name
[ i
] ; i
++) {
253 fprintf ( stderr
, "SARG: directory name too long %s \n " , name
);
256 if ( chars
> 0 && name
[ i
] == '/' ) {
258 if ( access ( w0
, R_OK
) != 0 ) {
260 fprintf ( stderr
, "SARG: mkdir %s %s \n " , w0
, strerror ( errno
));
261 fprintf ( stderr
, "SARG: process aborted. \n " );
266 if ( name
[ i
] != '/' ) chars
++;
270 if ( access ( name
, R_OK
) != 0 ) {
271 if ( mkdir ( name
, 0755 )) {
272 fprintf ( stderr
, "SARG: mkdir %s %s \n " , name
, strerror ( errno
));
273 fprintf ( stderr
, "SARG: process aborted. \n " );
280 void my_lltoa ( unsigned long long int n
, char s
[], int len
)
288 s
[ slen
++] = ( n
% 10 ) + '0' ;
289 } while (( n
/= 10 ) > 0 );
292 for ( i
= 0 , j
= slen
- 1 ; i
< j
; i
++, j
--) {
300 for ( j
= slen
; j
>= 0 ; j
--)
308 void builddia ( char * dia
, const char * mes
, const char * ano
, const char * df
, char * wdata
)
313 if ( strlen ( dia
) < 1 ) return ;
315 for ( nmes
= 0 ; nmes
< 12 ; nmes
++) {
316 if ( strcmp ( mtab1
[ nmes
], mes
) == 0 ) {
322 snprintf ( wdata
, 9 , "%s%02d%s" , ano
, nmes
, dia
);
325 snprintf ( ndia
, sizeof ( ndia
), "%s/%02d/%s" , dia
, nmes
, ano
);
327 snprintf ( ndia
, sizeof ( ndia
), "%02d/%s/%s" , nmes
, dia
, ano
);
334 void buildymd ( const char * dia
, const char * mes
, const char * ano
, char * wdata
)
338 for ( nmes
= 0 ; nmes
< 12 ; nmes
++) {
339 if ( strcmp ( mtab1
[ nmes
], mes
) == 0 )
343 sprintf ( wdata
, "%s%02d%s" , ano
, nmes
+ 1 , dia
);
348 void conv_month ( char * month
)
352 for ( x
= 0 ; x
< 12 && strcmp ( mtab1
[ x
], month
)!= 0 ; x
++);
353 sprintf ( month
, "%02d" , x
+ 1 );
357 void conv_month_name ( char * month
)
363 strcpy ( month
, mtab1
[ x
- 1 ]);
367 void name_month ( char * month
, int month_len
)
369 int x
, z
= atoi ( month
)- 1 ;
372 struct getwordstruct gwarea
;
375 getword_start (& gwarea
, m
);
378 if ( getword_multisep ( w
, sizeof ( w
),& gwarea
, ',' )< 0 ) {
379 printf ( "SARG: Maybe you have a broken record or garbage in the names of the months. \n " );
382 if ( getword_multisep ( month
, month_len
,& gwarea
, ',' )< 0 ) {
383 printf ( "SARG: Maybe you have a broken record or garbage in the name of the months. \n " );
389 void fixper ( char * tbuf
, char * period
, const char * duntil
)
392 char dia
[ 5 ], mes
[ 5 ], ano
[ 5 ];
395 strncpy ( dia
, duntil
+ 6 , 2 );
397 strncpy ( mes
, duntil
+ 4 , 2 );
399 strncpy ( ano
, duntil
, 4 );
404 strcpy ( mes
, mtab1
[ x
- 1 ]);
406 if ( strcmp ( df
, "e" ) == 0 )
407 sprintf ( warea
, "%s%s%s" , dia
, mes
, ano
);
408 else if ( strcmp ( df
, "u" ) == 0 )
409 sprintf ( warea
, "%s%s%s" , ano
, mes
, dia
);
413 strcat ( period
, warea
);
417 void debuga ( const char * msg
,...)
421 fputs ( "SARG: " , stderr
);
423 vfprintf ( stderr
, msg
, ap
);
429 void debugaz ( const char * head
, const char * msg
)
431 fprintf ( stderr
, "SARG: (util) %s=%s \n " , head
, msg
);
443 for ( i
= 0 ; ip
[ i
]; i
++) {
465 char * fixnum ( long long int value
, int n
)
467 #define MAXLEN_FIXNUM 1024
468 char num
[ MAXLEN_FIXNUM
]= "" ;
469 char buf
[ MAXLEN_FIXNUM
* 2 ];
471 static char ret
[ MAXLEN_FIXNUM
* 2 ];
473 register int i
, j
, k
;
475 static char abbrev
[ 30 ];
477 my_lltoa ( value
, num
, 0 );
479 if ( strcmp ( DisplayedValues
, "abbreviation" ) == 0 ) {
480 numlen
= strlen ( num
);
482 sprintf ( abbrev
, "%s" , num
);
483 if ( numlen
== 4 || numlen
== 7 || numlen
== 10 || numlen
== 13 ) {
484 snprintf ( abbrev
, 2 , "%s" , num
);
485 strncat ( abbrev
, "." , 1 );
486 strncat ( abbrev
, num
+ 1 , 2 );
487 if (! n
) return ( abbrev
);
489 strncat ( abbrev
, "K" , 1 );
491 strncat ( abbrev
, "M" , 1 );
492 else if ( numlen
== 10 )
493 strncat ( abbrev
, "G" , 1 );
494 else if ( numlen
== 13 )
495 strncat ( abbrev
, "T" , 1 );
497 if ( numlen
== 5 || numlen
== 8 || numlen
== 11 || numlen
== 14 ) {
498 snprintf ( abbrev
, 3 , "%s" , num
);
499 strncat ( abbrev
, "." , 1 );
500 strncat ( abbrev
, num
+ 2 , 2 );
501 if (! n
) return ( abbrev
);
503 strncat ( abbrev
, "K" , 1 );
505 strncat ( abbrev
, "M" , 1 );
506 else if ( numlen
== 11 )
507 strncat ( abbrev
, "G" , 1 );
508 else if ( numlen
== 14 )
509 strncat ( abbrev
, "T" , 1 );
511 if ( numlen
== 6 || numlen
== 9 || numlen
== 12 || numlen
== 15 ) {
512 snprintf ( abbrev
, 4 , "%s" , num
);
513 strncat ( abbrev
, "." , 1 );
514 strncat ( abbrev
, num
+ 3 , 2 );
515 if (! n
) return ( abbrev
);
517 strncat ( abbrev
, "K" , 1 );
519 strncat ( abbrev
, "M" , 1 );
520 else if ( numlen
== 12 )
521 strncat ( abbrev
, "G" , 1 );
522 else if ( numlen
== 15 )
523 strncat ( abbrev
, "T" , 1 );
529 bzero ( buf
, MAXLEN_FIXNUM
* 2 );
535 for ( i
= strlen ( num
) - 1 , j
= 0 ; i
> - 1 ; i
--) {
536 if ( k
== 2 && i
!= 0 ) {
539 pbuf
[ j
++] = ( UseComma
) ? ',' : '.' ;
549 for ( i
= strlen ( pbuf
) - 1 , j
= 0 ; i
> - 1 ; i
--, j
++)
558 char * fixnum2 ( long long int value
, int n
)
560 #define MAXLEN_FIXNUM2 1024
561 char num
[ MAXLEN_FIXNUM2
];
562 char buf
[ MAXLEN_FIXNUM2
* 2 ];
564 static char ret
[ MAXLEN_FIXNUM2
* 2 ];
566 register int i
, j
, k
;
568 my_lltoa ( value
, num
, 0 );
569 bzero ( buf
, MAXLEN_FIXNUM2
* 2 );
575 for ( i
= strlen ( num
) - 1 , j
= 0 ; i
> - 1 ; i
--) {
576 if ( k
== 2 && i
!= 0 ) {
579 pbuf
[ j
++] = ( UseComma
) ? ',' : '.' ;
589 for ( i
= strlen ( pbuf
) - 1 , j
= 0 ; i
> - 1 ; i
--, j
++)
599 void buildhref ( char * href
)
603 if ( strcmp ( href
, "./" ) == 0 ){
605 strcat ( href
, "<a href='" );
609 href
[ strlen ( href
)- 1 ]= '\0' ;
610 sprintf ( whref
, "%s" , strrchr ( href
, '/' ));
612 strcpy ( href
, "<a href='" );
621 char * buildtime ( long long int elap
)
624 int num
= elap
/ 1000 ;
633 min
=( num
% 3600 ) / 60 ;
635 sprintf ( buf
, "%02d:%02d:%02d" , hor
, min
, sec
);
642 void obtdate ( const char * dirname
, const char * name
, char * data
)
648 sprintf ( wdir
, "%s%s/sarg-date" , dirname
, name
);
649 if (( fp_in
= fopen ( wdir
, "rt" )) == 0 ) {
650 sprintf ( wdir
, "%s%s/date" , dirname
, name
);
651 if (( fp_in
= fopen ( wdir
, "rt" )) == 0 ) {
657 if (! fgets ( data
, 80 , fp_in
)) {
658 fprintf ( stderr
, "Failed to read the date in %s \n " , wdir
);
669 void formatdate ( char * date
, int date_size
, int year
, int month
, int day
, int hour
, int minute
, int second
, int dst
)
675 memset (& ltm
, 0 , sizeof ( ltm
));
676 if ( year
>= 1900 ) ltm
. tm_year
= year
- 1900 ;
677 if ( month
>= 1 && month
<= 12 ) ltm
. tm_mon
= month
- 1 ;
678 if ( day
>= 1 && day
<= 31 ) ltm
. tm_mday
= day
;
679 if ( hour
>= 0 && hour
< 24 ) ltm
. tm_hour
= hour
;
680 if ( minute
>= 0 && minute
< 60 ) ltm
. tm_min
= minute
;
681 if ( second
>= 0 && second
< 60 ) ltm
. tm_sec
= second
;
683 unixtime
= mktime (& ltm
); //fill the missing entries
684 fulltm
= localtime (& unixtime
);
685 //strftime(date,date_size,"%a %b %d %H:%M:%S %Z %Y",fulltm);
686 strftime ( date
, date_size
, "%c" , fulltm
);
690 void obtuser ( const char * dirname
, const char * name
, char * tuser
)
696 sprintf ( wdir
, "%s%s/sarg-users" , dirname
, name
);
697 if (( fp_in
= fopen ( wdir
, "r" ))== NULL
) {
698 sprintf ( wdir
, "%s%s/users" , dirname
, name
);
699 if (( fp_in
= fopen ( wdir
, "r" ))== NULL
) {
705 if (! fgets ( tuser
, 20 , fp_in
)) {
706 fprintf ( stderr
, "Failed to read the user in %s \n " , wdir
);
717 void obttotal ( const char * dirname
, const char * name
, char * tbytes
, const char * tuser
, char * media
)
724 long long int wtuser
= 0 ;
725 long long int twork
= 0 ;
726 struct getwordstruct gwarea
;
728 sprintf ( wdir
, "%s%s/sarg-general" , dirname
, name
);
729 if (( fp_in
= fopen ( wdir
, "r" )) == 0 ) {
730 sprintf ( wdir
, "%s%s/general" , dirname
, name
);
731 if (( fp_in
= fopen ( wdir
, "r" )) == 0 ) {
738 while ( fgets ( buf
, sizeof ( buf
), fp_in
)!= NULL
) {
739 getword_start (& gwarea
, buf
);
740 if ( getword ( warea
, sizeof ( warea
),& gwarea
, ' \t ' )< 0 ) {
741 printf ( "SARG: Maybe you have a broken record or garbage in your %s file. \n " , wdir
);
744 if ( strcmp ( warea
, "TOTAL" ) != 0 )
746 if ( getword_skip ( MAXLEN
,& gwarea
, ' \t ' )< 0 ) {
747 printf ( "SARG: Maybe you have a broken record or garbage in your %s file. \n " , wdir
);
750 if ( getword_atoll (& twork
,& gwarea
, ' \t ' )< 0 ) {
751 printf ( "SARG: Maybe you have a broken record or garbage in your %s file. \n " , wdir
);
754 strcpy ( tbytes
, fixnum ( twork
, 1 ));
759 wtuser
= my_atoll ( tuser
);
766 strcpy ( media
, fixnum ( med
, 1 ));
772 void gperiod ( const char * dirname
, const char * period
)
776 char wdirname
[ MAXLEN
];
778 strcpy ( wdirname
, dirname
);
779 strcat ( wdirname
, "/sarg-period" );
781 if (( fp_ou
= fopen ( wdirname
, "w" ))== NULL
){
782 fprintf ( stderr
, "SARG: (report) %s: %s \n " , text
[ 45 ], wdirname
);
790 debuga ( "%s" ,( char *) text
[ 50 ]);
796 static void copy_images ( void )
798 FILE * img_in
, * img_ou
;
801 char srcfile
[ MAXLEN
];
802 char dstfile
[ MAXLEN
];
804 struct dirent
* direntp
;
809 if ( snprintf ( images
, sizeof ( images
), "%simages" , outdir
)>= sizeof ( images
)) {
810 fprintf ( stderr
, "SARG: Cannot copy images to target directory %simages \n " , outdir
);
813 if ( access ( images
, R_OK
)!= 0 ) {
817 strcpy ( imgdir
, IMAGEDIR
);
818 dirp
= opendir ( imgdir
);
820 fprintf ( stderr
, "SARG: (util) %s %s: %s \n " , "Can't open directory" , imgdir
, strerror ( errno
));
823 while (( direntp
= readdir ( dirp
)) != NULL
){
824 if ( direntp
-> d_name
[ 0 ]== '.' )
826 sprintf ( srcfile
, "%s/%s" , imgdir
, direntp
-> d_name
);
827 if ( stat ( srcfile
,& info
)) {
828 fprintf ( stderr
, "SARG: Cannot stat \" %s \" - %s \n " , srcfile
, strerror ( errno
));
831 if ( S_ISREG ( info
. st_mode
)) {
832 sprintf ( dstfile
, "%s/%s" , images
, direntp
-> d_name
);
833 img_in
= fopen ( srcfile
, "rb" );
835 img_ou
= fopen ( dstfile
, "wb" );
837 while (( nread
= fread ( buffer
, 1 , sizeof ( buffer
), img_in
))> 0 ) {
838 fwrite ( buffer
, 1 , nread
, img_ou
);
842 fprintf ( stderr
, "SARG: (util): %s %s: %s \n " , text
[ 45 ]? text
[ 45 ]: "Can't open/create file" , dstfile
, strerror ( errno
));
845 fprintf ( stderr
, "SARG: (util): %s %s: %s \n " , text
[ 45 ]? text
[ 45 ]: "Can't open file" , srcfile
, strerror ( errno
));
848 ( void ) closedir ( dirp
);
853 void vrfydir ( const char * per1
, const char * addr
, const char * site
, const char * us
, const char * form
)
859 char dirname2
[ MAXLEN
];
867 if ( strcmp ( IndexTree
, "date" ) == 0 ) {
868 bzero ( y1
, sizeof ( y1
));
869 bzero ( y2
, sizeof ( y2
));
870 bzero ( d1
, sizeof ( d1
));
871 bzero ( d2
, sizeof ( d2
));
872 bzero ( m1
, sizeof ( m1
));
873 bzero ( m2
, sizeof ( m2
));
874 if ( strncmp ( df
, "u" , 1 ) == 0 ) {
875 strncpy ( y1
, period
, 4 );
876 strncpy ( y2
, period
+ 10 , 4 );
877 strncpy ( m1
, period
+ 4 , 3 );
878 strncpy ( m2
, period
+ 14 , 3 );
879 strncpy ( d1
, period
+ 7 , 2 );
880 strncpy ( d2
, period
+ 17 , 2 );
881 } else if ( strncmp ( df
, "e" , 1 ) == 0 ) {
882 strncpy ( d1
, period
+ 0 , 2 );
883 strncpy ( d2
, period
+ 10 , 2 );
884 strncpy ( m1
, period
+ 2 , 3 );
885 strncpy ( m2
, period
+ 12 , 3 );
886 strncpy ( y1
, period
+ 5 , 4 );
887 strncpy ( y2
, period
+ 15 , 4 );
892 sprintf ( wdir
, "%s%s" , outdir
, y1
);
893 if ( strcmp ( y1
, y2
) != 0 ) {
897 if ( access ( wdir
, R_OK
) != 0 )
902 if ( strcmp ( m1
, m2
) != 0 ) {
906 if ( access ( wdir
, R_OK
) != 0 )
911 if ( strcmp ( d1
, d2
) != 0 ) {
916 sprintf ( wdir
, "%s%s" , outdir
, per1
);
923 if ( addr
[ 0 ] != '\0' ) {
927 if ( site
[ 0 ] != '\0' ) {
932 if ( strcmp ( dirname
, wdir
) != 0 )
933 strcpy ( dirname
, wdir
);
935 if ( strcmp ( IndexTree
, "date" ) != 0 ) {
936 if (! OverwriteReport
) {
938 if ( access ( wdir
, R_OK
) == 0 ) {
939 sprintf ( wdir
, "%s.%d" , dirname
, num
);
940 sprintf ( per2
, "%s.%d" , per1
, num
);
949 fprintf ( stderr
, "SARG: %s: %s %s %s \n " , text
[ 51 ], dirname
, text
[ 52 ], wdir
);
950 rename ( dirname
, wdir
);
953 if ( access ( wdir
, R_OK
) == 0 ) {
954 sprintf ( csort
, "rm -r \" %s \" " , wdir
);
955 cstatus
= system ( csort
);
956 if (! WIFEXITED ( cstatus
) || WEXITSTATUS ( cstatus
)) {
957 fprintf ( stderr
, "SARG: command return status %d \n " , WEXITSTATUS ( cstatus
));
958 fprintf ( stderr
, "SARG: command: %s \n " , csort
);
965 strcpy ( dirname2
, wdir
);
966 if (! OverwriteReport
) {
968 if ( access ( wdir
, R_OK
) == 0 ) {
969 sprintf ( wdir
, "%s.%d" , dirname2
, num
);
970 sprintf ( per2
, "%s.%d" , per1
, num
);
979 fprintf ( stderr
, "SARG: %s: %s %s %s \n " , text
[ 51 ], dirname2
, text
[ 52 ], wdir
);
980 rename ( dirname2
, wdir
);
981 strcpy ( dirname2
, wdir
);
984 if ( access ( wdir
, R_OK
) == 0 ) {
985 sprintf ( csort
, "rm -r \" %s \" " , wdir
);
986 cstatus
= system ( csort
);
987 if (! WIFEXITED ( cstatus
) || WEXITSTATUS ( cstatus
)) {
988 fprintf ( stderr
, "SARG: command return status %d \n " , WEXITSTATUS ( cstatus
));
989 fprintf ( stderr
, "SARG: command: %s \n " , csort
);
995 if ( access ( wdir
, R_OK
) != 0 )
999 strcpy ( dirname2
, wdir
);
1001 sprintf ( wdir
, "%s/sarg-date" , dirname
);
1002 if (( fp_ou
= fopen ( wdir
, "wt" )) == 0 ) {
1003 fprintf ( stderr
, "SARG: cannot open %s for writing \n " , wdir
);
1008 //strftime(wdir,sizeof(wdir),"%a %b %d %H:%M:%S %Z %Y",localtime(&curtime));
1009 loctm
= localtime (& curtime
);
1010 strftime ( wdir
, sizeof ( wdir
), "%Y-%m-%d %H:%M:%S" , loctm
);
1011 fprintf ( fp_ou
, "%s %d \n " , wdir
, loctm
-> tm_isdst
);
1017 void strip_latin ( char * line
)
1024 for ( i
= 0 ; line
[ i
]; i
++){
1026 if ( line
[ i
]== ';' ) skip
= 0 ;
1039 void zdate ( char * ftime
, int ftimesize
, const char * DateFormat
)
1046 local
= localtime (& t
);
1047 if ( strcmp ( DateFormat
, "u" ) == 0 )
1048 strftime ( ftime
, ftimesize
, "%b/%d/%Y %H:%M" , local
);
1049 if ( strcmp ( DateFormat
, "e" ) == 0 )
1050 strftime ( ftime
, ftimesize
, "%d/%b/%Y-%H:%M" , local
);
1051 if ( strcmp ( DateFormat
, "w" ) == 0 )
1052 strftime ( ftime
, ftimesize
, "%V-%H-%M" , local
);
1057 char * fixtime ( long int elap
)
1060 int num
= elap
/ 1000 ;
1064 static char buf
[ 12 ];
1066 if ( strcmp ( datetimeby
, "bytes" ) == 0 ) {
1067 strcpy ( buf
, fixnum ( elap
, 1 ));
1072 sprintf ( buf
, "00:00:%02ld" , elap
);
1077 min
=( num
% 3600 ) / 60 ;
1080 if ( hor
== 0 && min
== 0 && sec
== 0 )
1083 sprintf ( buf
, "%01d:%02d:%02d" , hor
, min
, sec
);
1090 void date_from ( char * date
, char * dfrom
, char * duntil
)
1101 strncpy ( wdate
, date
, sizeof ( wdate
)- 1 );
1102 wdate
[ sizeof ( wdate
)- 1 ]= '\0' ;
1103 if ( strchr ( wdate
, '-' ) == NULL
) {
1104 if ( strlen ( wdate
)* 2 + 1 >= sizeof ( wdate
)) {
1105 fprintf ( stderr
, "SARG: Invalid date range passed as argument. \n " );
1113 if ( sscanf ( wdate
, "%d/%d/%d-%d/%d/%d" ,& diaf
,& mesf
,& anof
,& diau
,& mesu
,& anou
)!= 6 ) {
1114 fprintf ( stderr
, "SARG: The date range passed as argument is not formated as dd/mm/yyyy-dd/mm/yyyy. \n " );
1118 sprintf ( dfrom
, "%04d%02d%02d" , anof
, mesf
, diaf
);
1119 sprintf ( duntil
, "%04d%02d%02d" , anou
, mesu
, diau
);
1124 char * strlow ( char * string
)
1130 for ( s
= string
; * s
; ++ s
)
1140 char * strup ( char * string
)
1146 for ( s
= string
; * s
; ++ s
)
1154 void subs ( char * str
, int size
, char * from
, char * to
)
1162 tmp
= strstr ( str
, from
);
1172 if ( ss
+ shift
>= size
){
1173 fprintf ( stderr
, "SARG: Cannot replace %s by %s in %s and fit within %d bytes \n " , from
, to
, str
, size
);
1176 for ( i
= strlen ( tmp
) ; i
>= sf
; i
--)
1177 tmp
[ i
+ shift
]= tmp
[ i
];
1178 } else if ( shift
< 0 ) {
1180 for ( i
= sf
; i
<= len
; i
++)
1181 tmp
[ i
+ shift
]= tmp
[ i
];
1183 memcpy ( tmp
, to
, st
);
1188 void removetmp ( const char * outdir
)
1194 if (! RemoveTempFiles
)
1198 debuga ( "%s: sarg-general, sarg-period" , text
[ 82 ]);
1200 if ( snprintf ( warea
, sizeof ( warea
), "%s/sarg-general" , outdir
)>= sizeof ( warea
)) {
1201 fprintf ( stderr
, "SARG: (removetmp) directory too long to remove: %s/sarg-period \n " , outdir
);
1204 if (( fp_in
= fopen ( warea
, "r" ))== NULL
){
1205 fprintf ( stderr
, "===SARG: (removetmp) %s: %s \n " , text
[ 45 ], warea
);
1208 while ( fgets ( buf
, sizeof ( buf
), fp_in
)!= NULL
) {
1209 if ( strncmp ( buf
, "TOTAL" , 5 ) == 0 )
1213 if (( fp_in
= fopen ( warea
, "w" ))== NULL
){
1214 fprintf ( stderr
, "SARG: (removetmp) %s: %s \n " , text
[ 45 ], warea
);
1219 if ( snprintf ( warea
, sizeof ( warea
), "%s/sarg-period" , outdir
)>= sizeof ( warea
)) {
1220 fprintf ( stderr
, "SARG: (removetmp) directory too long to remove: %s/sarg-period \n " , outdir
);
1228 void load_excludecodes ( const char * ExcludeCodes
)
1235 if ( ExcludeCodes
[ 0 ] == '\0' )
1238 if (( excludecode
=( char *) malloc ( 1024 ))== NULL
) {
1239 fprintf ( stderr
, "SARG: %s (1024): \n " , text
[ 59 ]);
1242 bzero ( excludecode
, 1024 );
1244 if (( fp_in
= fopen ( ExcludeCodes
, "r" ))== NULL
) {
1245 fprintf ( stderr
, "SARG: (util) Cannot open file: %s (exclude_codes) \n " , ExcludeCodes
);
1249 while ( fgets ( data
, sizeof ( data
), fp_in
)!= NULL
) {
1250 for ( i
= strlen ( data
)- 1 ; i
>= 0 && ( unsigned char ) data
[ i
]<= ' ' ; i
--) data
[ i
]= 0 ;
1252 strcat ( excludecode
, data
);
1253 strcat ( excludecode
, ";" );
1261 void free_excludecodes ( void )
1269 int vercode ( const char * code
)
1274 if ( excludecode
&& excludecode
[ 0 ]!= 0 ) {
1276 for ( cod
= excludecode
; cod
; cod
= strchr ( cod
+ 1 , ';' )) {
1277 if ( strncmp ( code
, cod
, clen
)== 0 && cod
[ clen
]== ';' )
1284 void fixnone ( char * str
)
1288 for ( i
= strlen ( str
)- 1 ; i
>= 0 && ( unsigned char ) str
[ i
]<= ' ' ; i
--);
1289 if ( i
== 3 && strncmp ( str
, "none" , 4 ) == 0 )
1295 void fixendofline ( char * str
)
1299 for ( i
= strlen ( str
)- 1 ; i
>= 0 && ( unsigned char ) str
[ i
]<= ' ' ; i
--) str
[ i
]= 0 ;
1302 #ifdef LEGACY_TESTVALIDUSERCHAR
1303 int testvaliduserchar ( const char * user
)
1309 for ( y
= 0 ; y
< strlen ( UserInvalidChar
); y
++) {
1310 for ( x
= 0 ; x
< strlen ( user
); x
++) {
1311 if ( user
[ x
] == UserInvalidChar
[ y
])
1318 int testvaliduserchar ( const char * user
)
1321 char * p_UserInvalidChar
= UserInvalidChar
;
1322 const char * p_user
;
1324 while ( * p_UserInvalidChar
) {
1327 if ( * p_UserInvalidChar
== * p_user
)
1331 p_UserInvalidChar
++ ;
1337 int compar ( const void * a
, const void * b
)
1338 { if ( *( int *) a
> *( int *) b
) return 1 ;
1339 if ( *( int *) a
< *( int *) b
) return - 1 ;
1343 int getnumlist ( char * buf
, numlist
* list
, const int len
, const int maxvalue
)
1345 int i
, j
, d
, flag
, r1
, r2
;
1346 char * pbuf
, ** bp
, * strbufs
[ 24 ];
1349 strtok ( buf
, " \t " );
1350 for ( * bp
= strtok ( NULL
, "," ), list
-> len
= 0 ; * bp
; * bp
= strtok ( NULL
, "," ) ) {
1351 if ( ++ bp
>= & strbufs
[ 24 ] )
1358 for ( i
= 0 ; i
< list
-> len
; i
++ ) {
1359 if ( strchr ( strbufs
[ i
], '-' ) != 0 ) {
1360 pbuf
= strbufs
[ i
];
1361 strtok ( pbuf
, "-" );
1362 pbuf
= strtok ( NULL
, "\0" );
1363 r1
= atoi ( strbufs
[ i
] );
1364 if ( ( r2
= atoi ( pbuf
) ) >= maxvalue
|| r1
>= r2
)
1366 if ( i
+ d
+ ( r2
- r1
) + 1 <= len
) {
1367 for ( j
= r1
; j
<= r2
; j
++ )
1368 list
-> list
[ i
+ d
++ ] = j
;
1373 if ( ( list
-> list
[ i
+ d
] = atoi ( strbufs
[ i
] ) ) >= maxvalue
)
1377 qsort ( list
-> list
, list
-> len
, sizeof ( int ), compar
);
1380 for ( i
= 0 ; i
< list
-> len
- 1 ; i
++ )
1381 if ( list
-> list
[ i
] == list
-> list
[ i
+ 1 ] ) {
1382 for ( j
= i
+ 1 ; j
< list
-> len
; j
++ )
1383 list
-> list
[ j
- 1 ] = list
-> list
[ j
];
1393 char * get_size ( const char * path
, const char * file
)
1396 static char response
[ 255 ];
1400 if ( snprintf ( cmd
, sizeof ( cmd
), "du -skh %s%s" , path
, file
)>= sizeof ( cmd
)) {
1401 printf ( "SARG: Cannot get disk space because the path %s%s is too long. \n " , path
, file
);
1404 fp
= popen ( cmd
, "r" );
1405 if (! fgets ( response
, sizeof ( response
), fp
)) {
1406 fprintf ( stderr
, "SARG: Cannot get disk size with command %s" , cmd
);
1409 ptr
= strchr ( response
, ' \t ' );
1411 fprintf ( stderr
, "SARG: The command %s failed. \n " , cmd
);
1420 void show_info ( FILE * fp_ou
)
1424 if (! ShowSargInfo
) return ;
1425 zdate ( ftime
, sizeof ( ftime
), DateFormat
);
1426 fprintf ( fp_ou
, "<div align= \" center \" ><table><tr><td><br><br></td><td class= \" info \" >%s <a href='%s'><font class= \" info \" >%s-%s</font></a> %s %s</td></tr></table></div> \n " , text
[ 108 ], URL
, PGM
, VERSION
, text
[ 109 ], ftime
);
1429 void show_sarg ( FILE * fp_ou
, const char * ind
)
1431 if ( ShowSargLogo
) fprintf ( fp_ou
, "<div align= \" center \" ><table class= \" logo \" > \n <tr><th><a href= \" http://sarg.sourceforge.net \" ><img src= \" %s/images/sarg.png \" title= \" SARG, Squid Analysis Report Generator. Logo by Osamu Matsuzaki \" alt= \" Sarg \" ></a> Squid Analysis Report Generator</th></tr> \n <tr><th class= \" title \" > </th></tr> \n </table></div> \n " , ind
);
1434 void write_logo_image ( FILE * fp_ou
)
1436 if ( LogoImage
[ 0 ]!= '\0' )
1437 fprintf ( fp_ou
, "<div align= \" center \" ><table class= \" logo \" > \n <tr><th><img src= \" %s \" width= \" %s \" height= \" %s \" alt= \" Logo \" > %s</th></tr> \n <tr><td height= \" 5 \" ></td></tr> \n </table> \n </div> \n " , LogoImage
, Width
, Height
, LogoText
);
1440 void write_html_header ( FILE * fp_ou
, const char * ind
)
1442 fprintf ( fp_ou
, "<!DOCTYPE HTML PUBLIC \" -//W3C//DTD HTML 4.01 Transitional//EN \" \" http://www.w3.org/TR/html4/loose.dtd \" > \n <html> \n <head> \n <meta http-equiv= \" Content-Type \" content= \" text/html; charset=%s \" > \n " , CharSet
);
1444 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
);
1445 write_logo_image ( fp_ou
);
1446 show_sarg ( fp_ou
, ind
);
1447 fprintf ( fp_ou
, "<div align= \" center \" ><table cellpadding= \" 0 \" cellspacing= \" 0 \" > \n <tr><th class= \" title \" >%s</th></tr> \n </table></div> \n <div align= \" center \" ><table cellpadding= \" 1 \" cellspacing= \" 2 \" > \n <tr><td></td><td></td></tr> \n " , Title
);
1450 void output_html_string ( FILE * fp_ou
, const char * str
)
1456 fputs ( "&" , fp_ou
);
1459 fputs ( "<" , fp_ou
);
1462 fputs ( ">" , fp_ou
);
1465 fputs ( """ , fp_ou
);
1468 fputs ( "'" , fp_ou
);
1482 printf ( "SARG: ------------------------------------------------------------------------------ \n " );
1483 printf ( "SARG: MALICIUS CODE DETECTED. \n " );
1484 printf ( "SARG: I think someone is trying to execute arbitrary code in your system using sarg. \n " );
1485 printf ( "SARG: please review your access.log and/or your useragent.log file. \n " );
1486 printf ( "SARG: process stoped. No actions taken. \n " );
1487 printf ( "SARG: ------------------------------------------------------------------------------ \n " );
1489 if ( snprintf ( cmd
, sizeof ( cmd
), "rm -rf \" %s/sarg \" " , tmp
)>= sizeof ( cmd
)) {
1490 fprintf ( stderr
, "SARG: temporary directory too long: %s/sarg \n " , tmp
);
1493 cstatus
= system ( cmd
);
1494 if (! WIFEXITED ( cstatus
) || WEXITSTATUS ( cstatus
)) {
1495 fprintf ( stderr
, "SARG: command return status %d \n " , WEXITSTATUS ( cstatus
));
1496 fprintf ( stderr
, "SARG: command: %s \n " , cmd
);
1499 if ( snprintf ( cmd
, sizeof ( cmd
), "rm -rf \" %s \" " , dirname
)>= sizeof ( cmd
)) {
1500 fprintf ( stderr
, "SARG: directory to delete too long: %s \n " , dirname
);
1503 cstatus
= system ( cmd
);
1504 if (! WIFEXITED ( cstatus
) || WEXITSTATUS ( cstatus
)) {
1505 fprintf ( stderr
, "SARG: command return status %d \n " , WEXITSTATUS ( cstatus
));
1506 fprintf ( stderr
, "SARG: command: %s \n " , cmd
);
1514 void url_module ( const char * url
, char * w2
)
1520 for ( x
= strlen ( url
)- 1 ; x
>= 0 ; x
--) {
1521 if ( url
[ x
] == '/' || y
>= sizeof ( w
)- 1 ) break ;
1530 for ( y
= y
- 1 ; y
>= 0 ; y
--) {
1537 void write_html_trailer ( FILE * fp_ou
)
1541 fputs ( "</table></div> \n " , fp_ou
);
1542 zdate ( ftime
, sizeof ( ftime
), DateFormat
);
1544 fputs ( "</body> \n </html> \n " , fp_ou
);
1549 printf ( "SARG Version: %s \n " , VERSION
);
1553 char * get_param_value ( const char * param
, char * line
)
1557 while (* line
== ' ' || * line
== ' \t ' ) line
++;
1559 if ( strncasecmp ( line
, param
, plen
)) return ( NULL
);
1560 if ( line
[ plen
]!= ' ' && line
[ plen
]!= ' \t ' ) return ( NULL
);
1562 while (* line
== ' ' || * line
== ' \t ' ) line
++;
1566 void read_usertab ( const char * UserTabFile
)
1574 if ( UserTabFile
[ 0 ] == '\0' ) return ;
1576 debuga ( "%s: %s" , text
[ 86 ], UserTabFile
);
1577 if (( fp_usr
= fopen ( UserTabFile
, "r" ))== NULL
) {
1578 fprintf ( stderr
, "SARG: (log) %s: %s - %s \n " , text
[ 45 ], UserTabFile
, strerror ( errno
));
1581 fseek ( fp_usr
, 0 , SEEK_END
);
1582 nreg
= ftell ( fp_usr
);
1584 fprintf ( stderr
, "SARG: Cannot get the size of file %s" , UserTabFile
);
1588 fseek ( fp_usr
, 0 , SEEK_SET
);
1589 if (( userfile
=( char *) malloc ( nreg
))== NULL
){
1590 fprintf ( stderr
, "SARG ERROR: %s" , text
[ 87 ]);
1595 while ( fgets ( buf
, sizeof ( buf
), fp_usr
)!= NULL
) {
1596 if ( buf
[ 0 ]== '#' ) continue ;
1599 while ( buf
[ z1
] && ( unsigned char ) buf
[ z1
]> ' ' ) {
1600 if ( z2
+ 3 >= nreg
) { //need at least 3 additional bytes for the minimum string "\n\t\0"
1601 fprintf ( stderr
, "SARG: The list of the users is too long in your %s file. \n " , UserTabFile
);
1604 userfile
[ z2
++]= buf
[ z1
++];
1606 while ( buf
[ z1
] && ( unsigned char ) buf
[ z1
]<= ' ' ) z1
++;
1607 userfile
[ z2
++]= ' \n ' ;
1608 while ( buf
[ z1
] && ( unsigned char ) buf
[ z1
]> ' ' ) {
1609 if ( z2
+ 2 >= nreg
) { //need at least 2 additional bytes for "\t\0"
1610 fprintf ( stderr
, "SARG: The list of the users is too long in your %s file. \n " , UserTabFile
);
1613 userfile
[ z2
++]= buf
[ z1
++];
1615 userfile
[ z2
++]= ' \t ' ;
1621 void get_usertab_name ( const char * user
, char * name
, int namelen
)
1627 if ( UserTabFile
[ 0 ] == '\0' ) {
1628 strncpy ( name
, user
, namelen
);
1631 sprintf ( warea
, " \t %s \n " , user
);
1632 if (( str
=( char *) strstr ( userfile
, warea
)) == ( char *) NULL
) {
1633 strncpy ( name
, user
, namelen
);
1636 str
= strchr ( str
+ 1 , ' \n ' );
1638 for ( z1
= 0 ; * str
!= ' \t ' && z1
< namelen
; z1
++) {