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 #include "include/conf.h"
28 #include "include/defs.h"
34 #define REPORT_EVERY_X_LINES 5000
35 #define MAX_OPEN_USER_FILES 10
39 struct userfilestruct
*next
;
40 struct userinfostruct
*user
;
44 /*@null@*/static char *userfile
=NULL
;
46 numlist weekdays
= { { 0, 1, 2, 3, 4, 5, 6 }, 7 };
47 numlist hours
= { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 }, 24 };
49 //! Selected locale set through the environment variable.
50 char *CurrentLocale
=NULL
;
52 static void getusers(const char *pwdfile
, int debug
);
54 int main(int argc
,char *argv
[])
65 ISACOL_Last
//last entry of the list !
73 ILF_Last
//last entry of the list !
76 FILE *fp_in
= NULL
, *fp_denied
=NULL
, *fp_authfail
=NULL
, *fp_log
=NULL
;
78 char sz_Download_Unsort
[ 20000 ] ;
79 FILE * fp_Download_Unsort
= NULL
;
91 char smartfilter
[MAXLEN
];
101 char hexclude
[MAXLEN
];
107 char denied_unsort
[MAXLEN
];
108 char denied_sort
[MAXLEN
];
109 char authfail_unsort
[MAXLEN
];
110 char start_hour
[128];
114 char user
[MAX_USER_LEN
];
115 char splitprefix
[MAXLEN
];
116 enum InputLogFormat ilf
;
117 int ilf_count
[ILF_Last
];
129 int isa_ncols
=0,isa_cols
[ISACOL_Last
];
131 long long int nbytes
;
143 long int max_elapsed
=0;
144 long long int iyear
, imonth
, iday
;
149 unsigned long recs1
=0UL;
150 unsigned long recs2
=0UL;
151 unsigned long int lines_read
=0UL;
152 unsigned long int records_kept
=0UL;
153 unsigned long int nusers
=0UL;
154 int OutputNonZero
= REPORT_EVERY_X_LINES
;
155 bool download_flag
=false;
156 char download_url
[MAXLEN
];
157 struct getwordstruct gwarea
;
162 time_t read_start_time
;
163 time_t read_end_time
;
164 time_t process_start_time
;
165 time_t process_end_time
;
167 double process_elapsed
;
169 struct userinfostruct
*uinfo
;
170 struct userfilestruct
*first_user_file
, *ufile
, *ufile1
, *prev_ufile
;
172 static int convert
=0;
173 static int output_css
=0;
174 static int show_statis
=0;
176 static struct option long_options
[]=
178 {"convert",no_argument
,&convert
,1},
179 {"css",no_argument
,&output_css
,1},
180 {"help",no_argument
,NULL
,'h'},
181 {"lastlog",required_argument
,NULL
,2},
182 {"keeplogs",no_argument
,NULL
,3},
183 {"split",no_argument
,&split
,1},
184 {"splitprefix",required_argument
,NULL
,'P'},
185 {"statistics",no_argument
,&show_statis
,1},
189 start_time
=time(NULL
);
192 setlocale(LC_TIME
,"");
195 #if defined(ENABLE_NLS) && defined(HAVE_LOCALE_H)
196 CurrentLocale
=setlocale (LC_ALL
, "");
197 if (!CurrentLocale
) {
198 fprintf(stderr
,"SARG: Cannot set the locale LC_ALL to the environment variable\n");
201 if (!bindtextdomain (PACKAGE_NAME
, LOCALEDIR
)) {
202 fprintf(stderr
,"SARG: Cannot bind to text domain %s in directory %s (%s)\n",PACKAGE_NAME
,LOCALEDIR
,strerror(errno
));
205 if (!textdomain (PACKAGE_NAME
)) {
206 fprintf(stderr
,"SARG: Cannot set gettext domain for %s PACKAGE_NAME (%s)\n",PACKAGE_NAME
,strerror(errno
));
216 UserAgentLog
[0]='\0';
217 ExcludeHosts
[0]='\0';
218 ExcludeUsers
[0]='\0';
225 ExternalCSSFile
[0]='\0';
226 RedirectorLogFormat
[0]='\0';
228 for (ilf
=0 ; ilf
<ILF_Last
; ilf
++) ilf_count
[ilf
]=0;
230 snprintf(ExcludeCodes
,sizeof(ExcludeCodes
),"%s/exclude_codes",SYSCONFDIR
);
231 strcpy(GraphDaysBytesBarColor
,"orange");
232 strcpy(BgColor
,"#ffffff");
233 strcpy(TxColor
,"#000000");
234 strcpy(TxBgColor
,"lavender");
235 strcpy(TiColor
,"darkblue");
238 strcpy(LogoTextColor
,"#000000");
239 strcpy(HeaderColor
,"darkblue");
240 strcpy(HeaderBgColor
,"#dddddd");
241 strcpy(LogoTextColor
,"#006699");
242 strcpy(FontSize
,"9px");
243 strcpy(TempDir
,"/tmp");
244 strcpy(OutputDir
,"/var/www/html/squid-reports");
245 AnonymousOutputFiles
=false;
247 strcpy(DateFormat
,"u");
248 OverwriteReport
=false;
249 RemoveTempFiles
=true;
250 strcpy(ReplaceIndex
,"index.html");
252 RecordsWithoutUser
=RECORDWITHOUTUSER_IP
;
254 strcpy(MailUtility
,"mailx");
258 TopuserSort
=TOPUSER_SORT_BYTES
| TOPUSER_SORT_REVERSE
;
259 UserSort
=USER_SORT_BYTES
| USER_SORT_REVERSE
;
260 TopsitesSort
=TOPSITE_SORT_CONNECT
| TOPSITE_SORT_REVERSE
;
262 strcpy(FontFace
,"Verdana,Tahoma,Arial");
263 datetimeby
=DATETIME_BYTE
;
264 strcpy(CharSet
,"ISO-8859-1");
266 strcpy(PrivacyString
,"***.***.***.***");
267 strcpy(PrivacyStringColor
,"blue");
269 TopUserFields
=TOPUSERFIELDS_NUM
| TOPUSERFIELDS_DATE_TIME
| TOPUSERFIELDS_USERID
| TOPUSERFIELDS_CONNECT
|
270 TOPUSERFIELDS_BYTES
| TOPUSERFIELDS_SETYB
| TOPUSERFIELDS_IN_CACHE_OUT
|
271 TOPUSERFIELDS_USED_TIME
| TOPUSERFIELDS_MILISEC
| TOPUSERFIELDS_PTIME
|
272 TOPUSERFIELDS_TOTAL
| TOPUSERFIELDS_AVERAGE
;
273 UserReportFields
=USERREPORTFIELDS_CONNECT
| USERREPORTFIELDS_BYTES
| USERREPORTFIELDS_SETYB
|
274 USERREPORTFIELDS_IN_CACHE_OUT
| USERREPORTFIELDS_USED_TIME
| USERREPORTFIELDS_MILISEC
|
275 USERREPORTFIELDS_PTIME
| USERREPORTFIELDS_TOTAL
| USERREPORTFIELDS_AVERAGE
;
276 strcpy(DataFileDelimiter
,";");
277 DataFileFields
=DATA_FIELD_USER
| DATA_FIELD_DATE
| DATA_FIELD_TIME
| DATA_FIELD_URL
| DATA_FIELD_CONNECT
|
278 DATA_FIELD_BYTES
| DATA_FIELD_IN_CACHE
| DATA_FIELD_OUT_CACHE
| DATA_FIELD_ELAPSED
;
279 ShowReadStatistics
=true;
280 strcpy(IndexSortOrder
,"D");
283 ParsedOutputLog
[0]='\0';
284 strcpy(ParsedOutputLogCompress
,"/bin/gzip -f");
285 DisplayedValues
=DISPLAY_ABBREV
;
286 strcpy(HeaderFontSize
,"9px");
287 strcpy(TitleFontSize
,"11px");
288 strcpy(AuthUserTemplateFile
,"sarg_htaccess");
289 set_download_suffix("7z,ace,arj,avi,bat,bin,bz2,bzip,cab,com,cpio,dll,doc,dot,exe,gz,iso,lha,lzh,mdb,mov,mp3,mpeg,mpg,mso,nrg,ogg,ppt,rar,rtf,shs,src,sys,tar,tgz,vcd,vob,wma,wmv,zip");
292 strcpy(GraphFont
,FONTDIR
"/DejaVuSans.ttf");
296 strcpy(Ulimit
,"20000");
297 NtlmUserFormat
=NTLMUSERFORMAT_DOMAINUSER
;
298 IndexTree
=INDEX_TREE_FILE
;
299 IndexFields
=INDEXFIELDS_DIRSIZE
;
300 strcpy(RealtimeTypes
,"GET,PUT,CONNECT");
301 RealtimeUnauthRec
=REALTIME_UNAUTH_REC_SHOW
;
302 RedirectorFilterOutDate
=true;
303 DansguardianFilterOutDate
=true;
304 DataFileUrl
=DATAFILEURL_IP
;
305 strcpy(MaxElapsed
,"28800000");
306 BytesInSitesUsersReport
=0;
307 UserAuthentication
=0;
308 strcpy(LDAPHost
,"127.0.0.1");
310 LDAPProtocolVersion
=3;
313 LDAPBaseSearch
[0]='\0';
314 strcpy(LDAPFilterSearch
, "(uid=%s)");
315 strcpy(LDAPTargetAttr
, "cn");
336 UserInvalidChar
[0]='\0';
338 SquidGuardConf
[0]='\0';
339 DansGuardianConf
[0]='\0';
342 HostAliasFile
[0]='\0';
347 dansguardian_count
=0;
350 DeniedReportLimit
=10;
351 AuthfailReportLimit
=10;
352 DansGuardianReportLimit
=10;
353 SquidGuardReportLimit
=10;
354 DownloadReportLimit
=50;
363 realtime_access_log_lines
=1000;
372 bzero(IncludeUsers
, sizeof(IncludeUsers
));
373 bzero(ExcludeString
, sizeof(ExcludeString
));
374 first_user_file
=NULL
;
375 memset(&period
,0,sizeof(period
));
378 for(x
=0; x
<MAXLOGS
; x
++)
379 AccessLog
[x
][0]='\0';
380 AccessLogFromCmdLine
=0;
381 RedirectorLogFromCmdLine
=0;
383 strcpy(Title
,_("Squid User Access Report"));
385 while((ch
= getopt_long_only(argc
, argv
, "a:b:c:d:e:f:g:hikl:L:mno:P:prs:t:u:vw:xyz",long_options
,&option_index
)) != -1){
391 lastlog
=atoi(optarg
);
397 safe_strcpy(addr
,optarg
,sizeof(addr
));
399 case 'b': //unused option
400 safe_strcpy(uagent
,optarg
,sizeof(uagent
));
403 safe_strcpy(hexclude
,optarg
,sizeof(hexclude
));
406 safe_strcpy(date
,optarg
,sizeof(date
));
407 date_from(date
, sizeof(date
), &dfrom
, &duntil
);
410 safe_strcpy(email
,optarg
,sizeof(email
));
413 safe_strcpy(ConfigFile
,optarg
,sizeof(ConfigFile
));
416 safe_strcpy(df
,optarg
,sizeof(df
));
428 if (NAccessLog
>=MAXLOGS
) {
429 debuga(_("Too many log files passed on command line with option %s.\n"),"-l");
432 if (strlen(optarg
)>=MAX_LOG_FILELEN
) {
433 debuga(_("Log file name too long passed on command line with option %s: %s\n"),"-l",optarg
);
436 strcpy(AccessLog
[NAccessLog
],optarg
);
438 AccessLogFromCmdLine
++;
441 if (NRedirectorLogs
>MAX_REDIRECTOR_LOGS
) {
442 debuga(_("Too many log files passed on command line with option %s.\n"),"-L");
445 if (strlen(optarg
)>=MAX_REDIRECTOR_FILELEN
) {
446 debuga(_("Log file name too long passed on command line with option %s: %s\n"),"-L",optarg
);
449 strcpy(RedirectorLogs
[NRedirectorLogs
],optarg
);
451 RedirectorLogFromCmdLine
++;
460 safe_strcpy(outdir
,optarg
,sizeof(outdir
));
466 safe_strcpy(splitprefix
,optarg
,sizeof(splitprefix
));
472 safe_strcpy(site
,optarg
,sizeof(site
));
478 if(strstr(optarg
,"-") == 0) {
479 if(sscanf(optarg
,"%d:%d",&h1
,&m1
)!=2) {
480 debuga(_("Time period passed on the command line with option -t must be HH:MM\n"));
485 snprintf(hm_str
,sizeof(hm_str
),"%02d:%02d",h1
,m1
);
487 if(sscanf(optarg
,"%d:%d-%d:%d",&h1
,&m1
,&h2
,&m2
)!=4) {
488 debuga(_("Time range passed on the command line with option -t must be HH:MM-HH:MM\n"));
493 snprintf(hm_str
,sizeof(hm_str
),"%02d:%02d-%02d:%02d",h1
,m1
,h2
,m2
);
498 safe_strcpy(us
,optarg
,sizeof(us
));
504 safe_strcpy(tmp
,optarg
,sizeof(tmp
));
509 case 'y': //unused option
516 debuga(_("Option -%c requires an argument\n"),optopt
);
532 for (iarq
=optind
; iarq
<argc
; iarq
++) {
533 if (NAccessLog
>=MAXLOGS
) {
534 debuga(_("Too many log files passed on command line.\n"));
537 if (strlen(argv
[iarq
])>=MAX_LOG_FILELEN
) {
538 debuga(_("Log file name too long passed on command line: %s\n"),argv
[iarq
]);
541 strcpy(AccessLog
[NAccessLog
],argv
[iarq
]);
543 AccessLogFromCmdLine
++;
547 if(debug
) debuga(_("Init\n"));
549 if(ConfigFile
[0] == '\0') snprintf(ConfigFile
,sizeof(ConfigFile
),"%s/sarg.conf",SYSCONFDIR
);
550 if(access(ConfigFile
, R_OK
) != 0) {
551 debuga(_("Cannot open file \"%s\": %s\n"),ConfigFile
,strerror(errno
));
555 if(access(ConfigFile
, R_OK
) == 0)
558 if(userip
) UserIp
=true;
560 if(dns
) ip2name_forcedns();
562 if (lastlog
>=0) LastLog
=lastlog
;
564 if(outdir
[0] == '\0') strcpy(outdir
,OutputDir
);
565 if(outdir
[0] != '\0') strcat(outdir
,"/");
572 if(IndexTree
== INDEX_TREE_FILE
)
573 strcpy(ImageFile
,"../images");
575 strcpy(ImageFile
,"../../../images");
578 if(DataFile
[0] != '\0')
581 if(df
[0] == '\0') strcpy(df
,DateFormat
);
582 else strcpy(DateFormat
,df
);
586 strcpy(DateFormat
,"u");
589 IndexTree
=INDEX_TREE_FILE
;
591 if(NAccessLog
== 0) {
592 strcpy(AccessLog
[0],"/var/log/squid/access.log");
601 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++)
602 splitlog(AccessLog
[iarq
], df
, dfrom
, duntil
, convert
, splitprefix
);
606 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++)
607 convlog(AccessLog
[iarq
], df
, dfrom
, duntil
);
611 load_excludecodes(ExcludeCodes
);
613 if(access(PasswdFile
, R_OK
) == 0) {
614 getusers(PasswdFile
,debug
);
618 if(hexclude
[0] == '\0')
619 strcpy(hexclude
,ExcludeHosts
);
620 if(hexclude
[0] != '\0') {
621 gethexclude(hexclude
,debug
);
625 if(ReportType
== 0) {
626 ReportType
=REPORT_TYPE_TOPUSERS
| REPORT_TYPE_TOPSITES
| REPORT_TYPE_USERS_SITES
|
627 REPORT_TYPE_SITES_USERS
| REPORT_TYPE_DATE_TIME
| REPORT_TYPE_DENIED
|
628 REPORT_TYPE_AUTH_FAILURES
| REPORT_TYPE_SITE_USER_TIME_DATE
| REPORT_TYPE_DOWNLOADS
;
631 if(access(ExcludeUsers
, R_OK
) == 0) {
632 getuexclude(ExcludeUsers
,debug
);
635 if (HostAliasFile
[0] != '\0')
636 read_hostalias(HostAliasFile
);
643 if(strcmp(ExcludeUsers
,"indexonly") == 0) indexonly
=true;
644 if(Index
== INDEX_ONLY
) indexonly
=true;
646 if(MaxElapsed
[0] != '\0') max_elapsed
=atol(MaxElapsed
);
648 if(uagent
[0] == '\0') strcpy(uagent
,UserAgentLog
);
650 if(tmp
[0] == '\0') strcpy(tmp
,TempDir
);
651 else strcpy(TempDir
,tmp
);
653 For historical reasons, the temporary directory is the subdirectory "sarg" of the path
654 provided by the user.
658 if (tmp
[0]!='\0' && strncmp(outdir
,tmp
,strlen(tmp
))==0) {
659 debuga(_("The output directory \"%s\" must be outside of the temporary directory \"%s\"\n"),outdir
,tmp
);
663 if(email
[0] == '\0' && OutputEmail
[0] != '\0') strcpy(email
,OutputEmail
);
665 if(email
[0] != '\0') {
671 if(access(tmp
, R_OK
) == 0) {
672 if (debug
) debuga(_("Deleting temporary directory \"%s\"\n"),tmp
);
676 snprintf(denied_unsort
,sizeof(denied_unsort
),"%s/denied.int_unsort",tmp
);
677 snprintf(denied_sort
,sizeof(denied_sort
),"%s/denied.int_log",tmp
);
678 snprintf(authfail_unsort
,sizeof(authfail_unsort
),"%s/authfail.int_unsort",tmp
);
681 debuga(_("Parameters:\n"));
682 debuga(_(" Hostname or IP address (-a) = %s\n"),addr
);
683 debuga(_(" Useragent log (-b) = %s\n"),uagent
);
684 debuga(_(" Exclude file (-c) = %s\n"),hexclude
);
685 debuga(_(" Date from-until (-d) = %s\n"),date
);
686 debuga(_(" Email address to send reports (-e) = %s\n"),email
);
687 debuga(_(" Config file (-f) = %s\n"),ConfigFile
);
688 if(strcmp(df
,"e") == 0)
689 debuga(_(" Date format (-g) = Europe (dd/mm/yyyy)\n"));
690 if(strcmp(df
,"u") == 0)
691 debuga(_(" Date format (-g) = USA (mm/dd/yyyy)\n"));
692 if(strcmp(df
,"w") == 0)
693 debuga(_(" Date format (-g) = Sites & Users (yyyy/ww)\n"));
694 debuga(_(" IP report (-i) = %s\n"),(iprel
) ? _("Yes") : _("No"));
695 debuga(_(" Keep temporary files (-k) = %s\n"),(KeepTempLog
) ? _("Yes") : _("No"));
696 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++)
697 debuga(_(" Input log (-l) = %s\n"),AccessLog
[iarq
]);
698 for (iarq
=0 ; iarq
<NRedirectorLogs
; iarq
++)
699 debuga(_(" Redirector log (-L) = %s\n"),RedirectorLogs
[iarq
]);
700 debuga(_(" Resolve IP Address (-n) = %s\n"),(Ip2Name
) ? _("Yes") : _("No"));
701 debuga(_(" Output dir (-o) = %s\n"),outdir
);
702 debuga(_("Use Ip Address instead of userid (-p) = %s\n"),(UserIp
) ? _("Yes") : _("No"));
703 debuga(_(" Accessed site (-s) = %s\n"),site
);
704 debuga(_(" Time (-t) = %s\n"),hm_str
);
705 debuga(_(" User (-u) = %s\n"),us
);
706 debuga(_(" Temporary dir (-w) = %s\n"),tmp
);
707 debuga(_(" Debug messages (-x) = %s\n"),(debug
) ? _("Yes") : _("No"));
708 debuga(_(" Process messages (-z) = %s\n"),(debugz
) ? _("Yes") : _("No"));
709 debuga(_(" Previous reports to keep (--lastlog) = %d\n"),LastLog
);
714 printf(_("Parameters:\n"));
715 printf(_(" Hostname or IP address (-a) = %s\n"),addr
);
716 printf(_(" Useragent log (-b) = %s\n"),uagent
);
717 printf(_(" Exclude file (-c) = %s\n"),hexclude
);
718 printf(_(" Date from-until (-d) = %s\n"),date
);
719 printf(_(" Email address to send reports (-e) = %s\n"),email
);
720 printf(_(" Config file (-f) = %s\n"),ConfigFile
);
721 if(strcmp(df
,"e") == 0)
722 printf(_(" Date format (-g) = Europe (dd/mm/yyyy)\n"));
723 if(strcmp(df
,"u") == 0)
724 printf(_(" Date format (-g) = USA (mm/dd/yyyy)\n"));
725 if(strcmp(df
,"w") == 0)
726 printf(_(" Date format (-g) = Sites & Users (yyyy/ww)\n"));
727 printf(_(" IP report (-i) = %s\n"),(iprel
) ? _("Yes") : _("No"));
728 printf(_(" Keep temporary files (-k) = %s\n"),(KeepTempLog
) ? _("Yes") : _("No"));
729 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++)
730 printf(_(" Input log (-l) = %s\n"),AccessLog
[iarq
]);
731 for (iarq
=0 ; iarq
<NRedirectorLogs
; iarq
++)
732 printf(_(" Redirector log (-L) = %s\n"),RedirectorLogs
[iarq
]);
733 printf(_(" Resolve IP Address (-n) = %s\n"),(Ip2Name
) ? _("Yes") : _("No"));
734 printf(_(" Output dir (-o) = %s\n"),outdir
);
735 printf(_("Use Ip Address instead of userid (-p) = %s\n"),(UserIp
) ? _("Yes") : _("No"));
736 printf(_(" Accessed site (-s) = %s\n"),site
);
737 printf(_(" Time (-t) = %s\n"),hm_str
);
738 printf(_(" User (-u) = %s\n"),us
);
739 printf(_(" Temporary dir (-w) = %s\n"),tmp
);
740 printf(_(" Debug messages (-x) = %s\n"),(debug
) ? _("Yes") : _("No"));
741 printf(_(" Process messages (-z) = %s\n"),(debugz
) ? _("Yes") : _("No"));
742 printf(_(" Previous reports to keep (--lastlog) = %d\n"),LastLog
);
743 printf(_("SARG version: %s\n"),VERSION
);
747 debuga(_("SARG version: %s\n"),VERSION
);
749 #ifdef ENABLE_DOUBLE_CHECK_DATA
750 debuga(_("Sarg compiled to report warnings if the output is inconsistent\n"));
753 maxopenfiles
=MAX_OPEN_USER_FILES
;
755 if (Ulimit
[0] != '\0') {
760 #if defined(RLIMIT_NOFILE)
761 getrlimit (RLIMIT_NOFILE
, &rl
);
762 #elif defined(RLIMIT_OFILE)
763 getrlimit (RLIMIT_OFILE
, &rl
);
765 #warning "No rlimit resource for the number of open files"
770 rl
.rlim_cur
= atol(Ulimit
);
771 rl
.rlim_max
= atol(Ulimit
);
772 #if defined(RLIMIT_NOFILE)
773 rc
=setrlimit (RLIMIT_NOFILE
, &rl
);
774 #elif defined(RLIMIT_OFILE)
775 rc
=setrlimit (RLIMIT_OFILE
, &rl
);
777 #warning "No rlimit resource for the number of open files"
780 debuga(_("setrlimit error: %s\n"),strerror(errno
));
784 debuga("Maximum file descriptor: cur=%ld max=%ld, changed to cur="RLIM_STRING
" max="RLIM_STRING
"\n",l1
,l2
,rl
.rlim_cur
,rl
.rlim_max
);
788 init_usertab(UserTabFile
);
790 if ((line
=longline_create())==NULL
) {
791 debuga(_("Not enough memory to read a log file\n"));
795 snprintf(sz_Download_Unsort
,sizeof(sz_Download_Unsort
),"%s/download.int_unsort", tmp
);
797 if(DataFile
[0]=='\0') {
798 if((ReportType
& REPORT_TYPE_DENIED
) != 0) {
799 if((fp_denied
=MY_FOPEN(denied_unsort
,"w"))==NULL
) {
800 debugapos("log",_("Cannot open file \"%s\": %s\n"),denied_unsort
,strerror(errno
));
805 if((ReportType
& REPORT_TYPE_DENIED
) != 0 || (ReportType
& REPORT_TYPE_AUTH_FAILURES
) != 0) {
806 if((fp_authfail
=MY_FOPEN(authfail_unsort
,"w"))==NULL
) {
807 debugapos("log",_("Cannot open file \"%s\": %s\n"),authfail_unsort
,strerror(errno
));
813 read_start_time
=time(NULL
);
814 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++) {
815 strcpy(arq
,AccessLog
[iarq
]);
819 if(strcmp(arq
,"-")==0) {
821 debuga(_("Reading access log file: from stdin\n"));
826 if (stat(arq
,&logstat
)!=0) {
827 debuga(_("Cannot get the modification time of input log file \"%s\": %s\nProcessing it anyway\n"),arq
,strerror(errno
));
829 struct tm
*logtime
=localtime(&logstat
.st_mtime
);
830 if ((logtime
->tm_year
+1900)*10000+(logtime
->tm_mon
+1)*100+logtime
->tm_mday
<dfrom
) {
831 debuga(_("Ignoring old log file %s\n"),arq
);
836 fp_in
=decomp(arq
,&from_pipe
);
838 debugapos("log",_("Cannot open file \"%s\": %s\n"),arq
,strerror(errno
));
841 if(debug
) debuga(_("Reading access log file: %s\n"),arq
);
846 // pre-read the file only if we have to show stats
847 if(ShowReadStatistics
&& !from_stdin
&& !from_pipe
) {
855 while ((nread
=fread(tmp4
,1,sizeof(tmp4
),fp_in
))>0) {
856 for (i
=0 ; i
<nread
; i
++)
858 if (tmp4
[i
]!='\n' && tmp4
[i
]!='\r') {
862 if (tmp4
[i
]=='\n' || tmp4
[i
]=='\r') {
869 printf(_("SARG: Records in file: %lu, reading: %3.2lf%%"),recs1
,0.);
874 longline_reset(line
);
876 while ((linebuf
=longline_read(fp_in
,line
))!=NULL
) {
877 blen
=strlen(linebuf
);
880 if (ilf
==ILF_Unknown
) {
881 if(strncmp(linebuf
,"#Software: Mic",14) == 0) {
882 fixendofline(linebuf
);
884 debuga(_("Log is from Microsoft ISA: %s\n"),linebuf
);
890 if(strncmp(linebuf
,"*** SARG Log ***",16) == 0) {
891 if (getperiod_fromsarglog(arqtt
,&period
)<0) {
892 debuga(_("The name of the file is invalid: %s\n"),arq
);
901 if(!fp_log
&& ParsedOutputLog
[0] && ilf
!=ILF_Sarg
) {
902 if(access(ParsedOutputLog
,R_OK
) != 0) {
903 my_mkdir(ParsedOutputLog
);
905 if (snprintf(arq_log
,sizeof(arq_log
),"%s/sarg_temp.log",ParsedOutputLog
)>=sizeof(arq_log
)) {
906 debuga(_("Path too long: "));
907 debuga_more("%s/sarg_temp.log\n",ParsedOutputLog
);
910 if((fp_log
=MY_FOPEN(arq_log
,"w"))==NULL
) {
911 debugapos("log",_("Cannot open file \"%s\": %s\n"),arq_log
,strerror(errno
));
914 fputs("*** SARG Log ***\n",fp_log
);
918 if( ShowReadStatistics
&& !from_stdin
&& !from_pipe
&& --OutputNonZero
<=0) {
919 double perc
= recs2
* 100. / recs1
;
920 printf(_("SARG: Records in file: %lu, reading: %3.2lf%%"),recs2
,perc
);
923 OutputNonZero
= REPORT_EVERY_X_LINES
;
925 if(blen
< 58) continue;
926 if(strstr(linebuf
,"HTTP/0.0") != 0) continue;
927 if(strstr(linebuf
,"logfile turned over") != 0) continue;
928 if(linebuf
[0] == ' ') continue;
931 if(ExcludeString
[0] != '\0') {
933 getword_start(&gwarea
,ExcludeString
);
934 while(strchr(gwarea
.current
,':') != 0) {
935 if (getword_multisep(val1
,sizeof(val1
),&gwarea
,':')<0) {
936 debuga(_("Invalid record in exclusion string\n"));
939 if((str
=(char *) strstr(linebuf
,val1
)) != (char *) NULL
) {
944 if(!exstring
&& (str
=(char *) strstr(linebuf
,gwarea
.current
)) != (char *) NULL
)
946 if(exstring
) continue;
951 printf("BUF=%s\n",linebuf
);
954 if (ilf
==ILF_Squid
|| ilf
==ILF_Common
|| ilf
==ILF_Unknown
) {
955 getword_start(&gwarea
,linebuf
);
956 if (getword(data
,sizeof(data
),&gwarea
,' ')<0) {
957 debuga(_("Invalid time in file \"%s\"\n"),arq
);
960 if((str
=(char *) strchr(data
, '.')) != (char *) NULL
&& (str
=(char *) strchr(str
+1, '.')) != (char *) NULL
) {
964 if (getword(user
,sizeof(user
),&gwarea
,' ')<0 || getword_skip(255,&gwarea
,' ')<0) {
965 debuga(_("Invalid record in file \"%s\"\n"),arq
);
969 if (getword_skip(255,&gwarea
,' ')<0 || getword(user
,sizeof(user
),&gwarea
,' ')<0) {
970 debuga(_("Invalid record in file \"%s\"\n"),arq
);
974 if (getword(data
,sizeof(data
),&gwarea
,']')<0 || getword_skip(MAXLEN
,&gwarea
,'"')<0 ||
975 getword(fun
,sizeof(fun
),&gwarea
,' ')<0) {
976 debuga(_("Invalid record in file \"%s\"\n"),arq
);
979 if (getword_ptr(linebuf
,&full_url
,&gwarea
,' ')<0) {
980 debuga(_("Invalid url in file \"%s\"\n"),arq
);
983 if (getword_skip(MAXLEN
,&gwarea
,' ')<0) {
984 debuga(_("Invalid record in file \"%s\"\n"),arq
);
987 if (getword(code2
,sizeof(code2
),&gwarea
,' ')<0) {
988 debuga(_("Invalid record in file \"%s\"\n"),arq
);
991 if (getword(tam
,sizeof(tam
),&gwarea
,' ')<0) {
992 debuga(_("Invalid record in file \"%s\"\n"),arq
);
995 if((str
=(char *) strchr(gwarea
.current
, ' ')) != (char *) NULL
) {
996 if (getword(code
,sizeof(code
),&gwarea
,' ')<0) {
997 debuga(_("Invalid record in file \"%s\"\n"),arq
);
1001 if (getword(code
,sizeof(code
),&gwarea
,'\0')<0) {
1002 debuga(_("Invalid record in file \"%s\"\n"),arq
);
1007 if ((str
= strchr(code
, ':')) != NULL
)
1010 if(strcmp(tam
,"\0") == 0)
1016 getword_start(&gwarea
,data
+1);
1017 if (getword_multisep(data
,sizeof(data
),&gwarea
,':')<0){
1018 debuga(_("Invalid date in file \"%s\"\n"),arq
);
1021 if (getword_multisep(hora
,sizeof(hora
),&gwarea
,' ')<0){
1022 debuga(_("Invalid date in file \"%s\"\n"),arq
);
1025 getword_start(&gwarea
,data
);
1026 if (getword_atoll(&iday
,&gwarea
,'/')<0){
1027 debuga(_("Invalid date in file \"%s\"\n"),arq
);
1030 if (getword(mes
,sizeof(mes
),&gwarea
,'/')<0){
1031 debuga(_("Invalid date in file \"%s\"\n"),arq
);
1034 if (getword_atoll(&iyear
,&gwarea
,'/')<0){
1035 debuga(_("Invalid date in file \"%s\"\n"),arq
);
1039 imonth
=month2num(mes
)+1;
1040 idata
=builddia(iday
,imonth
,iyear
);
1041 computedate(iyear
,imonth
,iday
,&tt
);
1042 if (sscanf(hora
,"%d:%d:%d",&tt
.tm_hour
,&tt
.tm_min
,&tt
.tm_sec
)!=3 || tt
.tm_hour
<0 || tt
.tm_hour
>=24 ||
1043 tt
.tm_min
<0 || tt
.tm_min
>=60 || tt
.tm_sec
<0 || tt
.tm_sec
>=60) {
1044 debuga(_("Invalid time in file \"%s\"\n"),arq
);
1050 if(ilf
==ILF_Unknown
|| ilf
==ILF_Squid
) {
1051 if (getword(elap
,sizeof(elap
),&gwarea
,' ')<0) {
1052 debuga(_("Invalid elapsed time in file \"%s\"\n"),arq
);
1055 while(strcmp(elap
,"") == 0 && gwarea
.current
[0] != '\0')
1056 if (getword(elap
,sizeof(elap
),&gwarea
,' ')<0) {
1057 debuga(_("Invalid elapsed time in file \"%s\"\n"),arq
);
1060 if(strlen(elap
) < 1) continue;
1061 if (getword(ip
,sizeof(ip
),&gwarea
,' ')<0){
1062 debuga(_("Invalid client IP address in file \"%s\"\n"),arq
);
1065 if (getword(code
,sizeof(code
),&gwarea
,' ')<0){
1066 debuga(_("Invalid result code in file \"%s\"\n"),arq
);
1069 if (getword(tam
,sizeof(tam
),&gwarea
,' ')<0){
1070 debuga(_("Invalid amount of data in file \"%s\"\n"),arq
);
1073 if (getword(fun
,sizeof(fun
),&gwarea
,' ')<0){
1074 debuga(_("Invalid request method in file \"%s\"\n"),arq
);
1077 if (getword_ptr(linebuf
,&full_url
,&gwarea
,' ')<0){
1078 debuga(_("Invalid url in file \"%s\"\n"),arq
);
1081 if (getword(user
,sizeof(user
),&gwarea
,' ')<0){
1082 debuga(_("Invalid user ID in file \"%s\"\n"),arq
);
1091 debuga(_("Cannot convert the timestamp from the squid log file\n"));
1095 strftime(tbuf2
, sizeof(tbuf2
), "%H%M", t
);
1097 idata
=(t
->tm_year
+1900)*10000+(t
->tm_mon
+1)*100+t
->tm_mday
;
1100 if (ilf
==ILF_Sarg
) {
1101 getword_start(&gwarea
,linebuf
);
1102 if (getword(data
,sizeof(data
),&gwarea
,'\t')<0){
1103 debuga(_("Invalid record in file \"%s\"\n"),arq
);
1106 if (getword(hora
,sizeof(hora
),&gwarea
,'\t')<0) {
1107 debuga(_("Invalid record in file \"%s\"\n"),arq
);
1110 if (getword(user
,sizeof(user
),&gwarea
,'\t')<0) {
1111 debuga(_("Invalid record in file \"%s\"\n"),arq
);
1114 if (getword(ip
,sizeof(ip
),&gwarea
,'\t')<0) {
1115 debuga(_("Invalid record in file \"%s\"\n"),arq
);
1118 if (getword_ptr(linebuf
,&full_url
,&gwarea
,'\t')<0){
1119 debuga(_("Invalid record in file \"%s\"\n"),arq
);
1122 if (getword(tam
,sizeof(tam
),&gwarea
,'\t')<0){
1123 debuga(_("Invalid record in file \"%s\"\n"),arq
);
1126 if (getword(code
,sizeof(code
),&gwarea
,'\t')<0){
1127 debuga(_("Invalid record in file \"%s\"\n"),arq
);
1130 if (getword(elap
,sizeof(elap
),&gwarea
,'\t')<0){
1131 debuga(_("Invalid record in file \"%s\"\n"),arq
);
1134 if (getword(smartfilter
,sizeof(smartfilter
),&gwarea
,'\0')<0){
1135 debuga(_("Invalid record in file \"%s\"\n"),arq
);
1138 getword_start(&gwarea
,data
);
1139 if (getword_atoll(&iday
,&gwarea
,'/')<0 || iday
<1 || iday
>31){
1140 debuga(_("Invalid record in file \"%s\"\n"),arq
);
1143 if (getword_atoll(&imonth
,&gwarea
,'/')<0 || imonth
<1 || imonth
>12){
1144 debuga(_("Invalid record in file \"%s\"\n"),arq
);
1147 if (getword_atoll(&iyear
,&gwarea
,'\0')<0){
1148 debuga(_("Invalid record in file \"%s\"\n"),arq
);
1151 idata
=builddia(iday
,imonth
,iyear
);
1152 computedate(iyear
,imonth
,iday
,&tt
);
1153 if (sscanf(hora
,"%d:%d:%d",&tt
.tm_hour
,&tt
.tm_min
,&tt
.tm_sec
)!=3 || tt
.tm_hour
<0 || tt
.tm_hour
>=24 ||
1154 tt
.tm_min
<0 || tt
.tm_min
>=60 || tt
.tm_sec
<0 || tt
.tm_sec
>=60) {
1155 debuga(_("Invalid time in file \"%s\"\n"),arq
);
1161 if (linebuf
[0] == '#') {
1162 int ncols
,cols
[ISACOL_Last
];
1164 fixendofline(linebuf
);
1165 getword_start(&gwarea
,linebuf
);
1166 // remove the #Fields: column at the beginning of the line
1167 if (getword_skip(1000,&gwarea
,' ')<0){
1168 debuga(_("Invalid record in file \"%s\"\n"),arq
);
1171 for (ncols
=0 ; ncols
<ISACOL_Last
; ncols
++) cols
[ncols
]=-1;
1173 while(gwarea
.current
[0] != '\0') {
1174 if (getword(val1
,sizeof(val1
),&gwarea
,'\t')<0){
1175 debuga(_("Invalid record in file \"%s\"\n"),arq
);
1178 if(strcmp(val1
,"c-ip") == 0) cols
[ISACOL_Ip
]=ncols
;
1179 if(strcmp(val1
,"cs-username") == 0) cols
[ISACOL_UserName
]=ncols
;
1180 if(strcmp(val1
,"date") == 0) cols
[ISACOL_Date
]=ncols
;
1181 if(strcmp(val1
,"time") == 0) cols
[ISACOL_Time
]=ncols
;
1182 if(strcmp(val1
,"time-taken") == 0) cols
[ISACOL_TimeTaken
]=ncols
;
1183 if(strcmp(val1
,"sc-bytes") == 0) cols
[ISACOL_Bytes
]=ncols
;
1184 if(strcmp(val1
,"cs-uri") == 0) cols
[ISACOL_Uri
]=ncols
;
1185 if(strcmp(val1
,"sc-status") == 0) cols
[ISACOL_Status
]=ncols
;
1188 if (cols
[ISACOL_Ip
]>=0) {
1190 for (ncols
=0 ; ncols
<ISACOL_Last
; ncols
++)
1191 isa_cols
[ncols
]=cols
[ncols
];
1195 if (!isa_ncols
) continue;
1196 getword_start(&gwarea
,linebuf
);
1197 for (x
=0 ; x
<isa_ncols
; x
++) {
1198 if (getword_ptr(linebuf
,&str
,&gwarea
,'\t')<0) {
1199 debuga(_("Invalid record in file \"%s\"\n"),arq
);
1202 if (x
==isa_cols
[ISACOL_Ip
]) {
1203 if (strlen(str
)>=sizeof(ip
)) {
1204 debuga(_("Invalid IP address in file \"%s\"\n"),arq
);
1208 } else if (x
==isa_cols
[ISACOL_UserName
]) {
1209 if (strlen(str
)>=sizeof(user
)) {
1210 debuga(_("Invalid user ID in file \"%s\"\n"),arq
);
1214 } else if (x
==isa_cols
[ISACOL_Date
]) {
1215 if (strlen(str
)>=sizeof(data
)) {
1216 debuga(_("Invalid record in file \"%s\"\n"),arq
);
1220 } else if (x
==isa_cols
[ISACOL_Time
]) {
1221 if (strlen(str
)>=sizeof(hora
)) {
1222 debuga(_("Invalid time in file \"%s\"\n"),arq
);
1226 } else if (x
==isa_cols
[ISACOL_TimeTaken
]) {
1227 if (strlen(str
)>=sizeof(elap
)) {
1228 debuga(_("Invalid download duration in file \"%s\"\n"),arq
);
1232 } else if (x
==isa_cols
[ISACOL_Bytes
]) {
1233 if (strlen(str
)>=sizeof(tam
)) {
1234 debuga(_("Invalid download size in file \"%s\"\n"),arq
);
1238 } else if (x
==isa_cols
[ISACOL_Uri
]) {
1240 } else if (x
==isa_cols
[ISACOL_Status
]) {
1241 if (strlen(str
)>=sizeof(code
)) {
1242 debuga(_("Invalid access code in file \"%s\"\n"),arq
);
1249 if(strcmp(code
,"401") == 0 || strcmp(code
,"403") == 0 || strcmp(code
,"407") == 0) {
1250 sprintf(val1
,"DENIED/%s",code
);
1253 getword_start(&gwarea
,data
);
1254 if (getword_atoll(&iyear
,&gwarea
,'-')<0){
1255 debuga(_("Invalid year in file \"%s\"\n"),arq
);
1258 if (getword_atoll(&imonth
,&gwarea
,'-')<0){
1259 debuga(_("Invalid month in file \"%s\"\n"),arq
);
1262 if (getword_atoll(&iday
,&gwarea
,'\0')<0){
1263 debuga(_("Invalid day in file \"%s\"\n"),arq
);
1267 idata
=builddia(iday
,imonth
,iyear
);
1268 computedate(iyear
,imonth
,iday
,&tt
);
1269 if (isa_cols
[ISACOL_Time
]>=0) {
1270 if (sscanf(hora
,"%d:%d:%d",&tt
.tm_hour
,&tt
.tm_min
,&tt
.tm_sec
)!=3 || tt
.tm_hour
<0 || tt
.tm_hour
>=24 ||
1271 tt
.tm_min
<0 || tt
.tm_min
>=60 || tt
.tm_sec
<0 || tt
.tm_sec
>=60) {
1272 debuga(_("Invalid time in file \"%s\"\n"),arq
);
1279 debuga(_("Unknown input log file format\n"));
1283 strftime(dia
, sizeof(dia
), "%d/%m/%Y", t
);
1284 snprintf(hora
,sizeof(hora
),"%02d:%02d:%02d",t
->tm_hour
,t
->tm_min
,t
->tm_sec
);
1287 printf("DATE=%s IDATA=%d DFROM=%d DUNTIL=%d\n",date
,idata
,dfrom
,duntil
);
1289 if(date
[0] != '\0'){
1290 if(idata
< dfrom
|| idata
> duntil
) continue;
1293 // Record only hours usage which is required
1295 if( bsearch( &( t
-> tm_wday
), weekdays
.list
, weekdays
.len
, sizeof( int ), compar
) == NULL
)
1298 if( bsearch( &( t
-> tm_hour
), hours
.list
, hours
.len
, sizeof( int ), compar
) == NULL
)
1303 if(strlen(user
) > MAX_USER_LEN
) {
1304 if (debugm
) printf(_("User ID too long: %s\n"),user
);
1310 if(IncludeUsers
[0] != '\0') {
1311 snprintf(val1
,sizeof(val1
),":%s:",user
);
1312 if((str
=(char *) strstr(IncludeUsers
,val1
)) == (char *) NULL
)
1317 if (debugm
) printf(_("Excluded code: %s\n"),code
);
1322 if(testvaliduserchar(user
))
1326 if((str
= strstr(user
,"%20")) != NULL
) {
1328 This is a patch introduced to solve bug #1624251 reported at sourceforge but
1329 the side effect is to truncate the name at the first space and merge the reports
1330 of people whose name is identical up to the first space.
1332 The old code used to truncate the user name at the first % if a %20 was
1333 found anywhere in the string. That means the string could be truncated
1334 at the wrong place if another % occured before the %20. This new code should
1335 avoid that problem and only truncate at the space. There is no bug
1336 report indicating that anybody noticed this.
1342 Code prior to 2.2.7 used to replace any %xx by a dot as long as a %5c was
1343 found in the user name.
1345 while((str
= strstr(user
,"%5c")) != NULL
) {
1347 for (x
=3 ; str
[x
] ; x
++) str
[x
-2]=str
[x
];
1350 // replace any tab by a single space
1351 for (str
=full_url
; *str
; str
++)
1352 if (*str
=='\t') *str
=' ';
1353 for (str
=code
; *str
; str
++)
1354 if (*str
=='\t') *str
=' ';
1358 The full URL is not saved in sarg log. There is no point in testing the URL to detect
1361 download_flag
=is_download_suffix(full_url
);
1362 if (download_flag
) {
1363 safe_strcpy(download_url
,full_url
,sizeof(download_url
));
1367 download_flag
=false;
1369 url
=process_url(full_url
,LongUrl
);
1370 if (!url
|| url
[0] == '\0') continue;
1372 if(addr
[0] != '\0'){
1373 if(strcmp(addr
,ip
)!=0) continue;
1376 if(!vhexclude(url
)) {
1377 if (debugm
) printf(_("Excluded site: %s\n"),url
);
1383 if(hm
>= 0 && hmf
>= 0) {
1384 hmr
=t
->tm_hour
*100+t
->tm_min
;
1385 if(hmr
< hm
|| hmr
> hmf
) continue;
1388 if(site
[0] != '\0'){
1389 if(strstr(url
,site
)==0) continue;
1397 if(strcmp(user
,"-") == 0 || strcmp(user
," ") == 0 || strcmp(user
,"") == 0) {
1398 if(RecordsWithoutUser
== RECORDWITHOUTUSER_IP
) {
1402 if(RecordsWithoutUser
== RECORDWITHOUTUSER_IGNORE
)
1404 if(RecordsWithoutUser
== RECORDWITHOUTUSER_EVERYBODY
)
1405 strcpy(user
,"everybody");
1408 if(NtlmUserFormat
== NTLMUSERFORMAT_USER
) {
1409 if ((str
=strchr(user
,'+'))!=NULL
|| (str
=strchr(user
,'\\'))!=NULL
|| (str
=strchr(user
,'_'))!=NULL
) {
1410 strcpy(warea
,str
+1);
1418 if(strcmp(user
,us
)!=0) continue;
1422 snprintf(wuser
,sizeof(wuser
),":%s:",user
);
1423 if(strstr(userfile
, wuser
) == 0)
1428 if(!vuexclude(user
)) {
1429 if (debugm
) printf(_("Excluded user: %s\n"),user
);
1435 if(strcmp(user
,"-") ==0 || strcmp(user
," ") ==0 || strcmp(user
,"") ==0 || strcmp(user
,":") ==0)
1439 if (nbytes
<0) nbytes
=0;
1441 elap_time
=atol(elap
);
1442 if (elap_time
<0) elap_time
=0;
1444 if(elap_time
>max_elapsed
) {
1449 if((str
=(char *) strstr(linebuf
, "[SmartFilter:")) != (char *) NULL
) {
1451 snprintf(smartfilter
,sizeof(smartfilter
),"\"%s\"",str
+1);
1452 } else strcpy(smartfilter
,"\"\"");
1456 for (ufile
=first_user_file
; ufile
&& strcmp(user
,ufile
->user
->id
)!=0 ; ufile
=ufile
->next
) {
1458 if (ufile
->file
) nopen
++;
1461 ufile
=malloc(sizeof(*ufile
));
1463 debuga(_("Not enough memory to store user %s\n"),user
);
1466 memset(ufile
,0,sizeof(*ufile
));
1467 ufile
->next
=first_user_file
;
1468 first_user_file
=ufile
;
1469 uinfo
=userinfo_create(user
,ip
);
1471 uinfo
->id_is_ip
=id_is_ip
;
1475 prev_ufile
->next
=ufile
->next
;
1476 ufile
->next
=first_user_file
;
1477 first_user_file
=ufile
;
1480 #ifdef ENABLE_DOUBLE_CHECK_DATA
1481 ufile
->user
->nbytes
+=nbytes
;
1482 ufile
->user
->elap
+=elap_time
;
1485 if (ufile
->file
==NULL
) {
1486 if (nopen
>=maxopenfiles
) {
1488 for (ufile1
=first_user_file
; ufile1
; ufile1
=ufile1
->next
) {
1489 if (ufile1
->file
!=NULL
) {
1490 if (x
>=maxopenfiles
) {
1491 if (fclose(ufile1
->file
)==EOF
) {
1492 debuga(_("Failed to close file \"%s\": %s\n"),ufile1
->user
->id
,strerror(errno
));
1501 if (snprintf (tmp3
, sizeof(tmp3
), "%s/%s.user_unsort", tmp
, ufile
->user
->filename
)>=sizeof(tmp3
)) {
1502 debuga(_("Path too long: "));
1503 debuga_more("%s/%s.user_unsort\n", tmp
, ufile
->user
->filename
);
1506 if ((ufile
->file
= MY_FOPEN (tmp3
, "a")) == NULL
) {
1507 debugapos("log",_("Cannot open file \"%s\": %s\n"), tmp3
, strerror(errno
));
1512 if (fprintf(ufile
->file
, "%s\t%s\t%s\t%s\t%"PRIi64
"\t%s\t%ld\t%s\n",dia
,hora
,ip
,url
,(int64_t)nbytes
,code
,elap_time
,smartfilter
)<=0) {
1513 debuga(_("Write error in the log file of user %s\n"),user
);
1518 if(fp_log
&& ilf
!=ILF_Sarg
)
1519 fprintf(fp_log
, "%s\t%s\t%s\t%s\t%s\t%"PRIi64
"\t%s\t%ld\t%s\n",dia
,hora
,user
,ip
,url
,(int64_t)nbytes
,code
,elap_time
,smartfilter
);
1523 if(!dataonly
&& download_flag
&& strstr(code
,"DENIED") == 0) {
1526 if ( ! fp_Download_Unsort
) {
1527 if ((fp_Download_Unsort
= MY_FOPEN ( sz_Download_Unsort
, "a")) == NULL
) {
1528 debugapos("log",_("Cannot open file \"%s\": %s\n"),sz_Download_Unsort
, strerror(errno
));
1532 fprintf(fp_Download_Unsort
,"%s\t%s\t%s\t%s\t%s\n",dia
,hora
,user
,ip
,download_url
);
1535 if((ReportType
& REPORT_TYPE_DENIED
) != 0) {
1536 if(fp_denied
&& strstr(code
,"DENIED/403") != 0) {
1537 fprintf(fp_denied
, "%s\t%s\t%s\t%s\t%s\n",dia
,hora
,user
,ip
,full_url
);
1541 if((ReportType
& REPORT_TYPE_AUTH_FAILURES
) != 0) {
1542 if(fp_authfail
&& (strstr(code
,"DENIED/401") != 0 || strstr(code
,"DENIED/407") != 0)) {
1543 fprintf(fp_authfail
, "%s\t%s\t%s\t%s\t%s\n",dia
,hora
,user
,ip
,full_url
);
1548 if (ilf
!=ILF_Sarg
) {
1549 if(!totper
|| idata
<mindate
){
1551 memcpy(&period
.start
,t
,sizeof(*t
));
1552 strcpy(start_hour
,tbuf2
);
1554 if (!totper
|| idata
>maxdate
) {
1556 memcpy(&period
.end
,t
,sizeof(*t
));
1562 printf("IP=\t%s\n",ip
);
1563 printf("USER=\t%s\n",user
);
1564 printf("ELAP=\t%ld\n",elap_time
);
1565 printf("DATE=\t%s\n",dia
);
1566 printf("TIME=\t%s\n",hora
);
1567 printf("FUNC=\t%s\n",fun
);
1568 printf("URL=\t%s\n",url
);
1569 printf("CODE=\t%s\n",code
);
1570 printf("LEN=\t%"PRIi64
"\n",(int64_t)nbytes
);
1578 if( ShowReadStatistics
) {
1579 printf(_("SARG: Records in file: %lu, reading: %3.2lf%%"),recs1
,100.);
1585 read_end_time
=time(NULL
);
1586 read_elapsed
=(double)read_end_time
-(double)read_start_time
;
1589 debuga(_(" Records read: %ld, written: %ld, excluded: %ld\n"),totregsl
,totregsg
,totregsx
);
1591 longline_destroy(&line
);
1592 if ( fp_Download_Unsort
)
1593 fclose (fp_Download_Unsort
);
1595 for (ufile
=first_user_file
; ufile
; ufile
=ufile1
) {
1597 if (ufile
->file
!=NULL
) fclose(ufile
->file
);
1602 free_excludecodes();
1608 for (ilf
=0 ; ilf
<ILF_Last
; ilf
++) totalcount
+=ilf_count
[ilf
];
1610 if(ilf_count
[ILF_Common
]>0 && ilf_count
[ILF_Squid
]>0)
1611 debuga(_("Log with mixed records format (squid and common log)\n"));
1613 if(ilf_count
[ILF_Common
]>0 && ilf_count
[ILF_Squid
]==0)
1614 debuga(_("Common log format\n"));
1616 if(ilf_count
[ILF_Common
]==0 && ilf_count
[ILF_Squid
]>0)
1617 debuga(_("Squid log format\n"));
1619 if(ilf_count
[ILF_Sarg
]>0)
1620 debuga(_("Sarg log format\n"));
1622 if(totalcount
==0 && totregsg
)
1623 debuga(_("Log with invalid format\n"));
1627 debuga(_("No records found\n"));
1629 if(fp_denied
) fclose(fp_denied
);
1630 if(fp_authfail
) fclose(fp_authfail
);
1632 if(userfile
) free(userfile
);
1637 if (date
[0]!='\0') {
1638 char date0
[30], date1
[30];
1640 strftime(date0
,sizeof(date0
),"%d/%m/%Y",&period
.start
);
1641 strftime(date1
,sizeof(date1
),"%d/%m/%Y",&period
.end
);
1642 debuga(_("Period covered by log files: %s-%s\n"),date0
,date1
);
1643 getperiod_fromrange(&period
,dfrom
,duntil
);
1645 if (getperiod_buildtext(&period
)<0) {
1646 debuga(_("Failed to build the string representation of the date range\n"));
1651 debugaz(_("date=%s\n"),dia
);
1652 debugaz(_("period=%s\n"),period
.text
);
1656 debuga(_("Period: %s"),period
.text
);
1663 fclose(fp_authfail
);
1665 if(fp_log
!= NULL
) {
1668 char val4
[255];//val4 must not be bigger than arq_log without fixing the strcpy below
1671 safe_strcpy(end_hour
,tbuf2
,sizeof(end_hour
));
1672 strftime(val2
,sizeof(val2
),"%d%m%Y",&period
.start
);
1673 strftime(val1
,sizeof(val1
),"%d%m%Y",&period
.end
);
1674 if (snprintf(val4
,sizeof(val4
),"%s/sarg-%s_%s-%s_%s.log",ParsedOutputLog
,val2
,start_hour
,val1
,end_hour
)>=sizeof(val4
)) {
1675 debuga(_("Path too long: "));
1676 debuga_more("%s/sarg-%s_%s-%s_%s.log\n",ParsedOutputLog
,val2
,start_hour
,val1
,end_hour
);
1679 if (rename(arq_log
,val4
)) {
1680 debuga(_("Failed to rename \"%s\" into \"%s\": %s\n"),arq_log
,val4
,strerror(errno
));
1682 strcpy(arq_log
,val4
);
1684 if(strcmp(ParsedOutputLogCompress
,"nocompress") != 0 && ParsedOutputLogCompress
[0] != '\0') {
1686 No double quotes around ParsedOutputLogCompress because it may contain command line options. If double quotes are
1687 necessary around the command name, put them in the configuration file.
1689 if (snprintf(val1
,sizeof(val1
),"%s \"%s\"",ParsedOutputLogCompress
,arq_log
)>=sizeof(val1
)) {
1690 /* TRANSLATORS: The message is followed by the command that's too long. */
1691 debuga(_("Command too long: "));
1692 debuga_more("%s \"%s\"\n",ParsedOutputLogCompress
,arq_log
);
1695 cstatus
=system(val1
);
1696 if (!WIFEXITED(cstatus
) || WEXITSTATUS(cstatus
)) {
1697 debuga(_("command return status %d\n"),WEXITSTATUS(cstatus
));
1698 debuga(_("command: %s\n"),val1
);
1704 debuga(_("Sarg parsed log saved as %s\n"),arq_log
);
1707 if(DataFile
[0] == '\0' && (ReportType
& REPORT_TYPE_DENIED
) != 0) {
1708 if (snprintf(csort
,sizeof(csort
),"sort -T \"%s\" -t \"\t\" -k 3,3 -k 5,5 -o \"%s\" \"%s\"",tmp
,denied_sort
,denied_unsort
)>=sizeof(csort
)) {
1709 debuga(_("Command too long: "));
1710 debuga_more("sort -T \"%s\" -t \"\t\" -k 3,3 -k 5,5 -o \"%s\" \"%s\"",tmp
,denied_sort
,denied_unsort
);
1713 cstatus
=system(csort
);
1714 if (!WIFEXITED(cstatus
) || WEXITSTATUS(cstatus
)) {
1715 debuga(_("sort command return status %d\n"),WEXITSTATUS(cstatus
));
1716 debuga(_("sort command: %s\n"),csort
);
1719 if (!KeepTempLog
&& unlink(denied_unsort
)) {
1720 debuga(_("Cannot delete \"%s\": %s\n"),denied_unsort
,strerror(errno
));
1725 process_start_time
=time(NULL
);
1726 if(DataFile
[0] != '\0')
1730 process_end_time
=time(NULL
);
1731 process_elapsed
=(double)process_end_time
-(double)process_start_time
;
1733 if((ReportType
& REPORT_TYPE_DENIED
) != 0) {
1734 if (!KeepTempLog
&& unlink(denied_sort
) && errno
!=ENOENT
)
1735 debuga(_("Cannot delete \"%s\": %s\n"),denied_sort
,strerror(errno
));
1738 if(!KeepTempLog
&& strcmp(tmp
,"/tmp") != 0) {
1749 end_time
=time(NULL
);
1752 double elapsed
=(double)end_time
-(double)start_time
;
1753 debuga(_("Total execution time: %.0lf seconds\n"),elapsed
);
1754 if (read_elapsed
>0.) {
1755 debuga(_("Lines read: %lu lines in %.0lf seconds (%.0lf lines/s)\n"),lines_read
,read_elapsed
,(double)lines_read
/read_elapsed
);
1757 if (process_elapsed
>0.) {
1758 debuga(_("Processed records: %lu records in %.0lf seconds (%.0lf records/s)\n"),records_kept
,process_elapsed
,(double)records_kept
/process_elapsed
);
1759 debuga(_("Users: %lu users in %.0lf seconds (%.0lf users/s)\n"),nusers
,process_elapsed
,(double)nusers
/process_elapsed
);
1770 static void getusers(const char *pwdfile
, int debug
)
1778 debuga(_("Loading password file from %s\n"),pwdfile
);
1780 if ((fp_usr
= fopen(pwdfile
, "r")) == NULL
) {
1781 debugapos("getusers",_("Cannot open file \"%s\": %s\n"),pwdfile
,strerror(errno
));
1785 if (fseek(fp_usr
, 0, SEEK_END
)==-1) {
1786 debuga(_("Failed to move till the end of file \"%s\": %s\n"),pwdfile
,strerror(errno
));
1789 nreg
= ftell(fp_usr
);
1791 debuga(_("Cannot get the size of file \"%s\": %s\n"),pwdfile
,strerror(errno
));
1795 if (fseek(fp_usr
, 0, SEEK_SET
)==-1) {
1796 debuga(_("Failed to rewind file \"%s\": %s\n"),pwdfile
,strerror(errno
));
1800 if((userfile
=(char *) malloc(nreg
))==NULL
){
1801 debuga(_("malloc failed to allocate %ld bytes\n"),nreg
);
1805 bzero(userfile
,nreg
);
1806 strcpy(userfile
,":");
1808 while(fgets(buf
,sizeof(buf
),fp_usr
)!=NULL
) {
1809 str
=strchr(buf
,':');
1811 debuga(_("Invalid user in file \"%s\"\n"),pwdfile
);
1815 strcat(userfile
,buf
);