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 static void getusers(const char *pwdfile
, int debug
);
51 int main(int argc
,char *argv
[])
62 ISACOL_Last
//last entry of the list !
70 ILF_Last
//last entry of the list !
73 FILE *fp_in
= NULL
, *fp_denied
=NULL
, *fp_authfail
=NULL
, *fp_log
=NULL
;
75 char sz_Download_Unsort
[ 20000 ] ;
76 FILE * fp_Download_Unsort
= NULL
;
88 char smartfilter
[MAXLEN
];
98 char hexclude
[MAXLEN
];
104 char denied_unsort
[MAXLEN
];
105 char denied_sort
[MAXLEN
];
106 char authfail_unsort
[MAXLEN
];
107 char start_hour
[128];
111 char user
[MAX_USER_LEN
];
112 char splitprefix
[MAXLEN
];
113 enum InputLogFormat ilf
;
114 int ilf_count
[ILF_Last
];
126 int isa_ncols
=0,isa_cols
[ISACOL_Last
];
140 long int max_elapsed
=0;
141 long long int iyear
, imonth
, iday
;
146 unsigned long recs1
=0UL;
147 unsigned long recs2
=0UL;
148 int OutputNonZero
= REPORT_EVERY_X_LINES
;
149 bool download_flag
=false;
150 char download_url
[MAXLEN
];
151 struct getwordstruct gwarea
;
155 struct userinfostruct
*uinfo
;
156 struct userfilestruct
*first_user_file
, *ufile
, *ufile1
, *prev_ufile
;
158 static int convert
=0;
159 static int output_css
=0;
161 static struct option long_options
[]=
163 {"convert",no_argument
,&convert
,1},
164 {"css",no_argument
,&output_css
,1},
165 {"help",no_argument
,NULL
,'h'},
166 {"lastlog",required_argument
,NULL
,2},
167 {"keeplogs",no_argument
,NULL
,3},
168 {"split",no_argument
,&split
,1},
169 {"splitprefix",required_argument
,NULL
,'P'},
174 setlocale(LC_TIME
,"");
177 #if defined(ENABLE_NLS) && defined(HAVE_LOCALE_H)
178 if (!setlocale (LC_ALL
, "")) {
179 fprintf(stderr
,"SARG: Cannot set the locale LC_ALL to the environment variable\n");
182 if (!bindtextdomain (PACKAGE_NAME
, LOCALEDIR
)) {
183 fprintf(stderr
,"SARG: Cannot bind to text domain %s in directory %s (%s)\n",PACKAGE_NAME
,LOCALEDIR
,strerror(errno
));
186 if (!textdomain (PACKAGE_NAME
)) {
187 fprintf(stderr
,"SARG: Cannot set gettext domain for %s PACKAGE_NAME (%s)\n",PACKAGE_NAME
,strerror(errno
));
197 UserAgentLog
[0]='\0';
198 ExcludeHosts
[0]='\0';
199 ExcludeUsers
[0]='\0';
206 ExternalCSSFile
[0]='\0';
207 RedirectorLogFormat
[0]='\0';
209 for (ilf
=0 ; ilf
<ILF_Last
; ilf
++) ilf_count
[ilf
]=0;
211 snprintf(ExcludeCodes
,sizeof(ExcludeCodes
),"%s/exclude_codes",SYSCONFDIR
);
212 strcpy(GraphDaysBytesBarColor
,"orange");
213 strcpy(BgColor
,"#ffffff");
214 strcpy(TxColor
,"#000000");
215 strcpy(TxBgColor
,"lavender");
216 strcpy(TiColor
,"darkblue");
219 strcpy(LogoTextColor
,"#000000");
220 strcpy(HeaderColor
,"darkblue");
221 strcpy(HeaderBgColor
,"#dddddd");
222 strcpy(LogoTextColor
,"#006699");
223 strcpy(FontSize
,"9px");
224 strcpy(TempDir
,"/tmp");
225 strcpy(OutputDir
,"/var/www/html/squid-reports");
226 AnonymousOutputFiles
=false;
228 strcpy(DateFormat
,"u");
229 OverwriteReport
=false;
230 RemoveTempFiles
=true;
231 strcpy(ReplaceIndex
,"index.html");
233 RecordsWithoutUser
=RECORDWITHOUTUSER_IP
;
235 strcpy(MailUtility
,"mailx");
239 TopuserSort
=TOPUSER_SORT_BYTES
| TOPUSER_SORT_REVERSE
;
240 UserSort
=USER_SORT_BYTES
| USER_SORT_REVERSE
;
241 TopsitesSort
=TOPSITE_SORT_CONNECT
| TOPSITE_SORT_REVERSE
;
243 strcpy(FontFace
,"Verdana,Tahoma,Arial");
244 datetimeby
=DATETIME_BYTE
;
245 strcpy(CharSet
,"ISO-8859-1");
247 strcpy(PrivacyString
,"***.***.***.***");
248 strcpy(PrivacyStringColor
,"blue");
250 TopUserFields
=TOPUSERFIELDS_NUM
| TOPUSERFIELDS_DATE_TIME
| TOPUSERFIELDS_USERID
| TOPUSERFIELDS_CONNECT
|
251 TOPUSERFIELDS_BYTES
| TOPUSERFIELDS_SETYB
| TOPUSERFIELDS_IN_CACHE_OUT
|
252 TOPUSERFIELDS_USED_TIME
| TOPUSERFIELDS_MILISEC
| TOPUSERFIELDS_PTIME
|
253 TOPUSERFIELDS_TOTAL
| TOPUSERFIELDS_AVERAGE
;
254 UserReportFields
=USERREPORTFIELDS_CONNECT
| USERREPORTFIELDS_BYTES
| USERREPORTFIELDS_SETYB
|
255 USERREPORTFIELDS_IN_CACHE_OUT
| USERREPORTFIELDS_USED_TIME
| USERREPORTFIELDS_MILISEC
|
256 USERREPORTFIELDS_PTIME
| USERREPORTFIELDS_TOTAL
| USERREPORTFIELDS_AVERAGE
;
257 strcpy(DataFileDelimiter
,";");
258 DataFileFields
=DATA_FIELD_USER
| DATA_FIELD_DATE
| DATA_FIELD_TIME
| DATA_FIELD_URL
| DATA_FIELD_CONNECT
|
259 DATA_FIELD_BYTES
| DATA_FIELD_IN_CACHE
| DATA_FIELD_OUT_CACHE
| DATA_FIELD_ELAPSED
;
260 ShowReadStatistics
=true;
261 strcpy(IndexSortOrder
,"D");
264 ParsedOutputLog
[0]='\0';
265 strcpy(ParsedOutputLogCompress
,"/bin/gzip -f");
266 DisplayedValues
=DISPLAY_ABBREV
;
267 strcpy(HeaderFontSize
,"9px");
268 strcpy(TitleFontSize
,"11px");
269 strcpy(AuthUserTemplateFile
,"sarg_htaccess");
270 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");
273 strcpy(GraphFont
,FONTDIR
"/DejaVuSans.ttf");
277 strcpy(Ulimit
,"20000");
278 NtlmUserFormat
=NTLMUSERFORMAT_DOMAINUSER
;
279 IndexTree
=INDEX_TREE_FILE
;
280 IndexFields
=INDEXFIELDS_DIRSIZE
;
281 strcpy(RealtimeTypes
,"GET,PUT,CONNECT");
282 RealtimeUnauthRec
=REALTIME_UNAUTH_REC_SHOW
;
283 RedirectorFilterOutDate
=true;
284 DansguardianFilterOutDate
=true;
285 DataFileUrl
=DATAFILEURL_IP
;
286 strcpy(MaxElapsed
,"28800000");
287 BytesInSitesUsersReport
=0;
288 UserAuthentication
=0;
289 strcpy(LDAPHost
,"127.0.0.1");
291 LDAPProtocolVersion
=3;
294 LDAPBaseSearch
[0]='\0';
295 strcpy(LDAPFilterSearch
, "(uid=%s)");
296 strcpy(LDAPTargetAttr
, "cn");
317 UserInvalidChar
[0]='\0';
319 SquidGuardConf
[0]='\0';
320 DansGuardianConf
[0]='\0';
323 HostAliasFile
[0]='\0';
328 dansguardian_count
=0;
331 DeniedReportLimit
=10;
332 AuthfailReportLimit
=10;
333 DansGuardianReportLimit
=10;
334 SquidGuardReportLimit
=10;
335 DownloadReportLimit
=50;
344 realtime_access_log_lines
=1000;
353 bzero(IncludeUsers
, sizeof(IncludeUsers
));
354 bzero(ExcludeString
, sizeof(ExcludeString
));
355 first_user_file
=NULL
;
356 memset(&period
,0,sizeof(period
));
359 for(x
=0; x
<MAXLOGS
; x
++)
360 AccessLog
[x
][0]='\0';
361 AccessLogFromCmdLine
=0;
362 RedirectorLogFromCmdLine
=0;
364 strcpy(Title
,_("Squid User Access Report"));
366 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){
372 lastlog
=atoi(optarg
);
378 safe_strcpy(addr
,optarg
,sizeof(addr
));
380 case 'b': //unused option
381 safe_strcpy(uagent
,optarg
,sizeof(uagent
));
384 safe_strcpy(hexclude
,optarg
,sizeof(hexclude
));
387 safe_strcpy(date
,optarg
,sizeof(date
));
388 date_from(date
, &dfrom
, &duntil
);
391 safe_strcpy(email
,optarg
,sizeof(email
));
394 safe_strcpy(ConfigFile
,optarg
,sizeof(ConfigFile
));
397 safe_strcpy(df
,optarg
,sizeof(df
));
409 if (NAccessLog
>=MAXLOGS
) {
410 debuga(_("Too many log files passed on command line with option -l.\n"));
413 if (strlen(optarg
)>=MAX_LOG_FILELEN
) {
414 debuga(_("Log file name too long passed on command line with option -l: %s\n"),optarg
);
417 strcpy(AccessLog
[NAccessLog
],optarg
);
419 AccessLogFromCmdLine
++;
422 if (NRedirectorLogs
>MAX_REDIRECTOR_LOGS
) {
423 debuga(_("Too many redirector logs passed on command line with option -L.\n"));
426 if (strlen(optarg
)>=MAX_REDIRECTOR_FILELEN
) {
427 debuga(_("Redirector log file name too long passed on command line with opton -L: %s\n"),optarg
);
430 strcpy(RedirectorLogs
[NRedirectorLogs
],optarg
);
432 RedirectorLogFromCmdLine
++;
441 safe_strcpy(outdir
,optarg
,sizeof(outdir
));
447 safe_strcpy(splitprefix
,optarg
,sizeof(splitprefix
));
453 safe_strcpy(site
,optarg
,sizeof(site
));
459 if(strstr(optarg
,"-") == 0) {
460 if(sscanf(optarg
,"%d:%d",&h1
,&m1
)!=2) {
461 debuga(_("Time period passed on the command line with option -t must be MM:SS\n"));
466 snprintf(hm_str
,sizeof(hm_str
),"%02d:%02d",h1
,m1
);
468 if(sscanf(optarg
,"%d:%d-%d:%d",&h1
,&m1
,&h2
,&m2
)!=4) {
469 debuga(_("Time range passed on the command line with option -t must be MM:SS-MM:SS\n"));
474 snprintf(hm_str
,sizeof(hm_str
),"%02d:%02d-%02d:%02d",h1
,m1
,h2
,m2
);
479 safe_strcpy(us
,optarg
,sizeof(us
));
485 safe_strcpy(tmp
,optarg
,sizeof(tmp
));
490 case 'y': //unused option
497 debuga(_("Option -%c requires an argument\n"),optopt
);
513 for (iarq
=optind
; iarq
<argc
; iarq
++) {
514 if (NAccessLog
>=MAXLOGS
) {
515 debuga(_("Too many log files passed on command line.\n"));
518 if (strlen(argv
[iarq
])>=MAX_LOG_FILELEN
) {
519 debuga(_("Log file name too long passed on command line: %s\n"),argv
[iarq
]);
522 strcpy(AccessLog
[NAccessLog
],argv
[iarq
]);
524 AccessLogFromCmdLine
++;
528 if(debug
) debuga(_("Init\n"));
530 if(ConfigFile
[0] == '\0') snprintf(ConfigFile
,sizeof(ConfigFile
),"%s/sarg.conf",SYSCONFDIR
);
531 if(access(ConfigFile
, R_OK
) != 0) {
532 debuga(_("Cannot open config file: %s - %s\n"),ConfigFile
,strerror(errno
));
536 if(access(ConfigFile
, R_OK
) == 0)
539 if(userip
) UserIp
=true;
541 if(dns
) ip2name_forcedns();
543 if (lastlog
>=0) LastLog
=lastlog
;
545 if(outdir
[0] == '\0') strcpy(outdir
,OutputDir
);
546 if(outdir
[0] != '\0') strcat(outdir
,"/");
553 if(IndexTree
== INDEX_TREE_FILE
)
554 strcpy(ImageFile
,"../images");
556 strcpy(ImageFile
,"../../../images");
559 if(DataFile
[0] != '\0')
562 if(df
[0] == '\0') strcpy(df
,DateFormat
);
563 else strcpy(DateFormat
,df
);
567 strcpy(DateFormat
,"u");
570 IndexTree
=INDEX_TREE_FILE
;
572 if(NAccessLog
== 0) {
573 strcpy(AccessLog
[0],"/var/log/squid/access.log");
582 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++)
583 splitlog(AccessLog
[iarq
], df
, dfrom
, duntil
, convert
, splitprefix
);
587 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++)
588 convlog(AccessLog
[iarq
], df
, dfrom
, duntil
);
592 load_excludecodes(ExcludeCodes
);
594 if(access(PasswdFile
, R_OK
) == 0) {
595 getusers(PasswdFile
,debug
);
599 if(hexclude
[0] == '\0')
600 strcpy(hexclude
,ExcludeHosts
);
601 if(hexclude
[0] != '\0') {
602 gethexclude(hexclude
,debug
);
606 if(ReportType
== 0) {
607 ReportType
=REPORT_TYPE_TOPUSERS
| REPORT_TYPE_TOPSITES
| REPORT_TYPE_USERS_SITES
|
608 REPORT_TYPE_SITES_USERS
| REPORT_TYPE_DATE_TIME
| REPORT_TYPE_DENIED
|
609 REPORT_TYPE_AUTH_FAILURES
| REPORT_TYPE_SITE_USER_TIME_DATE
| REPORT_TYPE_DOWNLOADS
;
612 if(access(ExcludeUsers
, R_OK
) == 0) {
613 getuexclude(ExcludeUsers
,debug
);
616 if (HostAliasFile
[0] != '\0')
617 read_hostalias(HostAliasFile
);
624 if(strcmp(ExcludeUsers
,"indexonly") == 0) indexonly
=true;
625 if(Index
== INDEX_ONLY
) indexonly
=true;
627 if(MaxElapsed
[0] != '\0') max_elapsed
=atol(MaxElapsed
);
629 if(uagent
[0] == '\0') strcpy(uagent
,UserAgentLog
);
631 if(tmp
[0] == '\0') strcpy(tmp
,TempDir
);
632 else strcpy(TempDir
,tmp
);
634 For historical reasons, the temporary directory is the subdirectory "sarg" of the path
635 provided by the user.
639 if (tmp
[0]!='\0' && strncmp(outdir
,tmp
,strlen(tmp
))==0) {
640 debuga(_("The output directory \"%s\" must be outside of the temporary directory \"%s\"\n"),outdir
,tmp
);
644 if(email
[0] == '\0' && OutputEmail
[0] != '\0') strcpy(email
,OutputEmail
);
646 if(email
[0] != '\0') {
652 if(access(tmp
, R_OK
) == 0) {
653 if (debug
) debuga(_("Deleting temporary directory \"%s\"\n"),tmp
);
657 snprintf(denied_unsort
,sizeof(denied_unsort
),"%s/denied.int_unsort",tmp
);
658 snprintf(denied_sort
,sizeof(denied_sort
),"%s/denied.int_log",tmp
);
659 snprintf(authfail_unsort
,sizeof(authfail_unsort
),"%s/authfail.int_unsort",tmp
);
662 debuga(_("Parameters:\n"));
663 debuga(_(" Hostname or IP address (-a) = %s\n"),addr
);
664 debuga(_(" Useragent log (-b) = %s\n"),uagent
);
665 debuga(_(" Exclude file (-c) = %s\n"),hexclude
);
666 debuga(_(" Date from-until (-d) = %s\n"),date
);
667 debuga(_(" Email address to send reports (-e) = %s\n"),email
);
668 debuga(_(" Config file (-f) = %s\n"),ConfigFile
);
669 if(strcmp(df
,"e") == 0)
670 debuga(_(" Date format (-g) = Europe (dd/mm/yyyy)\n"));
671 if(strcmp(df
,"u") == 0)
672 debuga(_(" Date format (-g) = USA (mm/dd/yyyy)\n"));
673 if(strcmp(df
,"w") == 0)
674 debuga(_(" Date format (-g) = Sites & Users (yyyy/ww)\n"));
675 debuga(_(" IP report (-i) = %s\n"),(iprel
) ? _("Yes") : _("No"));
676 debuga(_(" Keep temporary files (-k) = %s\n"),(KeepTempLog
) ? _("Yes") : _("No"));
677 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++)
678 debuga(_(" Input log (-l) = %s\n"),AccessLog
[iarq
]);
679 for (iarq
=0 ; iarq
<NRedirectorLogs
; iarq
++)
680 debuga(_(" Redirector log (-L) = %s\n"),RedirectorLogs
[iarq
]);
681 debuga(_(" Resolve IP Address (-n) = %s\n"),(Ip2Name
) ? _("Yes") : _("No"));
682 debuga(_(" Output dir (-o) = %s\n"),outdir
);
683 debuga(_("Use Ip Address instead of userid (-p) = %s\n"),(UserIp
) ? _("Yes") : _("No"));
684 debuga(_(" Accessed site (-s) = %s\n"),site
);
685 debuga(_(" Time (-t) = %s\n"),hm_str
);
686 debuga(_(" User (-u) = %s\n"),us
);
687 debuga(_(" Temporary dir (-w) = %s\n"),tmp
);
688 debuga(_(" Debug messages (-x) = %s\n"),(debug
) ? _("Yes") : _("No"));
689 debuga(_(" Process messages (-z) = %s\n"),(debugz
) ? _("Yes") : _("No"));
690 debuga(_(" Previous reports to keep (--lastlog) = %d\n"),LastLog
);
695 printf(_("Parameters:\n"));
696 printf(_(" Hostname or IP address (-a) = %s\n"),addr
);
697 printf(_(" Useragent log (-b) = %s\n"),uagent
);
698 printf(_(" Exclude file (-c) = %s\n"),hexclude
);
699 printf(_(" Date from-until (-d) = %s\n"),date
);
700 printf(_(" Email address to send reports (-e) = %s\n"),email
);
701 printf(_(" Config file (-f) = %s\n"),ConfigFile
);
702 if(strcmp(df
,"e") == 0)
703 printf(_(" Date format (-g) = Europe (dd/mm/yyyy)\n"));
704 if(strcmp(df
,"u") == 0)
705 printf(_(" Date format (-g) = USA (mm/dd/yyyy)\n"));
706 if(strcmp(df
,"w") == 0)
707 printf(_(" Date format (-g) = Sites & Users (yyyy/ww)\n"));
708 printf(_(" IP report (-i) = %s\n"),(iprel
) ? _("Yes") : _("No"));
709 printf(_(" Keep temporary files (-k) = %s\n"),(KeepTempLog
) ? _("Yes") : _("No"));
710 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++)
711 printf(_(" Input log (-l) = %s\n"),AccessLog
[iarq
]);
712 for (iarq
=0 ; iarq
<NRedirectorLogs
; iarq
++)
713 printf(_(" Redirector log (-L) = %s\n"),RedirectorLogs
[iarq
]);
714 printf(_(" Resolve IP Address (-n) = %s\n"),(Ip2Name
) ? _("Yes") : _("No"));
715 printf(_(" Output dir (-o) = %s\n"),outdir
);
716 printf(_("Use Ip Address instead of userid (-p) = %s\n"),(UserIp
) ? _("Yes") : _("No"));
717 printf(_(" Accessed site (-s) = %s\n"),site
);
718 printf(_(" Time (-t) = %s\n"),hm_str
);
719 printf(_(" User (-u) = %s\n"),us
);
720 printf(_(" Temporary dir (-w) = %s\n"),tmp
);
721 printf(_(" Debug messages (-x) = %s\n"),(debug
) ? _("Yes") : _("No"));
722 printf(_(" Process messages (-z) = %s\n"),(debugz
) ? _("Yes") : _("No"));
723 printf(_(" Previous reports to keep (--lastlog) = %d\n"),LastLog
);
724 printf(_("sarg version: %s\n"),VERSION
);
728 debuga(_("sarg version: %s\n"),VERSION
);
730 #ifdef ENABLE_DOUBLE_CHECK_DATA
731 debuga(_("Sarg compiled to report warnings if the output is inconsistent\n"));
734 maxopenfiles
=MAX_OPEN_USER_FILES
;
736 if (Ulimit
[0] != '\0') {
741 #if defined(RLIMIT_NOFILE)
742 getrlimit (RLIMIT_NOFILE
, &rl
);
743 #elif defined(RLIMIT_OFILE)
744 getrlimit (RLIMIT_OFILE
, &rl
);
746 #warning "No rlimit resource for the number of open files"
751 rl
.rlim_cur
= atol(Ulimit
);
752 rl
.rlim_max
= atol(Ulimit
);
753 #if defined(RLIMIT_NOFILE)
754 rc
=setrlimit (RLIMIT_NOFILE
, &rl
);
755 #elif defined(RLIMIT_OFILE)
756 rc
=setrlimit (RLIMIT_OFILE
, &rl
);
758 #warning "No rlimit resource for the number of open files"
761 debuga(_("setrlimit error - %s\n"),strerror(errno
));
765 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
);
769 init_usertab(UserTabFile
);
771 if ((line
=longline_create())==NULL
) {
772 debuga(_("Not enough memory to read a log file\n"));
776 snprintf(sz_Download_Unsort
,sizeof(sz_Download_Unsort
),"%s/download.int_unsort", tmp
);
778 if(DataFile
[0]=='\0') {
779 if((ReportType
& REPORT_TYPE_DENIED
) != 0) {
780 if((fp_denied
=MY_FOPEN(denied_unsort
,"w"))==NULL
) {
781 debuga(_("(log) Cannot open file: %s - %s\n"),denied_unsort
,strerror(errno
));
786 if((ReportType
& REPORT_TYPE_DENIED
) != 0 || (ReportType
& REPORT_TYPE_AUTH_FAILURES
) != 0) {
787 if((fp_authfail
=MY_FOPEN(authfail_unsort
,"w"))==NULL
) {
788 debuga(_("(log) Cannot open file: %s - %s\n"),authfail_unsort
,strerror(errno
));
794 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++) {
795 strcpy(arq
,AccessLog
[iarq
]);
799 if(strcmp(arq
,"-")==0) {
801 debuga(_("Reading access log file: from stdin\n"));
806 if (stat(arq
,&logstat
)!=0) {
807 debuga(_("Cannot get the modification time of input log file %s (%s). Processing it anyway\n"),arq
,strerror(errno
));
809 struct tm
*logtime
=localtime(&logstat
.st_mtime
);
810 if ((logtime
->tm_year
+1900)*10000+(logtime
->tm_mon
+1)*100+logtime
->tm_mday
<dfrom
) {
811 debuga(_("Ignoring old log file %s\n"),arq
);
816 fp_in
=decomp(arq
,&from_pipe
);
818 debuga(_("(log) Cannot open log file: %s - %s\n"),arq
,strerror(errno
));
821 if(debug
) debuga(_("Reading access log file: %s\n"),arq
);
826 // pre-read the file only if we have to show stats
827 if(ShowReadStatistics
&& !from_stdin
&& !from_pipe
) {
835 while ((nread
=fread(tmp4
,1,sizeof(tmp4
),fp_in
))>0) {
836 for (i
=0 ; i
<nread
; i
++)
838 if (tmp4
[i
]!='\n' && tmp4
[i
]!='\r') {
842 if (tmp4
[i
]=='\n' || tmp4
[i
]=='\r') {
849 printf(_("SARG: Records in file: %lu, reading: %3.2f%%"),recs1
,(float) 0);
854 longline_reset(line
);
856 while ((linebuf
=longline_read(fp_in
,line
))!=NULL
) {
857 blen
=strlen(linebuf
);
859 if (ilf
==ILF_Unknown
) {
860 if(strncmp(linebuf
,"#Software: Mic",14) == 0) {
861 fixendofline(linebuf
);
863 debuga(_("Log is from Microsoft ISA: %s\n"),linebuf
);
869 if(strncmp(linebuf
,"*** SARG Log ***",16) == 0) {
870 if (getperiod_fromsarglog(arqtt
,&period
)<0) {
871 debuga(_("The name of the file is invalid: %s\n"),arq
);
880 if(!fp_log
&& ParsedOutputLog
[0] && ilf
!=ILF_Sarg
) {
881 if(access(ParsedOutputLog
,R_OK
) != 0) {
882 my_mkdir(ParsedOutputLog
);
884 if (snprintf(arq_log
,sizeof(arq_log
),"%s/sarg_temp.log",ParsedOutputLog
)>=sizeof(arq_log
)) {
885 debuga(_("File name too long: %s/sarg_temp.log\n"),ParsedOutputLog
);
888 if((fp_log
=MY_FOPEN(arq_log
,"w"))==NULL
) {
889 debuga(_("(log) Cannot open log file: %s - %s\n"),arq_log
,strerror(errno
));
892 fputs("*** SARG Log ***\n",fp_log
);
896 if( ShowReadStatistics
&& !from_stdin
&& !from_pipe
&& --OutputNonZero
<=0) {
897 double perc
= recs2
* 100. / recs1
;
898 printf(_("SARG: Records in file: %lu, reading: %3.2lf%%"),recs2
,perc
);
901 OutputNonZero
= REPORT_EVERY_X_LINES
;
903 if(blen
< 58) continue;
904 if(strstr(linebuf
,"HTTP/0.0") != 0) continue;
905 if(strstr(linebuf
,"logfile turned over") != 0) continue;
906 if(linebuf
[0] == ' ') continue;
909 if(ExcludeString
[0] != '\0') {
911 getword_start(&gwarea
,ExcludeString
);
912 while(strchr(gwarea
.current
,':') != 0) {
913 if (getword_multisep(val1
,sizeof(val1
),&gwarea
,':')<0) {
914 debuga(_("Maybe you have a broken record or garbage in your exclusion string\n"));
917 if((str
=(char *) strstr(linebuf
,val1
)) != (char *) NULL
) {
922 if(!exstring
&& (str
=(char *) strstr(linebuf
,gwarea
.current
)) != (char *) NULL
)
924 if(exstring
) continue;
929 printf("BUF=%s\n",linebuf
);
932 if (ilf
==ILF_Squid
|| ilf
==ILF_Common
|| ilf
==ILF_Unknown
) {
933 getword_start(&gwarea
,linebuf
);
934 if (getword(data
,sizeof(data
),&gwarea
,' ')<0) {
935 debuga(_("Maybe you have a broken time in your access.log file\n"));
938 if((str
=(char *) strchr(data
, '.')) != (char *) NULL
&& (str
=(char *) strchr(str
+1, '.')) != (char *) NULL
) {
942 if (getword(user
,sizeof(user
),&gwarea
,' ')<0 || getword_skip(255,&gwarea
,' ')<0) {
943 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
947 if (getword_skip(255,&gwarea
,' ')<0 || getword(user
,sizeof(user
),&gwarea
,' ')<0) {
948 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
952 if (getword(data
,sizeof(data
),&gwarea
,']')<0 || getword_skip(MAXLEN
,&gwarea
,'"')<0 ||
953 getword(fun
,sizeof(fun
),&gwarea
,' ')<0) {
954 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
957 if (getword_ptr(linebuf
,&full_url
,&gwarea
,' ')<0) {
958 debuga(_("Maybe you have a broken url in your %s file\n"),arq
);
961 if (getword_skip(MAXLEN
,&gwarea
,' ')<0) {
962 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
965 if (getword(code2
,sizeof(code2
),&gwarea
,' ')<0) {
966 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
969 if (getword(tam
,sizeof(tam
),&gwarea
,' ')<0) {
970 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
973 if((str
=(char *) strchr(gwarea
.current
, ' ')) != (char *) NULL
) {
974 if (getword(code
,sizeof(code
),&gwarea
,' ')<0) {
975 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
979 if (getword(code
,sizeof(code
),&gwarea
,'\0')<0) {
980 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
985 if ((str
= strchr(code
, ':')) != NULL
)
988 if(strcmp(tam
,"\0") == 0)
994 getword_start(&gwarea
,data
+1);
995 if (getword_multisep(data
,sizeof(data
),&gwarea
,':')<0){
996 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
999 if (getword_multisep(hora
,sizeof(hora
),&gwarea
,' ')<0){
1000 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1003 getword_start(&gwarea
,data
);
1004 if (getword_atoll(&iday
,&gwarea
,'/')<0){
1005 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1008 if (getword(mes
,sizeof(mes
),&gwarea
,'/')<0){
1009 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1012 if (getword_atoll(&iyear
,&gwarea
,'/')<0){
1013 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1017 imonth
=month2num(mes
)+1;
1018 idata
=builddia(iday
,imonth
,iyear
);
1019 computedate(iyear
,imonth
,iday
,&tt
);
1020 if (sscanf(hora
,"%d:%d:%d",&tt
.tm_hour
,&tt
.tm_min
,&tt
.tm_sec
)!=3 || tt
.tm_hour
<0 || tt
.tm_hour
>=24 ||
1021 tt
.tm_min
<0 || tt
.tm_min
>=60 || tt
.tm_sec
<0 || tt
.tm_sec
>=60) {
1022 debuga(_("Invalid time found in %s\n"),arq
);
1028 if(ilf
==ILF_Unknown
|| ilf
==ILF_Squid
) {
1029 if (getword(elap
,sizeof(elap
),&gwarea
,' ')<0) {
1030 debuga(_("Maybe you have a broken elapsed time in your %s file\n"),arq
);
1033 while(strcmp(elap
,"") == 0 && gwarea
.current
[0] != '\0')
1034 if (getword(elap
,sizeof(elap
),&gwarea
,' ')<0) {
1035 debuga(_("Maybe you have a broken elapsed time in your %s file\n"),arq
);
1038 if(strlen(elap
) < 1) continue;
1039 if (getword(ip
,sizeof(ip
),&gwarea
,' ')<0){
1040 debuga(_("Maybe you have a broken client IP address in your %s file\n"),arq
);
1043 if (getword(code
,sizeof(code
),&gwarea
,' ')<0){
1044 debuga(_("Maybe you have a broken result code in your %s file\n"),arq
);
1047 if (getword(tam
,sizeof(tam
),&gwarea
,' ')<0){
1048 debuga(_("Maybe you have a broken amount of data in your %s file\n"),arq
);
1051 if (getword(fun
,sizeof(fun
),&gwarea
,' ')<0){
1052 debuga(_("Maybe you have a broken request method in your %s file\n"),arq
);
1055 if (getword_ptr(linebuf
,&full_url
,&gwarea
,' ')<0){
1056 debuga(_("Maybe you have a broken url in your %s file\n"),arq
);
1059 if (getword(user
,sizeof(user
),&gwarea
,' ')<0){
1060 debuga(_("Maybe you have a broken user ID in your %s file\n"),arq
);
1069 debuga(_("Cannot convert the timestamp from the squid log file\n"));
1073 strftime(tbuf2
, sizeof(tbuf2
), "%H%M", t
);
1075 idata
=(t
->tm_year
+1900)*10000+(t
->tm_mon
+1)*100+t
->tm_mday
;
1078 if (ilf
==ILF_Sarg
) {
1079 getword_start(&gwarea
,linebuf
);
1080 if (getword(data
,sizeof(data
),&gwarea
,'\t')<0){
1081 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1084 if (getword(hora
,sizeof(hora
),&gwarea
,'\t')<0) {
1085 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1088 if (getword(user
,sizeof(user
),&gwarea
,'\t')<0) {
1089 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1092 if (getword(ip
,sizeof(ip
),&gwarea
,'\t')<0) {
1093 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1096 if (getword_ptr(linebuf
,&full_url
,&gwarea
,'\t')<0){
1097 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1100 if (getword(tam
,sizeof(tam
),&gwarea
,'\t')<0){
1101 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1104 if (getword(code
,sizeof(code
),&gwarea
,'\t')<0){
1105 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1108 if (getword(elap
,sizeof(elap
),&gwarea
,'\t')<0){
1109 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1112 if (getword(smartfilter
,sizeof(smartfilter
),&gwarea
,'\0')<0){
1113 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1116 getword_start(&gwarea
,data
);
1117 if (getword_atoll(&iday
,&gwarea
,'/')<0 || iday
<1 || iday
>31){
1118 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1121 if (getword_atoll(&imonth
,&gwarea
,'/')<0 || imonth
<1 || imonth
>12){
1122 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1125 if (getword_atoll(&iyear
,&gwarea
,'\0')<0){
1126 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1129 idata
=builddia(iday
,imonth
,iyear
);
1130 computedate(iyear
,imonth
,iday
,&tt
);
1131 if (sscanf(hora
,"%d:%d:%d",&tt
.tm_hour
,&tt
.tm_min
,&tt
.tm_sec
)!=3 || tt
.tm_hour
<0 || tt
.tm_hour
>=24 ||
1132 tt
.tm_min
<0 || tt
.tm_min
>=60 || tt
.tm_sec
<0 || tt
.tm_sec
>=60) {
1133 debuga(_("Invalid time found in %s\n"),arq
);
1139 if (linebuf
[0] == '#') {
1140 int ncols
,cols
[ISACOL_Last
];
1142 fixendofline(linebuf
);
1143 getword_start(&gwarea
,linebuf
);
1144 // remove the #Fields: column at the beginning of the line
1145 if (getword_skip(1000,&gwarea
,' ')<0){
1146 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1149 for (ncols
=0 ; ncols
<ISACOL_Last
; ncols
++) cols
[ncols
]=-1;
1151 while(gwarea
.current
[0] != '\0') {
1152 if (getword(val1
,sizeof(val1
),&gwarea
,'\t')<0){
1153 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1156 if(strcmp(val1
,"c-ip") == 0) cols
[ISACOL_Ip
]=ncols
;
1157 if(strcmp(val1
,"cs-username") == 0) cols
[ISACOL_UserName
]=ncols
;
1158 if(strcmp(val1
,"date") == 0) cols
[ISACOL_Date
]=ncols
;
1159 if(strcmp(val1
,"time") == 0) cols
[ISACOL_Time
]=ncols
;
1160 if(strcmp(val1
,"time-taken") == 0) cols
[ISACOL_TimeTaken
]=ncols
;
1161 if(strcmp(val1
,"sc-bytes") == 0) cols
[ISACOL_Bytes
]=ncols
;
1162 if(strcmp(val1
,"cs-uri") == 0) cols
[ISACOL_Uri
]=ncols
;
1163 if(strcmp(val1
,"sc-status") == 0) cols
[ISACOL_Status
]=ncols
;
1166 if (cols
[ISACOL_Ip
]>=0) {
1168 for (ncols
=0 ; ncols
<ISACOL_Last
; ncols
++)
1169 isa_cols
[ncols
]=cols
[ncols
];
1173 if (!isa_ncols
) continue;
1174 getword_start(&gwarea
,linebuf
);
1175 for (x
=0 ; x
<isa_ncols
; x
++) {
1176 if (getword_ptr(linebuf
,&str
,&gwarea
,'\t')<0) {
1177 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1180 if (x
==isa_cols
[ISACOL_Ip
]) {
1181 if (strlen(str
)>=sizeof(ip
)) {
1182 debuga(_("Maybe you have a broken IP in your %s file\n"),arq
);
1186 } else if (x
==isa_cols
[ISACOL_UserName
]) {
1187 if (strlen(str
)>=sizeof(user
)) {
1188 debuga(_("Maybe you have a broken user ID in your %s file\n"),arq
);
1192 } else if (x
==isa_cols
[ISACOL_Date
]) {
1193 if (strlen(str
)>=sizeof(data
)) {
1194 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1198 } else if (x
==isa_cols
[ISACOL_Time
]) {
1199 if (strlen(str
)>=sizeof(hora
)) {
1200 debuga(_("Maybe you have a broken time in your %s file\n"),arq
);
1204 } else if (x
==isa_cols
[ISACOL_TimeTaken
]) {
1205 if (strlen(str
)>=sizeof(elap
)) {
1206 debuga(_("Maybe you have a broken download duration in your %s file\n"),arq
);
1210 } else if (x
==isa_cols
[ISACOL_Bytes
]) {
1211 if (strlen(str
)>=sizeof(tam
)) {
1212 debuga(_("Maybe you have a broken download size in your %s file\n"),arq
);
1216 } else if (x
==isa_cols
[ISACOL_Uri
]) {
1218 } else if (x
==isa_cols
[ISACOL_Status
]) {
1219 if (strlen(str
)>=sizeof(code
)) {
1220 debuga(_("Maybe you have a broken access code in your %s file\n"),arq
);
1227 if(strcmp(code
,"401") == 0 || strcmp(code
,"403") == 0 || strcmp(code
,"407") == 0) {
1228 sprintf(val1
,"DENIED/%s",code
);
1231 getword_start(&gwarea
,data
);
1232 if (getword_atoll(&iyear
,&gwarea
,'-')<0){
1233 debuga(_("Maybe you have a broken year in your %s file\n"),arq
);
1236 if (getword_atoll(&imonth
,&gwarea
,'-')<0){
1237 debuga(_("Maybe you have a broken month in your %s file\n"),arq
);
1240 if (getword_atoll(&iday
,&gwarea
,'\0')<0){
1241 debuga(_("Maybe you have a broken day in your %s file\n"),arq
);
1245 idata
=builddia(iday
,imonth
,iyear
);
1246 computedate(iyear
,imonth
,iday
,&tt
);
1247 if (isa_cols
[ISACOL_Time
]>=0) {
1248 if (sscanf(hora
,"%d:%d:%d",&tt
.tm_hour
,&tt
.tm_min
,&tt
.tm_sec
)!=3 || tt
.tm_hour
<0 || tt
.tm_hour
>=24 ||
1249 tt
.tm_min
<0 || tt
.tm_min
>=60 || tt
.tm_sec
<0 || tt
.tm_sec
>=60) {
1250 debuga(_("Invalid time found in %s\n"),arq
);
1257 debuga(_("Unknown input log file format\n"));
1261 strftime(dia
, sizeof(dia
), "%d/%m/%Y", t
);
1262 snprintf(hora
,sizeof(hora
),"%02d:%02d:%02d",t
->tm_hour
,t
->tm_min
,t
->tm_sec
);
1265 printf("DATE=%s IDATA=%d DFROM=%d DUNTIL=%d\n",date
,idata
,dfrom
,duntil
);
1267 if(date
[0] != '\0'){
1268 if(idata
< dfrom
|| idata
> duntil
) continue;
1271 // Record only hours usage which is required
1273 if( bsearch( &( t
-> tm_wday
), weekdays
.list
, weekdays
.len
, sizeof( int ), compar
) == NULL
)
1276 if( bsearch( &( t
-> tm_hour
), hours
.list
, hours
.len
, sizeof( int ), compar
) == NULL
)
1281 if(strlen(user
) > MAX_USER_LEN
) {
1282 if (debugm
) printf(_("User ID too long: %s\n"),user
);
1288 if(IncludeUsers
[0] != '\0') {
1289 snprintf(val1
,sizeof(val1
),":%s:",user
);
1290 if((str
=(char *) strstr(IncludeUsers
,val1
)) == (char *) NULL
)
1295 if (debugm
) printf(_("Excluded code: %s\n"),code
);
1300 if(testvaliduserchar(user
))
1304 if((str
= strstr(user
,"%20")) != NULL
) {
1306 This is a patch introduced to solve bug #1624251 reported at sourceforge but
1307 the side effect is to truncate the name at the first space and merge the reports
1308 of people whose name is identical up to the first space.
1310 The old code used to truncate the user name at the first % if a %20 was
1311 found anywhere in the string. That means the string could be truncated
1312 at the wrong place if another % occured before the %20. This new code should
1313 avoid that problem and only truncate at the space. There is no bug
1314 report indicating that anybody noticed this.
1320 Code prior to 2.2.7 used to replace any %xx by a dot as long as a %5c was
1321 found in the user name.
1323 while((str
= strstr(user
,"%5c")) != NULL
) {
1325 for (x
=3 ; str
[x
] ; x
++) str
[x
-2]=str
[x
];
1328 // replace any tab by a single space
1329 for (str
=full_url
; *str
; str
++)
1330 if (*str
=='\t') *str
=' ';
1331 for (str
=code
; *str
; str
++)
1332 if (*str
=='\t') *str
=' ';
1336 The full URL is not saved in sarg log. There is no point in testing the URL to detect
1339 download_flag
=is_download_suffix(full_url
);
1340 if (download_flag
) {
1341 safe_strcpy(download_url
,full_url
,sizeof(download_url
));
1345 download_flag
=false;
1347 url
=process_url(full_url
,LongUrl
);
1348 if (!url
|| url
[0] == '\0') continue;
1350 if(addr
[0] != '\0'){
1351 if(strcmp(addr
,ip
)!=0) continue;
1354 if(!vhexclude(url
)) {
1355 if (debugm
) printf(_("Excluded site: %s\n"),url
);
1361 if(hm
>= 0 && hmf
>= 0) {
1362 hmr
=t
->tm_hour
*100+t
->tm_min
;
1363 if(hmr
< hm
|| hmr
> hmf
) continue;
1366 if(site
[0] != '\0'){
1367 if(strstr(url
,site
)==0) continue;
1375 if(strcmp(user
,"-") == 0 || strcmp(user
," ") == 0 || strcmp(user
,"") == 0) {
1376 if(RecordsWithoutUser
== RECORDWITHOUTUSER_IP
) {
1380 if(RecordsWithoutUser
== RECORDWITHOUTUSER_IGNORE
)
1382 if(RecordsWithoutUser
== RECORDWITHOUTUSER_EVERYBODY
)
1383 strcpy(user
,"everybody");
1386 if(NtlmUserFormat
== NTLMUSERFORMAT_USER
) {
1387 if ((str
=strchr(user
,'+'))!=NULL
|| (str
=strchr(user
,'\\'))!=NULL
|| (str
=strchr(user
,'_'))!=NULL
) {
1388 strcpy(warea
,str
+1);
1396 if(strcmp(user
,us
)!=0) continue;
1400 snprintf(wuser
,sizeof(wuser
),":%s:",user
);
1401 if(strstr(userfile
, wuser
) == 0)
1406 if(!vuexclude(user
)) {
1407 if (debugm
) printf(_("Excluded user: %s\n"),user
);
1413 if(strcmp(user
,"-") ==0 || strcmp(user
," ") ==0 || strcmp(user
,"") ==0 || strcmp(user
,":") ==0)
1417 if (nbytes
<0) nbytes
=0;
1419 elap_time
=atol(elap
);
1420 if (elap_time
<0) elap_time
=0;
1422 if(elap_time
>max_elapsed
) {
1427 if((str
=(char *) strstr(linebuf
, "[SmartFilter:")) != (char *) NULL
) {
1429 snprintf(smartfilter
,sizeof(smartfilter
),"\"%s\"",str
+1);
1430 } else strcpy(smartfilter
,"\"\"");
1434 for (ufile
=first_user_file
; ufile
&& strcmp(user
,ufile
->user
->id
)!=0 ; ufile
=ufile
->next
) {
1436 if (ufile
->file
) nopen
++;
1439 ufile
=malloc(sizeof(*ufile
));
1441 debuga(_("Not enough memory to store the user %s\n"),user
);
1444 memset(ufile
,0,sizeof(*ufile
));
1445 ufile
->next
=first_user_file
;
1446 first_user_file
=ufile
;
1447 uinfo
=userinfo_create(user
);
1449 uinfo
->id_is_ip
=id_is_ip
;
1452 prev_ufile
->next
=ufile
->next
;
1453 ufile
->next
=first_user_file
;
1454 first_user_file
=ufile
;
1457 #ifdef ENABLE_DOUBLE_CHECK_DATA
1458 ufile
->user
->nbytes
+=nbytes
;
1459 ufile
->user
->elap
+=elap_time
;
1462 if (ufile
->file
==NULL
) {
1463 if (nopen
>=maxopenfiles
) {
1465 for (ufile1
=first_user_file
; ufile1
; ufile1
=ufile1
->next
) {
1466 if (ufile1
->file
!=NULL
) {
1467 if (x
>=maxopenfiles
) {
1468 if (fclose(ufile1
->file
)==EOF
) {
1469 debuga(_("Failed to close the log file of user %s - %s\n"),ufile1
->user
->id
,strerror(errno
));
1478 if (snprintf (tmp3
, sizeof(tmp3
), "%s/%s.user_unsort", tmp
, ufile
->user
->filename
)>=sizeof(tmp3
)) {
1479 debuga(_("Temporary user file name too long: %s/%s.user_unsort\n"), tmp
, ufile
->user
->filename
);
1482 if ((ufile
->file
= MY_FOPEN (tmp3
, "a")) == NULL
) {
1483 debuga(_("(log) Cannot open temporary file: %s - %s\n"), tmp3
, strerror(errno
));
1488 if (fprintf(ufile
->file
, "%s\t%s\t%s\t%s\t%ld\t%s\t%ld\t%s\n",dia
,hora
,ip
,url
,nbytes
,code
,elap_time
,smartfilter
)<=0) {
1489 debuga(_("Write error in the log file of user %s\n"),user
);
1493 if(fp_log
&& ilf
!=ILF_Sarg
)
1494 fprintf(fp_log
, "%s\t%s\t%s\t%s\t%s\t%ld\t%s\t%ld\t%s\n",dia
,hora
,user
,ip
,url
,nbytes
,code
,elap_time
,smartfilter
);
1498 if(!dataonly
&& download_flag
&& strstr(code
,"DENIED") == 0) {
1501 if ( ! fp_Download_Unsort
) {
1502 if ((fp_Download_Unsort
= MY_FOPEN ( sz_Download_Unsort
, "a")) == NULL
) {
1503 debuga(_("(log) Cannot open temporary file: %s - %s\n"),sz_Download_Unsort
, strerror(errno
));
1507 fprintf(fp_Download_Unsort
,"%s\t%s\t%s\t%s\t%s\n",dia
,hora
,user
,ip
,download_url
);
1510 if((ReportType
& REPORT_TYPE_DENIED
) != 0) {
1511 if(fp_denied
&& strstr(code
,"DENIED/403") != 0) {
1512 fprintf(fp_denied
, "%s\t%s\t%s\t%s\t%s\n",dia
,hora
,user
,ip
,full_url
);
1516 if((ReportType
& REPORT_TYPE_AUTH_FAILURES
) != 0) {
1517 if(fp_authfail
&& (strstr(code
,"DENIED/401") != 0 || strstr(code
,"DENIED/407") != 0)) {
1518 fprintf(fp_authfail
, "%s\t%s\t%s\t%s\t%s\n",dia
,hora
,user
,ip
,full_url
);
1523 if (ilf
!=ILF_Sarg
) {
1524 if(!totper
|| idata
<mindate
){
1526 memcpy(&period
.start
,t
,sizeof(*t
));
1527 strcpy(start_hour
,tbuf2
);
1529 if (!totper
|| idata
>maxdate
) {
1531 memcpy(&period
.end
,t
,sizeof(*t
));
1537 printf("IP=\t%s\n",ip
);
1538 printf("USER=\t%s\n",user
);
1539 printf("ELAP=\t%ld\n",elap_time
);
1540 printf("DATE=\t%s\n",dia
);
1541 printf("TIME=\t%s\n",hora
);
1542 printf("FUNC=\t%s\n",fun
);
1543 printf("URL=\t%s\n",url
);
1544 printf("CODE=\t%s\n",code
);
1545 printf("LEN=\t%ld\n",nbytes
);
1553 if( ShowReadStatistics
)
1554 printf(_("SARG: Records in file: %lu, reading: %3.2f%%\n"),recs1
, (float) 100 );
1560 debuga(_(" Records read: %ld, written: %ld, excluded: %ld\n"),totregsl
,totregsg
,totregsx
);
1562 longline_destroy(&line
);
1563 if ( fp_Download_Unsort
)
1564 fclose (fp_Download_Unsort
);
1566 for (ufile
=first_user_file
; ufile
; ufile
=ufile1
) {
1568 if (ufile
->file
!=NULL
) fclose(ufile
->file
);
1573 free_excludecodes();
1579 for (ilf
=0 ; ilf
<ILF_Last
; ilf
++) totalcount
+=ilf_count
[ilf
];
1581 if(ilf_count
[ILF_Common
]>0 && ilf_count
[ILF_Squid
]>0)
1582 debuga(_("Log with mixed records format (squid and common log)\n"));
1584 if(ilf_count
[ILF_Common
]>0 && ilf_count
[ILF_Squid
]==0)
1585 debuga(_("Common log format\n"));
1587 if(ilf_count
[ILF_Common
]==0 && ilf_count
[ILF_Squid
]>0)
1588 debuga(_("Squid log format\n"));
1590 if(ilf_count
[ILF_Sarg
]>0)
1591 debuga(_("Sarg log format\n"));
1593 if(totalcount
==0 && totregsg
)
1594 debuga(_("Log with invalid format\n"));
1598 debuga(_("No records found\n"));
1600 if(fp_denied
) fclose(fp_denied
);
1601 if(fp_authfail
) fclose(fp_authfail
);
1603 if(userfile
) free(userfile
);
1608 if (date
[0]!='\0') {
1609 char date0
[30], date1
[30];
1611 strftime(date0
,sizeof(date0
),"%d/%m/%Y",&period
.start
);
1612 strftime(date1
,sizeof(date1
),"%d/%m/%Y",&period
.end
);
1613 debuga(_("Period covered by log files: %s-%s\n"),date0
,date1
);
1614 getperiod_fromrange(&period
,dfrom
,duntil
);
1616 if (getperiod_buildtext(&period
)<0) {
1617 debuga(_("Failed to build the string representation of the date range\n"));
1622 debugaz(_("date=%s\n"),dia
);
1623 debugaz(_("period=%s\n"),period
.text
);
1627 debuga(_("Period: %s\n"),period
.text
);
1632 fclose(fp_authfail
);
1634 if(fp_log
!= NULL
) {
1637 char val4
[255];//val4 must not be bigger than arq_log without fixing the strcpy below
1640 safe_strcpy(end_hour
,tbuf2
,sizeof(end_hour
));
1641 strftime(val2
,sizeof(val2
),"%d%m%Y",&period
.start
);
1642 strftime(val1
,sizeof(val1
),"%d%m%Y",&period
.end
);
1643 if (snprintf(val4
,sizeof(val4
),"%s/sarg-%s_%s-%s_%s.log",ParsedOutputLog
,val2
,start_hour
,val1
,end_hour
)>=sizeof(val4
)) {
1644 debuga(_("File name too long: %s/sarg-%s_%s-%s_%s.log\n"),ParsedOutputLog
,val2
,start_hour
,val1
,end_hour
);
1647 if (rename(arq_log
,val4
)) {
1648 debuga(_("failed to rename %s to %s - %s\n"),arq_log
,val4
,strerror(errno
));
1650 strcpy(arq_log
,val4
);
1652 if(strcmp(ParsedOutputLogCompress
,"nocompress") != 0 && ParsedOutputLogCompress
[0] != '\0') {
1654 No double quotes around ParsedOutputLogCompress because it may contain command line options. If double quotes are
1655 necessary around the command name, put them in the configuration file.
1657 if (snprintf(val1
,sizeof(val1
),"%s \"%s\"",ParsedOutputLogCompress
,arq_log
)>=sizeof(val1
)) {
1658 debuga(_("Command too long: %s \"%s\"\n"),ParsedOutputLogCompress
,arq_log
);
1661 cstatus
=system(val1
);
1662 if (!WIFEXITED(cstatus
) || WEXITSTATUS(cstatus
)) {
1663 debuga(_("command return status %d\n"),WEXITSTATUS(cstatus
));
1664 debuga(_("command: %s\n"),val1
);
1670 debuga(_("Sarg parsed log saved as %s\n"),arq_log
);
1673 if(DataFile
[0] == '\0' && (ReportType
& REPORT_TYPE_DENIED
) != 0) {
1674 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
)) {
1675 debuga(_("Sort command too long when sorting file \"%s\" to \"%s\"\n"),denied_unsort
,denied_sort
);
1678 cstatus
=system(csort
);
1679 if (!WIFEXITED(cstatus
) || WEXITSTATUS(cstatus
)) {
1680 debuga(_("sort command return status %d\n"),WEXITSTATUS(cstatus
));
1681 debuga(_("sort command: %s\n"),csort
);
1684 if (!KeepTempLog
&& unlink(denied_unsort
)) {
1685 debuga(_("Cannot delete \"%s\": %s\n"),denied_unsort
,strerror(errno
));
1690 if(DataFile
[0] != '\0')
1695 if((ReportType
& REPORT_TYPE_DENIED
) != 0) {
1696 if (!KeepTempLog
&& unlink(denied_sort
) && errno
!=ENOENT
)
1697 debuga(_("Cannot delete \"%s\": %s\n"),denied_sort
,strerror(errno
));
1700 if(!KeepTempLog
&& strcmp(tmp
,"/tmp") != 0) {
1718 static void getusers(const char *pwdfile
, int debug
)
1726 debuga(_("Loading password file from %s\n"),pwdfile
);
1728 if ((fp_usr
= fopen(pwdfile
, "r")) == NULL
) {
1729 debuga(_("(getusers) Cannot open file %s - %s\n"),pwdfile
,strerror(errno
));
1733 if (fseek(fp_usr
, 0, SEEK_END
)==-1) {
1734 debuga(_("Failed to move till the end of the users file %s: %s\n"),pwdfile
,strerror(errno
));
1737 nreg
= ftell(fp_usr
);
1739 debuga(_("Cannot get the size of file %s\n"),pwdfile
);
1743 if (fseek(fp_usr
, 0, SEEK_SET
)==-1) {
1744 debuga(_("Failed to rewind the users file %s: %s\n"),pwdfile
,strerror(errno
));
1748 if((userfile
=(char *) malloc(nreg
))==NULL
){
1749 debuga(_("malloc error (%ld)\n"),nreg
);
1753 bzero(userfile
,nreg
);
1754 strcpy(userfile
,":");
1756 while(fgets(buf
,sizeof(buf
),fp_usr
)!=NULL
) {
1757 str
=strchr(buf
,':');
1759 debuga(_("You have an invalid user in your %s file\n"),pwdfile
);
1763 strcat(userfile
,buf
);