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
];
100 char hexclude
[MAXLEN
];
107 char denied_unsort
[MAXLEN
];
108 char denied_sort
[MAXLEN
];
109 char authfail_unsort
[MAXLEN
];
110 char start_hour
[128];
116 char user
[MAX_USER_LEN
];
117 enum InputLogFormat ilf
;
118 int ilf_count
[ILF_Last
];
130 int isa_ncols
=0,isa_cols
[ISACOL_Last
];
142 long int max_elapsed
=0;
143 long long int iyear
, imonth
, iday
;
148 unsigned long recs1
=0UL;
149 unsigned long recs2
=0UL;
150 int OutputNonZero
= REPORT_EVERY_X_LINES
;
151 bool download_flag
=false;
152 char *download_url
=NULL
;
153 struct getwordstruct gwarea
;
157 struct userinfostruct
*uinfo
;
158 struct userfilestruct
*first_user_file
, *ufile
, *ufile1
, *prev_ufile
;
160 static int convert
=0;
161 static int output_css
=0;
163 static struct option long_options
[]=
165 {"convert",no_argument
,&convert
,1},
166 {"css",no_argument
,&output_css
,1},
167 {"lastlog",required_argument
,NULL
,2},
168 {"keeplogs",no_argument
,NULL
,3},
169 {"split",no_argument
,&split
,1},
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 sprintf(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");
227 strcpy(DateFormat
,"u");
228 OverwriteReport
=false;
229 RemoveTempFiles
=true;
230 strcpy(ReplaceIndex
,"index.html");
232 RecordsWithoutUser
=RECORDWITHOUTUSER_IP
;
234 strcpy(MailUtility
,"mailx");
238 TopuserSort
=TOPUSER_SORT_BYTES
| TOPUSER_SORT_REVERSE
;
239 UserSort
=USER_SORT_BYTES
| USER_SORT_REVERSE
;
240 TopsitesSort
=TOPSITE_SORT_CONNECT
| TOPSITE_SORT_REVERSE
;
242 strcpy(FontFace
,"Verdana,Tahoma,Arial");
243 datetimeby
=DATETIME_BYTE
;
244 strcpy(CharSet
,"ISO-8859-1");
246 strcpy(PrivacyString
,"***.***.***.***");
247 strcpy(PrivacyStringColor
,"blue");
249 TopUserFields
=TOPUSERFIELDS_NUM
| TOPUSERFIELDS_DATE_TIME
| TOPUSERFIELDS_USERID
| TOPUSERFIELDS_CONNECT
|
250 TOPUSERFIELDS_BYTES
| TOPUSERFIELDS_SETYB
| TOPUSERFIELDS_IN_CACHE_OUT
|
251 TOPUSERFIELDS_USED_TIME
| TOPUSERFIELDS_MILISEC
| TOPUSERFIELDS_PTIME
|
252 TOPUSERFIELDS_TOTAL
| TOPUSERFIELDS_AVERAGE
;
253 UserReportFields
=USERREPORTFIELDS_CONNECT
| USERREPORTFIELDS_BYTES
| USERREPORTFIELDS_SETYB
|
254 USERREPORTFIELDS_IN_CACHE_OUT
| USERREPORTFIELDS_USED_TIME
| USERREPORTFIELDS_MILISEC
|
255 USERREPORTFIELDS_PTIME
| USERREPORTFIELDS_TOTAL
| USERREPORTFIELDS_AVERAGE
;
256 strcpy(DataFileDelimiter
,";");
257 DataFileFields
=DATA_FIELD_USER
| DATA_FIELD_DATE
| DATA_FIELD_TIME
| DATA_FIELD_URL
| DATA_FIELD_CONNECT
|
258 DATA_FIELD_BYTES
| DATA_FIELD_IN_CACHE
| DATA_FIELD_OUT_CACHE
| DATA_FIELD_ELAPSED
;
259 ShowReadStatistics
=true;
260 strcpy(IndexSortOrder
,"D");
263 ParsedOutputLog
[0]='\0';
264 strcpy(ParsedOutputLogCompress
,"/bin/gzip -f");
265 DisplayedValues
=DISPLAY_ABBREV
;
266 strcpy(HeaderFontSize
,"9px");
267 strcpy(TitleFontSize
,"11px");
268 strcpy(AuthUserTemplateFile
,"sarg_htaccess");
269 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");
272 strcpy(GraphFont
,FONTDIR
"/DejaVuSans.ttf");
276 strcpy(Ulimit
,"20000");
277 NtlmUserFormat
=NTLMUSERFORMAT_DOMAINUSER
;
278 IndexTree
=INDEX_TREE_FILE
;
279 IndexFields
=INDEXFIELDS_DIRSIZE
;
280 strcpy(RealtimeTypes
,"GET,PUT,CONNECT");
281 RealtimeUnauthRec
=REALTIME_UNAUTH_REC_SHOW
;
282 RedirectorFilterOutDate
=true;
283 DansguardianFilterOutDate
=true;
284 DataFileUrl
=DATAFILEURL_IP
;
285 strcpy(MaxElapsed
,"28800000");
286 BytesInSitesUsersReport
=0;
287 UserAuthentication
=0;
288 strcpy(LDAPHost
,"127.0.0.1");
290 LDAPProtocolVersion
=3;
293 LDAPBaseSearch
[0]='\0';
294 strcpy(LDAPFilterSearch
, "(uid=%s)");
295 strcpy(LDAPTargetAttr
, "cn");
318 UserInvalidChar
[0]='\0';
320 SquidGuardConf
[0]='\0';
321 DansGuardianConf
[0]='\0';
329 dansguardian_count
=0;
332 DeniedReportLimit
=10;
333 AuthfailReportLimit
=10;
334 DansGuardianReportLimit
=10;
335 SquidGuardReportLimit
=10;
336 DownloadReportLimit
=50;
345 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:u:l:L:o:s:t:w:hijmnprvxyz",long_options
,&option_index
)) != -1){
372 lastlog
=atoi(optarg
);
381 strcpy(uagent
,optarg
);
384 strcpy(hexclude
,optarg
);
387 strncpy(date
,optarg
,sizeof(date
)-1);
388 date
[sizeof(date
)-1]='\0';
389 date_from(date
, &dfrom
, &duntil
);
392 strcpy(email
,optarg
);
395 strcpy(ConfigFile
,optarg
);
407 if (NAccessLog
>=MAXLOGS
) {
408 debuga(_("Too many log files passed on command line with option -l.\n"));
411 if (strlen(optarg
)>=MAX_LOG_FILELEN
) {
412 debuga(_("Log file name too long passed on command line with option -l: %s\n"),optarg
);
415 strcpy(AccessLog
[NAccessLog
],optarg
);
417 AccessLogFromCmdLine
++;
420 if (NRedirectorLogs
>MAX_REDIRECTOR_LOGS
) {
421 debuga(_("Too many redirector logs passed on command line with option -L.\n"));
424 if (strlen(optarg
)>=MAX_REDIRECTOR_FILELEN
) {
425 debuga(_("Redirector log file name too long passed on command line with opton -L: %s\n"),optarg
);
428 strcpy(RedirectorLogs
[NRedirectorLogs
],optarg
);
430 RedirectorLogFromCmdLine
++;
439 strcpy(outdir
,optarg
);
454 if(strstr(optarg
,"-") == 0) {
455 if(sscanf(optarg
,"%d:%d",&h1
,&m1
)!=2) {
456 debuga(_("Time period passed on the command line with option -t must be MM:SS\n"));
461 snprintf(hm_str
,sizeof(hm_str
),"%02d:%02d",h1
,m1
);
463 if(sscanf(optarg
,"%d:%d-%d:%d",&h1
,&m1
,&h2
,&m2
)!=4) {
464 debuga(_("Time range passed on the command line with option -t must be MM:SS-MM:SS\n"));
469 snprintf(hm_str
,sizeof(hm_str
),"%02d:%02d-%02d:%02d",h1
,m1
,h2
,m2
);
492 debuga(_("Option -%c requires an argument\n"),optopt
);
508 for (iarq
=optind
; iarq
<argc
; iarq
++) {
509 if (NAccessLog
>=MAXLOGS
) {
510 debuga(_("Too many log files passed on command line.\n"));
513 if (strlen(argv
[iarq
])>=MAX_LOG_FILELEN
) {
514 debuga(_("Log file name too long passed on command line: %s\n"),argv
[iarq
]);
517 strcpy(AccessLog
[NAccessLog
],argv
[iarq
]);
519 AccessLogFromCmdLine
++;
523 if(debug
) debuga(_("Init\n"));
525 if(ConfigFile
[0] == '\0') snprintf(ConfigFile
,sizeof(ConfigFile
),"%s/sarg.conf",SYSCONFDIR
);
526 if(access(ConfigFile
, R_OK
) != 0) {
527 debuga(_("Cannot open config file: %s - %s\n"),ConfigFile
,strerror(errno
));
531 if(access(ConfigFile
, R_OK
) == 0)
534 if(userip
) UserIp
=true;
536 if(dns
) Ip2Name
=true;
538 if (lastlog
>=0) LastLog
=lastlog
;
545 if(IndexTree
== INDEX_TREE_FILE
)
546 strcpy(ImageFile
,"../images");
548 strcpy(ImageFile
,"../../../images");
551 if(DataFile
[0] != '\0')
554 if(NAccessLog
== 0) {
555 strcpy(AccessLog
[0],"/var/log/squid/access.log");
564 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++)
565 splitlog(AccessLog
[iarq
], df
, dfrom
, duntil
, convert
);
569 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++)
570 convlog(AccessLog
[iarq
], df
, dfrom
, duntil
);
574 load_excludecodes(ExcludeCodes
);
576 if(access(PasswdFile
, R_OK
) == 0) {
577 getusers(PasswdFile
,debug
);
581 if(hexclude
[0] == '\0')
582 strcpy(hexclude
,ExcludeHosts
);
583 if(hexclude
[0] != '\0') {
584 gethexclude(hexclude
,debug
);
588 if(ReportType
== 0) {
589 ReportType
=REPORT_TYPE_TOPUSERS
| REPORT_TYPE_TOPSITES
| REPORT_TYPE_USERS_SITES
|
590 REPORT_TYPE_SITES_USERS
| REPORT_TYPE_DATE_TIME
| REPORT_TYPE_DENIED
|
591 REPORT_TYPE_AUTH_FAILURES
| REPORT_TYPE_SITE_USER_TIME_DATE
| REPORT_TYPE_DOWNLOADS
;
594 if(access(ExcludeUsers
, R_OK
) == 0) {
595 getuexclude(ExcludeUsers
,debug
);
604 if(strcmp(ExcludeUsers
,"indexonly") == 0) indexonly
++;
605 if(Index
== INDEX_ONLY
) indexonly
++;
607 if(MaxElapsed
[0] != '\0') max_elapsed
=atol(MaxElapsed
);
609 if(outdir
[0] == '\0') strcpy(outdir
,OutputDir
);
610 if(outdir
[0] != '\0') strcat(outdir
,"/");
612 if(uagent
[0] == '\0') strcpy(uagent
,UserAgentLog
);
614 if(tmp
[0] == '\0') strcpy(tmp
,TempDir
);
615 else strcpy(TempDir
,tmp
);
617 For historical reasons, the temporary directory is the subdirectory "sarg" of the path
618 provided by the user.
622 if (tmp
[0]!='\0' && strncmp(outdir
,tmp
,strlen(tmp
))==0) {
623 debuga(_("The output directory \"%s\" must be outside of the temporary directory \"%s\"\n"),outdir
,tmp
);
627 if(df
[0] == '\0') strcpy(df
,DateFormat
);
628 else strcpy(DateFormat
,df
);
632 strcpy(DateFormat
,"u");
635 IndexTree
=INDEX_TREE_FILE
;
637 if(email
[0] == '\0' && OutputEmail
[0] != '\0') strcpy(email
,OutputEmail
);
639 if(email
[0] != '\0') {
645 if(access(tmp
, R_OK
) == 0) {
649 snprintf(denied_unsort
,sizeof(denied_unsort
),"%s/denied.log.unsort",tmp
);
650 snprintf(denied_sort
,sizeof(denied_sort
),"%s/denied.log",tmp
);
651 snprintf(authfail_unsort
,sizeof(authfail_unsort
),"%s/authfail.log.unsort",tmp
);
654 debuga(_("Parameters:\n"));
655 debuga(_(" Hostname or IP address (-a) = %s\n"),addr
);
656 debuga(_(" Useragent log (-b) = %s\n"),uagent
);
657 debuga(_(" Exclude file (-c) = %s\n"),hexclude
);
658 debuga(_(" Date from-until (-d) = %s\n"),date
);
659 debuga(_(" Email address to send reports (-e) = %s\n"),email
);
660 debuga(_(" Config file (-f) = %s\n"),ConfigFile
);
661 if(strcmp(df
,"e") == 0)
662 debuga(_(" Date format (-g) = Europe (dd/mm/yyyy)\n"));
663 if(strcmp(df
,"u") == 0)
664 debuga(_(" Date format (-g) = USA (mm/dd/yyyy)\n"));
665 if(strcmp(df
,"w") == 0)
666 debuga(_(" Date format (-g) = Sites & Users (yyyy/ww)\n"));
667 debuga(_(" IP report (-i) = %s\n"),(iprel
) ? _("Yes") : _("No"));
668 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++)
669 debuga(_(" Input log (-l) = %s\n"),AccessLog
[iarq
]);
670 for (iarq
=0 ; iarq
<NRedirectorLogs
; iarq
++)
671 debuga(_(" Redirector log (-L) = %s\n"),RedirectorLogs
[iarq
]);
672 debuga(_(" Resolve IP Address (-n) = %s\n"),(Ip2Name
) ? _("Yes") : _("No"));
673 debuga(_(" Output dir (-o) = %s\n"),outdir
);
674 debuga(_("Use Ip Address instead of userid (-p) = %s\n"),(UserIp
) ? _("Yes") : _("No"));
675 debuga(_(" Accessed site (-s) = %s\n"),site
);
676 debuga(_(" Time (-t) = %s\n"),hm_str
);
677 debuga(_(" User (-u) = %s\n"),us
);
678 debuga(_(" Temporary dir (-w) = %s\n"),tmp
);
679 debuga(_(" Debug messages (-x) = %s\n"),(debug
) ? _("Yes") : _("No"));
680 debuga(_(" Process messages (-z) = %s\n"),(debugz
) ? _("Yes") : _("No"));
681 debuga(_(" Previous reports to keep (--lastlog) = %d\n"),LastLog
);
686 printf(_("Parameters:\n"));
687 printf(_(" Hostname or IP address (-a) = %s\n"),addr
);
688 printf(_(" Useragent log (-b) = %s\n"),uagent
);
689 printf(_(" Exclude file (-c) = %s\n"),hexclude
);
690 printf(_(" Date from-until (-d) = %s\n"),date
);
691 printf(_(" Email address to send reports (-e) = %s\n"),email
);
692 printf(_(" Config file (-f) = %s\n"),ConfigFile
);
693 if(strcmp(df
,"e") == 0)
694 printf(_(" Date format (-g) = Europe (dd/mm/yyyy)\n"));
695 if(strcmp(df
,"u") == 0)
696 printf(_(" Date format (-g) = USA (mm/dd/yyyy)\n"));
697 if(strcmp(df
,"w") == 0)
698 printf(_(" Date format (-g) = Sites & Users (yyyy/ww)\n"));
699 printf(_(" IP report (-i) = %s\n"),(iprel
) ? _("Yes") : _("No"));
700 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++)
701 printf(_(" Input log (-l) = %s\n"),AccessLog
[iarq
]);
702 for (iarq
=0 ; iarq
<NRedirectorLogs
; iarq
++)
703 printf(_(" Redirector log (-L) = %s\n"),RedirectorLogs
[iarq
]);
704 printf(_(" Resolve IP Address (-n) = %s\n"),(Ip2Name
) ? _("Yes") : _("No"));
705 printf(_(" Output dir (-o) = %s\n"),outdir
);
706 printf(_("Use Ip Address instead of userid (-p) = %s\n"),(UserIp
) ? _("Yes") : _("No"));
707 printf(_(" Accessed site (-s) = %s\n"),site
);
708 printf(_(" Time (-t) = %s\n"),hm_str
);
709 printf(_(" User (-u) = %s\n"),us
);
710 printf(_(" Temporary dir (-w) = %s\n"),tmp
);
711 printf(_(" Debug messages (-x) = %s\n"),(debug
) ? _("Yes") : _("No"));
712 printf(_(" Process messages (-z) = %s\n"),(debugz
) ? _("Yes") : _("No"));
713 printf(_(" Previous reports to keep (--lastlog) = %d\n"),LastLog
);
714 printf(_("sarg version: %s\n"),VERSION
);
718 debuga(_("sarg version: %s\n"),VERSION
);
720 #ifdef ENABLE_DOUBLE_CHECK_DATA
721 debuga(_("Sarg compiled to report warnings if the output is inconsistent\n"));
724 maxopenfiles
=MAX_OPEN_USER_FILES
;
726 if (Ulimit
[0] != '\0') {
731 #if defined(RLIMIT_NOFILE)
732 getrlimit (RLIMIT_NOFILE
, &rl
);
733 #elif defined(RLIMIT_OFILE)
734 getrlimit (RLIMIT_OFILE
, &rl
);
736 #warning "No rlimit resource for the number of open files"
741 rl
.rlim_cur
= atol(Ulimit
);
742 rl
.rlim_max
= atol(Ulimit
);
743 #if defined(RLIMIT_NOFILE)
744 rc
=setrlimit (RLIMIT_NOFILE
, &rl
);
745 #elif defined(RLIMIT_OFILE)
746 rc
=setrlimit (RLIMIT_OFILE
, &rl
);
748 #warning "No rlimit resource for the number of open files"
751 debuga(_("setrlimit error - %s\n"),strerror(errno
));
755 debuga("Maximum file descriptor: cur=%ld max=%ld, changed to cur="RLIM_STRING
" max="RLIM_STRING
,l1
,l2
,rl
.rlim_cur
,rl
.rlim_max
);
759 init_usertab(UserTabFile
);
761 if ((line
=longline_create())==NULL
) {
762 debuga(_("Not enough memory to read a log file\n"));
766 snprintf(sz_Download_Unsort
,sizeof(sz_Download_Unsort
),"%s/download.unsort", tmp
);
768 if(DataFile
[0]=='\0') {
769 if((ReportType
& REPORT_TYPE_DENIED
) != 0) {
770 if((fp_denied
=MY_FOPEN(denied_unsort
,"w"))==NULL
) {
771 debuga(_("(log) Cannot open file: %s - %s\n"),denied_unsort
,strerror(errno
));
776 if((ReportType
& REPORT_TYPE_DENIED
) != 0 || (ReportType
& REPORT_TYPE_AUTH_FAILURES
) != 0) {
777 if((fp_authfail
=MY_FOPEN(authfail_unsort
,"w"))==NULL
) {
778 debuga(_("(log) Cannot open file: %s - %s\n"),authfail_unsort
,strerror(errno
));
784 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++) {
785 strcpy(arq
,AccessLog
[iarq
]);
789 if(strcmp(arq
,"-")==0) {
791 debuga(_("Reading access log file: from stdin\n"));
796 if (stat(arq
,&logstat
)!=0) {
797 debuga(_("Cannot get the modification time of input log file %s (%s). Processing it anyway\n"),arq
,strerror(errno
));
799 struct tm
*logtime
=localtime(&logstat
.st_mtime
);
800 if ((logtime
->tm_year
+1900)*10000+(logtime
->tm_mon
+1)*100+logtime
->tm_mday
<dfrom
) {
801 debuga(_("Ignoring old log file %s\n"),arq
);
806 fp_in
=decomp(arq
,&from_pipe
);
808 debuga(_("(log) Cannot open log file: %s - %s\n"),arq
,strerror(errno
));
811 if(debug
) debuga(_("Reading access log file: %s\n"),arq
);
816 // pre-read the file only if we have to show stats
817 if(ShowReadStatistics
&& !from_stdin
&& !from_pipe
) {
825 while ((nread
=fread(tmp4
,1,sizeof(tmp4
),fp_in
))>0) {
826 for (i
=0 ; i
<nread
; i
++)
828 if (tmp4
[i
]!='\n' && tmp4
[i
]!='\r') {
832 if (tmp4
[i
]=='\n' || tmp4
[i
]=='\r') {
839 printf(_("SARG: Records in file: %lu, reading: %3.2f%%"),recs1
,(float) 0);
844 longline_reset(line
);
846 while ((linebuf
=longline_read(fp_in
,line
))!=NULL
) {
847 blen
=strlen(linebuf
);
849 if (ilf
==ILF_Unknown
) {
850 if(strncmp(linebuf
,"#Software: Mic",14) == 0) {
851 fixendofline(linebuf
);
853 debuga(_("Log is from Microsoft ISA: %s\n"),linebuf
);
859 if(strncmp(linebuf
,"*** SARG Log ***",16) == 0) {
860 if (getperiod_fromsarglog(arqtt
,&period
)<0) {
861 debuga(_("The name of the file is invalid: %s\n"),arq
);
870 if(!fp_log
&& ParsedOutputLog
[0] && ilf
!=ILF_Sarg
) {
871 if(access(ParsedOutputLog
,R_OK
) != 0) {
872 my_mkdir(ParsedOutputLog
);
874 sprintf(arq_log
,"%s/sarg_temp.log",ParsedOutputLog
);
875 if((fp_log
=MY_FOPEN(arq_log
,"w"))==NULL
) {
876 debuga(_("(log) Cannot open log file: %s - %s\n"),arq_log
,strerror(errno
));
879 fputs("*** SARG Log ***\n",fp_log
);
883 if( ShowReadStatistics
&& !from_stdin
&& !from_pipe
&& --OutputNonZero
<=0) {
884 double perc
= recs2
* 100. / recs1
;
885 printf(_("SARG: Records in file: %lu, reading: %3.2lf%%"),recs2
,perc
);
888 OutputNonZero
= REPORT_EVERY_X_LINES
;
890 if(blen
< 58) continue;
891 if(strstr(linebuf
,"HTTP/0.0") != 0) continue;
892 if(strstr(linebuf
,"logfile turned over") != 0) continue;
893 if(linebuf
[0] == ' ') continue;
896 if(ExcludeString
[0] != '\0') {
898 getword_start(&gwarea
,ExcludeString
);
899 while(strchr(gwarea
.current
,':') != 0) {
900 if (getword_multisep(val1
,sizeof(val1
),&gwarea
,':')<0) {
901 debuga(_("Maybe you have a broken record or garbage in your exclusion string\n"));
904 if((str
=(char *) strstr(linebuf
,val1
)) != (char *) NULL
) {
909 if(!exstring
&& (str
=(char *) strstr(linebuf
,gwarea
.current
)) != (char *) NULL
)
911 if(exstring
) continue;
916 printf("BUF=%s\n",linebuf
);
919 if (ilf
==ILF_Squid
|| ilf
==ILF_Common
|| ilf
==ILF_Unknown
) {
920 getword_start(&gwarea
,linebuf
);
921 if (getword(data
,sizeof(data
),&gwarea
,' ')<0) {
922 debuga(_("Maybe you have a broken time in your access.log file\n"));
925 if((str
=(char *) strchr(data
, '.')) != (char *) NULL
&& (str
=(char *) strchr(str
+1, '.')) != (char *) NULL
) {
929 if (getword(user
,sizeof(user
),&gwarea
,' ')<0 || getword_skip(255,&gwarea
,' ')<0) {
930 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
934 if (getword_skip(255,&gwarea
,' ')<0 || getword(user
,sizeof(user
),&gwarea
,' ')<0) {
935 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
939 if (getword(data
,sizeof(data
),&gwarea
,']')<0 || getword_skip(MAXLEN
,&gwarea
,'"')<0 ||
940 getword(fun
,sizeof(fun
),&gwarea
,' ')<0) {
941 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
944 if (getword_ptr(linebuf
,&url
,&gwarea
,' ')<0) {
945 debuga(_("Maybe you have a broken url in your %s file\n"),arq
);
948 if (getword_skip(MAXLEN
,&gwarea
,' ')<0) {
949 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
952 if (getword(code2
,sizeof(code2
),&gwarea
,' ')<0) {
953 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
956 if (getword(tam
,sizeof(tam
),&gwarea
,' ')<0) {
957 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
960 if((str
=(char *) strchr(gwarea
.current
, ' ')) != (char *) NULL
) {
961 if (getword(code
,sizeof(code
),&gwarea
,' ')<0) {
962 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
966 if (getword(code
,sizeof(code
),&gwarea
,'\0')<0) {
967 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
972 if ((str
= strchr(code
, ':')) != NULL
)
975 if(strcmp(tam
,"\0") == 0)
981 getword_start(&gwarea
,data
+1);
982 if (getword_multisep(data
,sizeof(data
),&gwarea
,':')<0){
983 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
986 if (getword_multisep(hora
,sizeof(hora
),&gwarea
,' ')<0){
987 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
990 getword_start(&gwarea
,data
);
991 if (getword_atoll(&iday
,&gwarea
,'/')<0){
992 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
995 if (getword(mes
,sizeof(mes
),&gwarea
,'/')<0){
996 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
999 if (getword_atoll(&iyear
,&gwarea
,'/')<0){
1000 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1004 imonth
=month2num(mes
)+1;
1005 idata
=builddia(iday
,imonth
,iyear
);
1006 computedate(iyear
,imonth
,iday
,&tt
);
1010 if(ilf
==ILF_Unknown
|| ilf
==ILF_Squid
) {
1011 if (getword(elap
,sizeof(elap
),&gwarea
,' ')<0) {
1012 debuga(_("Maybe you have a broken elapsed time in your %s file\n"),arq
);
1015 while(strcmp(elap
,"") == 0 && gwarea
.current
[0] != '\0')
1016 if (getword(elap
,sizeof(elap
),&gwarea
,' ')<0) {
1017 debuga(_("Maybe you have a broken elapsed time in your %s file\n"),arq
);
1020 if(strlen(elap
) < 1) continue;
1021 if (getword(ip
,sizeof(ip
),&gwarea
,' ')<0){
1022 debuga(_("Maybe you have a broken client IP address in your %s file\n"),arq
);
1025 if (getword(code
,sizeof(code
),&gwarea
,' ')<0){
1026 debuga(_("Maybe you have a broken result code in your %s file\n"),arq
);
1029 if (getword(tam
,sizeof(tam
),&gwarea
,' ')<0){
1030 debuga(_("Maybe you have a broken amount of data in your %s file\n"),arq
);
1033 if (getword(fun
,sizeof(fun
),&gwarea
,' ')<0){
1034 debuga(_("Maybe you have a broken request method in your %s file\n"),arq
);
1037 if (getword_ptr(linebuf
,&url
,&gwarea
,' ')<0){
1038 debuga(_("Maybe you have a broken url in your %s file\n"),arq
);
1041 if (getword(user
,sizeof(user
),&gwarea
,' ')<0){
1042 debuga(_("Maybe you have a broken user ID in your %s file\n"),arq
);
1051 debuga(_("Cannot convert the timestamp from the squid log file\n"));
1055 strftime(tbuf2
, sizeof(tbuf2
), "%H%M", t
);
1057 idata
=(t
->tm_year
+1900)*10000+(t
->tm_mon
+1)*100+t
->tm_mday
;
1060 if (ilf
==ILF_Sarg
) {
1061 getword_start(&gwarea
,linebuf
);
1062 if (getword(data
,sizeof(data
),&gwarea
,'\t')<0){
1063 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1066 if (getword(hora
,sizeof(hora
),&gwarea
,'\t')<0) {
1067 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1070 if (getword(user
,sizeof(user
),&gwarea
,'\t')<0) {
1071 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1074 if (getword(ip
,sizeof(ip
),&gwarea
,'\t')<0) {
1075 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1078 if (getword_ptr(linebuf
,&url
,&gwarea
,'\t')<0){
1079 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1082 if (getword(tam
,sizeof(tam
),&gwarea
,'\t')<0){
1083 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1086 if (getword(code
,sizeof(code
),&gwarea
,'\t')<0){
1087 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1090 if (getword(elap
,sizeof(elap
),&gwarea
,'\t')<0){
1091 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1094 if (getword(smartfilter
,sizeof(smartfilter
),&gwarea
,'\0')<0){
1095 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1098 getword_start(&gwarea
,data
);
1099 if (getword_atoll(&iday
,&gwarea
,'/')<0 || iday
<1 || iday
>31){
1100 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1103 if (getword_atoll(&imonth
,&gwarea
,'/')<0 || imonth
<1 || imonth
>12){
1104 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1107 if (getword_atoll(&iyear
,&gwarea
,'\0')<0){
1108 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1111 idata
=builddia(iday
,imonth
,iyear
);
1112 computedate(iyear
,imonth
,iday
,&tt
);
1113 if (sscanf(hora
,"%d:%d:%d",&tt
.tm_hour
,&tt
.tm_min
,&tt
.tm_sec
)!=3 || tt
.tm_hour
<0 || tt
.tm_hour
>=24 ||
1114 tt
.tm_min
<0 || tt
.tm_min
>=60 || tt
.tm_sec
<0 || tt
.tm_sec
>=60) {
1115 debuga(_("Invalid time found in %s\n"),arq
);
1121 if (linebuf
[0] == '#') {
1122 int ncols
,cols
[ISACOL_Last
];
1124 fixendofline(linebuf
);
1125 getword_start(&gwarea
,linebuf
);
1126 // remove the #Fields: column at the beginning of the line
1127 if (getword_skip(1000,&gwarea
,' ')<0){
1128 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1131 for (ncols
=0 ; ncols
<ISACOL_Last
; ncols
++) cols
[ncols
]=-1;
1133 while(gwarea
.current
[0] != '\0') {
1134 if (getword(val1
,sizeof(val1
),&gwarea
,'\t')<0){
1135 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1138 if(strcmp(val1
,"c-ip") == 0) cols
[ISACOL_Ip
]=ncols
;
1139 if(strcmp(val1
,"cs-username") == 0) cols
[ISACOL_UserName
]=ncols
;
1140 if(strcmp(val1
,"date") == 0) cols
[ISACOL_Date
]=ncols
;
1141 if(strcmp(val1
,"time") == 0) cols
[ISACOL_Time
]=ncols
;
1142 if(strcmp(val1
,"time-taken") == 0) cols
[ISACOL_TimeTaken
]=ncols
;
1143 if(strcmp(val1
,"sc-bytes") == 0) cols
[ISACOL_Bytes
]=ncols
;
1144 if(strcmp(val1
,"cs-uri") == 0) cols
[ISACOL_Uri
]=ncols
;
1145 if(strcmp(val1
,"sc-status") == 0) cols
[ISACOL_Status
]=ncols
;
1148 if (cols
[ISACOL_Ip
]>=0) {
1150 for (ncols
=0 ; ncols
<ISACOL_Last
; ncols
++)
1151 isa_cols
[ncols
]=cols
[ncols
];
1155 if (!isa_ncols
) continue;
1156 getword_start(&gwarea
,linebuf
);
1157 for (x
=0 ; x
<isa_ncols
; x
++) {
1158 if (getword_ptr(linebuf
,&str
,&gwarea
,'\t')<0) {
1159 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1162 if (x
==isa_cols
[ISACOL_Ip
]) {
1163 if (strlen(str
)>=sizeof(ip
)) {
1164 debuga(_("Maybe you have a broken IP in your %s file\n"),arq
);
1168 } else if (x
==isa_cols
[ISACOL_UserName
]) {
1169 if (strlen(str
)>=sizeof(user
)) {
1170 debuga(_("Maybe you have a broken user ID in your %s file\n"),arq
);
1174 } else if (x
==isa_cols
[ISACOL_Date
]) {
1175 if (strlen(str
)>=sizeof(data
)) {
1176 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1180 } else if (x
==isa_cols
[ISACOL_Time
]) {
1181 if (strlen(str
)>=sizeof(hora
)) {
1182 debuga(_("Maybe you have a broken time in your %s file\n"),arq
);
1186 } else if (x
==isa_cols
[ISACOL_TimeTaken
]) {
1187 if (strlen(str
)>=sizeof(elap
)) {
1188 debuga(_("Maybe you have a broken download duration in your %s file\n"),arq
);
1192 } else if (x
==isa_cols
[ISACOL_Bytes
]) {
1193 if (strlen(str
)>=sizeof(tam
)) {
1194 debuga(_("Maybe you have a broken download size in your %s file\n"),arq
);
1198 } else if (x
==isa_cols
[ISACOL_Uri
]) {
1200 } else if (x
==isa_cols
[ISACOL_Status
]) {
1201 if (strlen(str
)>=sizeof(code
)) {
1202 debuga(_("Maybe you have a broken access code in your %s file\n"),arq
);
1209 if(strcmp(code
,"401") == 0 || strcmp(code
,"403") == 0 || strcmp(code
,"407") == 0) {
1210 sprintf(val1
,"DENIED/%s",code
);
1213 getword_start(&gwarea
,data
);
1214 if (getword_atoll(&iyear
,&gwarea
,'-')<0){
1215 debuga(_("Maybe you have a broken year in your %s file\n"),arq
);
1218 if (getword_atoll(&imonth
,&gwarea
,'-')<0){
1219 debuga(_("Maybe you have a broken month in your %s file\n"),arq
);
1222 if (getword_atoll(&iday
,&gwarea
,'\0')<0){
1223 debuga(_("Maybe you have a broken day in your %s file\n"),arq
);
1227 idata
=builddia(iday
,imonth
,iyear
);
1228 computedate(iyear
,imonth
,iday
,&tt
);
1229 if (isa_cols
[ISACOL_Time
]>=0) {
1230 if (sscanf(hora
,"%d:%d:%d",&tt
.tm_hour
,&tt
.tm_min
,&tt
.tm_sec
)!=3 || tt
.tm_hour
<0 || tt
.tm_hour
>=24 ||
1231 tt
.tm_min
<0 || tt
.tm_min
>=60 || tt
.tm_sec
<0 || tt
.tm_sec
>=60) {
1232 debuga(_("Invalid time found in %s\n"),arq
);
1239 debuga(_("Unknown input log file format\n"));
1243 strftime(dia
, sizeof(dia
), "%d/%m/%Y", t
);
1244 snprintf(hora
,sizeof(hora
),"%02d:%02d:%02d",t
->tm_hour
,t
->tm_min
,t
->tm_sec
);
1247 printf("DATE=%s IDATA=%d DFROM=%d DUNTIL=%d\n",date
,idata
,dfrom
,duntil
);
1249 if(date
[0] != '\0'){
1250 if(idata
< dfrom
|| idata
> duntil
) continue;
1253 // Record only hours usage which is required
1255 if( bsearch( &( t
-> tm_wday
), weekdays
.list
, weekdays
.len
, sizeof( int ), compar
) == NULL
)
1258 if( bsearch( &( t
-> tm_hour
), hours
.list
, hours
.len
, sizeof( int ), compar
) == NULL
)
1263 if(strlen(user
) > MAX_USER_LEN
) {
1264 if (debugm
) printf(_("User ID too long: %s\n"),user
);
1270 if(IncludeUsers
[0] != '\0') {
1271 sprintf(val1
,":%s:",user
);
1272 if((str
=(char *) strstr(IncludeUsers
,val1
)) == (char *) NULL
)
1277 if (debugm
) printf(_("Excluded code: %s\n"),code
);
1282 if(testvaliduserchar(user
))
1286 if((str
= strstr(user
,"%20")) != NULL
) {
1288 This is a patch introduced to solve bug #1624251 reported at sourceforge but
1289 the side effect is to truncate the name at the first space and merge the reports
1290 of people whose name is identical up to the first space.
1292 The old code used to truncate the user name at the first % if a %20 was
1293 found anywhere in the string. That means the string could be truncated
1294 at the wrong place if another % occured before the %20. This new code should
1295 avoid that problem and only truncate at the space. There is no bug
1296 report indicating that anybody noticed this.
1302 Code prior to 2.2.7 used to replace any %xx by a dot as long as a %5c was
1303 found in the user name.
1305 while((str
= strstr(user
,"%5c")) != NULL
) {
1307 for (x
=3 ; str
[x
] ; x
++) str
[x
-2]=str
[x
];
1315 The full URL is not saved in sarg log. There is no point in testing the URL to detect
1318 download_flag
=is_download_suffix(url
);
1319 if (download_flag
) {
1324 download_flag
=false;
1326 // remove any protocol:// at the beginning of the URL
1327 if ((str
= strchr(url
,'/')) != NULL
&& str
[1] == '/') {
1331 for (i
=0 ; str
[i
] ; i
++)
1337 url_hostname(url
,hostname
,sizeof(hostname
));
1341 if(url
[0] == '\0') continue;
1343 if(addr
[0] != '\0'){
1344 if(strcmp(addr
,ip
)!=0) continue;
1347 if(!vhexclude(url
)) {
1348 if (debugm
) printf(_("Excluded site: %s\n"),url
);
1354 if(hm
>= 0 && hmf
>= 0) {
1355 hmr
=t
->tm_hour
*100+t
->tm_min
;
1356 if(hmr
< hm
|| hmr
> hmf
) continue;
1359 if(site
[0] != '\0'){
1360 if(strstr(url
,site
)==0) continue;
1368 if(strcmp(user
,"-") == 0 || strcmp(user
," ") == 0 || strcmp(user
,"") == 0) {
1369 if(RecordsWithoutUser
== RECORDWITHOUTUSER_IP
) {
1373 if(RecordsWithoutUser
== RECORDWITHOUTUSER_IGNORE
)
1375 if(RecordsWithoutUser
== RECORDWITHOUTUSER_EVERYBODY
)
1376 strcpy(user
,"everybody");
1379 if(NtlmUserFormat
== NTLMUSERFORMAT_USER
) {
1380 if((str
= strchr(user
,'_')) != 0) {
1381 strcpy(warea
,str
+1);
1384 if((str
= strchr(user
,'+')) != 0) {
1385 strcpy(warea
,str
+1);
1393 if(strcmp(user
,us
)!=0) continue;
1397 sprintf(wuser
,":%s:",user
);
1398 if(strstr(userfile
, wuser
) == 0)
1403 if(!vuexclude(user
)) {
1404 if (debugm
) printf(_("Excluded user: %s\n"),user
);
1410 if(strcmp(user
,"-") ==0 || strcmp(user
," ") ==0 || strcmp(user
,"") ==0 || strcmp(user
,":") ==0)
1414 if(atol(elap
)>max_elapsed
) {
1420 if((str
=(char *) strstr(linebuf
, "[SmartFilter:")) != (char *) NULL
) {
1422 sprintf(smartfilter
,"\"%s\"",str
+1);
1423 } else sprintf(smartfilter
,"\"\"");
1427 for (ufile
=first_user_file
; ufile
&& strcmp(user
,ufile
->user
->id
)!=0 ; ufile
=ufile
->next
) {
1429 if (ufile
->file
) nopen
++;
1432 ufile
=malloc(sizeof(*ufile
));
1434 debuga(_("Not enough memory to store the user %s\n"),user
);
1437 memset(ufile
,0,sizeof(*ufile
));
1438 ufile
->next
=first_user_file
;
1439 first_user_file
=ufile
;
1440 uinfo
=userinfo_create(user
);
1442 uinfo
->id_is_ip
=id_is_ip
;
1445 prev_ufile
->next
=ufile
->next
;
1446 ufile
->next
=first_user_file
;
1447 first_user_file
=ufile
;
1451 if (ufile
->file
==NULL
) {
1452 if (nopen
>=maxopenfiles
) {
1454 for (ufile1
=first_user_file
; ufile1
; ufile1
=ufile1
->next
) {
1455 if (ufile1
->file
!=NULL
) {
1456 if (x
>=maxopenfiles
) {
1457 if (fclose(ufile1
->file
)==EOF
) {
1458 debuga(_("Failed to close the log file of user %s - %s\n"),ufile1
->user
->id
,strerror(errno
));
1467 if (snprintf (tmp3
, sizeof(tmp3
), "%s/%s.unsort", tmp
, ufile
->user
->filename
)>=sizeof(tmp3
)) {
1468 debuga(_("Temporary user file name too long: %s/%s.unsort\n"), tmp
, ufile
->user
->filename
);
1471 if ((ufile
->file
= MY_FOPEN (tmp3
, "a")) == NULL
) {
1472 debuga(_("(log) Cannot open temporary file: %s - %s\n"), tmp3
, strerror(errno
));
1477 /*if ( strcmp ( user , sz_Last_User ) != 0 ) {
1478 if ( fp_Write_User )
1479 fclose( fp_Write_User ) ;
1480 sprintf (tmp3, "%s/%s.unsort", tmp, user);
1482 if ((fp_Write_User = MY_FOPEN (tmp3, "a")) == NULL) {
1483 fprintf (stderr, "%s: (log) %s: %s - %s\n", argv[0], _("Cannot open temporary file"), tmp3, strerror(errno));
1486 strcpy( sz_Last_User , user ) ;
1488 if (fprintf(ufile
->file
, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",dia
,hora
,ip
,url
,tam
,code
,elap
,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%s\t%s\t%s\t%s\n",dia
,hora
,user
,ip
,url
,tam
,code
,elap
,smartfilter
);
1498 if(!dataonly
&& download_flag
&& download_url
&& 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 || (ReportType
& REPORT_TYPE_AUTH_FAILURES
) != 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
,urly
);
1515 if(fp_authfail
&& (strstr(code
,"DENIED/401") != 0 || strstr(code
,"DENIED/407") != 0)) {
1516 fprintf(fp_authfail
, "%s\t%s\t%s\t%s\t%s\n",dia
,hora
,user
,ip
,urly
);
1521 if (ilf
!=ILF_Sarg
) {
1522 if(!totper
|| idata
<mindate
){
1524 memcpy(&period
.start
,t
,sizeof(*t
));
1525 strcpy(start_hour
,tbuf2
);
1527 if (!totper
|| idata
>maxdate
) {
1529 memcpy(&period
.end
,t
,sizeof(*t
));
1535 printf("IP=\t%s\n",ip
);
1536 printf("USER=\t%s\n",user
);
1537 printf("ELAP=\t%s\n",elap
);
1538 printf("DATE=\t%s\n",dia
);
1539 printf("TIME=\t%s\n",hora
);
1540 printf("FUNC=\t%s\n",fun
);
1541 printf("URL=\t%s\n",url
);
1542 printf("CODE=\t%s\n",code
);
1543 printf("LEN=\t%s\n",tam
);
1551 if( ShowReadStatistics
)
1552 printf(_("SARG: Records in file: %lu, reading: %3.2f%%\n"),recs1
, (float) 100 );
1558 debuga(_(" Records read: %ld, written: %ld, excluded: %ld\n"),totregsl
,totregsg
,totregsx
);
1560 longline_destroy(&line
);
1561 if ( fp_Download_Unsort
)
1562 fclose (fp_Download_Unsort
);
1564 for (ufile
=first_user_file
; ufile
; ufile
=ufile1
) {
1566 if (ufile
->file
!=NULL
) fclose(ufile
->file
);
1571 free_excludecodes();
1577 for (ilf
=0 ; ilf
<ILF_Last
; ilf
++) totalcount
+=ilf_count
[ilf
];
1579 if(ilf_count
[ILF_Common
]>0 && ilf_count
[ILF_Squid
]>0)
1580 debuga(_("Log with mixed records format (squid and common log)\n"));
1582 if(ilf_count
[ILF_Common
]>0 && ilf_count
[ILF_Squid
]==0)
1583 debuga(_("Common log format\n"));
1585 if(ilf_count
[ILF_Common
]==0 && ilf_count
[ILF_Squid
]>0)
1586 debuga(_("Squid log format\n"));
1588 if(ilf_count
[ILF_Sarg
]>0)
1589 debuga(_("Sarg log format\n"));
1591 if(totalcount
==0 && totregsg
)
1592 debuga(_("Log with invalid format\n"));
1596 debuga(_("No records found\n"));
1598 if(fp_denied
) fclose(fp_denied
);
1599 if(fp_authfail
) fclose(fp_authfail
);
1601 if(userfile
) free(userfile
);
1606 if (date
[0]!='\0') {
1607 char date0
[30], date1
[30];
1609 strftime(date0
,sizeof(date0
),"%d/%m/%Y",&period
.start
);
1610 strftime(date1
,sizeof(date1
),"%d/%m/%Y",&period
.end
);
1611 debuga(_("Period covered by log files: %s-%s\n"),date0
,date1
);
1612 getperiod_fromrange(&period
,dfrom
,duntil
);
1614 if (getperiod_buildtext(&period
)<0) {
1615 debuga(_("Failed to build the string representation of the date range\n"));
1620 debugaz("data",dia
);
1621 debugaz("period",period
.text
);
1625 debuga(_("Period: %s\n"),period
.text
);
1630 fclose(fp_authfail
);
1632 if(fp_log
!= NULL
) {
1634 strcpy(end_hour
,tbuf2
);
1635 strftime(val2
,sizeof(val2
),"%d%m%Y",&period
.start
);
1636 strftime(val1
,sizeof(val1
),"%d%m%Y",&period
.end
);
1637 sprintf(val4
,"%s/sarg-%s_%s-%s_%s.log",ParsedOutputLog
,val2
,start_hour
,val1
,end_hour
);
1638 if (rename(arq_log
,val4
)) {
1639 debuga(_("failed to rename %s to %s - %s\n"),arq_log
,val4
,strerror(errno
));
1641 strcpy(arq_log
,val4
);
1643 if(strcmp(ParsedOutputLogCompress
,"nocompress") != 0 && ParsedOutputLogCompress
[0] != '\0') {
1645 No double quotes around ParsedOutputLogCompress because it may contain command line options. If double quotes are
1646 necessary around the command name, put them in the configuration file.
1648 sprintf(val1
,"%s \"%s\"",ParsedOutputLogCompress
,arq_log
);
1649 cstatus
=system(val1
);
1650 if (!WIFEXITED(cstatus
) || WEXITSTATUS(cstatus
)) {
1651 debuga(_("command return status %d\n"),WEXITSTATUS(cstatus
));
1652 debuga(_("command: %s\n"),val1
);
1658 debuga(_("Sarg parsed log saved as %s\n"),arq_log
);
1661 if(DataFile
[0] == '\0' && (ReportType
& REPORT_TYPE_DENIED
) != 0) {
1662 sprintf(csort
,"sort -T \"%s\" -k 3,3 -k 5,5 -o \"%s\" \"%s\"",tmp
,denied_sort
,denied_unsort
);
1663 cstatus
=system(csort
);
1664 if (!WIFEXITED(cstatus
) || WEXITSTATUS(cstatus
)) {
1665 debuga(_("sort command return status %d\n"),WEXITSTATUS(cstatus
));
1666 debuga(_("sort command: %s\n"),csort
);
1669 if (unlink(denied_unsort
)) {
1670 debuga(_("Cannot delete %s - %s\n"),denied_unsort
,strerror(errno
));
1675 sort_users_log(tmp
, debug
);
1677 if(DataFile
[0] != '\0')
1682 if((ReportType
& REPORT_TYPE_DENIED
) != 0) {
1683 unlink(denied_sort
);
1686 if(strcmp(tmp
,"/tmp") != 0) {
1702 static void getusers(const char *pwdfile
, int debug
)
1710 debuga(_("Loading password file from %s\n"),pwdfile
);
1712 if ((fp_usr
= fopen(pwdfile
, "r")) == NULL
) {
1713 debuga(_("(getusers) Cannot open file %s - %s\n"),pwdfile
,strerror(errno
));
1717 if (fseek(fp_usr
, 0, SEEK_END
)==-1) {
1718 debuga(_("Failed to move till the end of the users file %s: %s\n"),pwdfile
,strerror(errno
));
1721 nreg
= ftell(fp_usr
);
1723 debuga(_("Cannot get the size of file %s\n"),pwdfile
);
1727 if (fseek(fp_usr
, 0, SEEK_SET
)==-1) {
1728 debuga(_("Failed to rewind the users file %s: %s\n"),pwdfile
,strerror(errno
));
1732 if((userfile
=(char *) malloc(nreg
))==NULL
){
1733 debuga(_("malloc error (%ld)\n"),nreg
);
1737 bzero(userfile
,nreg
);
1738 strcpy(userfile
,":");
1740 while(fgets(buf
,sizeof(buf
),fp_usr
)!=NULL
) {
1741 str
=strchr(buf
,':');
1743 debuga(_("You have an invalid user in your %s file\n"),pwdfile
);
1747 strcat(userfile
,buf
);