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 {"lastlog",required_argument
,NULL
,2},
166 {"keeplogs",no_argument
,NULL
,3},
167 {"split",no_argument
,&split
,1},
168 {"splitprefix",required_argument
,NULL
,'P'},
173 setlocale(LC_TIME
,"");
176 #if defined(ENABLE_NLS) && defined(HAVE_LOCALE_H)
177 if (!setlocale (LC_ALL
, "")) {
178 fprintf(stderr
,"SARG: Cannot set the locale LC_ALL to the environment variable\n");
181 if (!bindtextdomain (PACKAGE_NAME
, LOCALEDIR
)) {
182 fprintf(stderr
,"SARG: Cannot bind to text domain %s in directory %s (%s)\n",PACKAGE_NAME
,LOCALEDIR
,strerror(errno
));
185 if (!textdomain (PACKAGE_NAME
)) {
186 fprintf(stderr
,"SARG: Cannot set gettext domain for %s PACKAGE_NAME (%s)\n",PACKAGE_NAME
,strerror(errno
));
196 UserAgentLog
[0]='\0';
197 ExcludeHosts
[0]='\0';
198 ExcludeUsers
[0]='\0';
205 ExternalCSSFile
[0]='\0';
206 RedirectorLogFormat
[0]='\0';
208 for (ilf
=0 ; ilf
<ILF_Last
; ilf
++) ilf_count
[ilf
]=0;
210 snprintf(ExcludeCodes
,sizeof(ExcludeCodes
),"%s/exclude_codes",SYSCONFDIR
);
211 strcpy(GraphDaysBytesBarColor
,"orange");
212 strcpy(BgColor
,"#ffffff");
213 strcpy(TxColor
,"#000000");
214 strcpy(TxBgColor
,"lavender");
215 strcpy(TiColor
,"darkblue");
218 strcpy(LogoTextColor
,"#000000");
219 strcpy(HeaderColor
,"darkblue");
220 strcpy(HeaderBgColor
,"#dddddd");
221 strcpy(LogoTextColor
,"#006699");
222 strcpy(FontSize
,"9px");
223 strcpy(TempDir
,"/tmp");
224 strcpy(OutputDir
,"/var/www/html/squid-reports");
225 AnonymousOutputFiles
=false;
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");
316 UserInvalidChar
[0]='\0';
318 SquidGuardConf
[0]='\0';
319 DansGuardianConf
[0]='\0';
322 HostAliasFile
[0]='\0';
327 dansguardian_count
=0;
330 DeniedReportLimit
=10;
331 AuthfailReportLimit
=10;
332 DansGuardianReportLimit
=10;
333 SquidGuardReportLimit
=10;
334 DownloadReportLimit
=50;
343 realtime_access_log_lines
=1000;
351 bzero(IncludeUsers
, sizeof(IncludeUsers
));
352 bzero(ExcludeString
, sizeof(ExcludeString
));
353 first_user_file
=NULL
;
354 memset(&period
,0,sizeof(period
));
357 for(x
=0; x
<MAXLOGS
; x
++)
358 AccessLog
[x
][0]='\0';
359 AccessLogFromCmdLine
=0;
360 RedirectorLogFromCmdLine
=0;
362 strcpy(Title
,_("Squid User Access Report"));
364 while((ch
= getopt_long_only(argc
, argv
, "a:b:c:d:e:f:g:u:l:L:o:s:t:w:P:hijmnprvxyz",long_options
,&option_index
)) != -1){
370 lastlog
=atoi(optarg
);
376 safe_strcpy(addr
,optarg
,sizeof(addr
));
379 safe_strcpy(uagent
,optarg
,sizeof(uagent
));
382 safe_strcpy(hexclude
,optarg
,sizeof(hexclude
));
385 safe_strcpy(date
,optarg
,sizeof(date
));
386 date_from(date
, &dfrom
, &duntil
);
389 safe_strcpy(email
,optarg
,sizeof(email
));
392 safe_strcpy(ConfigFile
,optarg
,sizeof(ConfigFile
));
395 safe_strcpy(df
,optarg
,sizeof(df
));
404 if (NAccessLog
>=MAXLOGS
) {
405 debuga(_("Too many log files passed on command line with option -l.\n"));
408 if (strlen(optarg
)>=MAX_LOG_FILELEN
) {
409 debuga(_("Log file name too long passed on command line with option -l: %s\n"),optarg
);
412 strcpy(AccessLog
[NAccessLog
],optarg
);
414 AccessLogFromCmdLine
++;
417 if (NRedirectorLogs
>MAX_REDIRECTOR_LOGS
) {
418 debuga(_("Too many redirector logs passed on command line with option -L.\n"));
421 if (strlen(optarg
)>=MAX_REDIRECTOR_FILELEN
) {
422 debuga(_("Redirector log file name too long passed on command line with opton -L: %s\n"),optarg
);
425 strcpy(RedirectorLogs
[NRedirectorLogs
],optarg
);
427 RedirectorLogFromCmdLine
++;
436 safe_strcpy(outdir
,optarg
,sizeof(outdir
));
442 safe_strcpy(splitprefix
,optarg
,sizeof(splitprefix
));
448 safe_strcpy(site
,optarg
,sizeof(site
));
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
);
474 safe_strcpy(us
,optarg
,sizeof(us
));
480 safe_strcpy(tmp
,optarg
,sizeof(tmp
));
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_forcedns();
538 if (lastlog
>=0) LastLog
=lastlog
;
540 if(outdir
[0] == '\0') strcpy(outdir
,OutputDir
);
541 if(outdir
[0] != '\0') strcat(outdir
,"/");
548 if(IndexTree
== INDEX_TREE_FILE
)
549 strcpy(ImageFile
,"../images");
551 strcpy(ImageFile
,"../../../images");
554 if(DataFile
[0] != '\0')
557 if(df
[0] == '\0') strcpy(df
,DateFormat
);
558 else strcpy(DateFormat
,df
);
562 strcpy(DateFormat
,"u");
565 IndexTree
=INDEX_TREE_FILE
;
567 if(NAccessLog
== 0) {
568 strcpy(AccessLog
[0],"/var/log/squid/access.log");
577 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++)
578 splitlog(AccessLog
[iarq
], df
, dfrom
, duntil
, convert
, splitprefix
);
582 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++)
583 convlog(AccessLog
[iarq
], df
, dfrom
, duntil
);
587 load_excludecodes(ExcludeCodes
);
589 if(access(PasswdFile
, R_OK
) == 0) {
590 getusers(PasswdFile
,debug
);
594 if(hexclude
[0] == '\0')
595 strcpy(hexclude
,ExcludeHosts
);
596 if(hexclude
[0] != '\0') {
597 gethexclude(hexclude
,debug
);
601 if(ReportType
== 0) {
602 ReportType
=REPORT_TYPE_TOPUSERS
| REPORT_TYPE_TOPSITES
| REPORT_TYPE_USERS_SITES
|
603 REPORT_TYPE_SITES_USERS
| REPORT_TYPE_DATE_TIME
| REPORT_TYPE_DENIED
|
604 REPORT_TYPE_AUTH_FAILURES
| REPORT_TYPE_SITE_USER_TIME_DATE
| REPORT_TYPE_DOWNLOADS
;
607 if(access(ExcludeUsers
, R_OK
) == 0) {
608 getuexclude(ExcludeUsers
,debug
);
611 if (HostAliasFile
[0] != '\0')
612 read_hostalias(HostAliasFile
);
619 if(strcmp(ExcludeUsers
,"indexonly") == 0) indexonly
=true;
620 if(Index
== INDEX_ONLY
) indexonly
=true;
622 if(MaxElapsed
[0] != '\0') max_elapsed
=atol(MaxElapsed
);
624 if(uagent
[0] == '\0') strcpy(uagent
,UserAgentLog
);
626 if(tmp
[0] == '\0') strcpy(tmp
,TempDir
);
627 else strcpy(TempDir
,tmp
);
629 For historical reasons, the temporary directory is the subdirectory "sarg" of the path
630 provided by the user.
634 if (tmp
[0]!='\0' && strncmp(outdir
,tmp
,strlen(tmp
))==0) {
635 debuga(_("The output directory \"%s\" must be outside of the temporary directory \"%s\"\n"),outdir
,tmp
);
639 if(email
[0] == '\0' && OutputEmail
[0] != '\0') strcpy(email
,OutputEmail
);
641 if(email
[0] != '\0') {
647 if(access(tmp
, R_OK
) == 0) {
648 if (debug
) debuga(_("Deleting directory %s\n"),tmp
);
652 snprintf(denied_unsort
,sizeof(denied_unsort
),"%s/denied.int_unsort",tmp
);
653 snprintf(denied_sort
,sizeof(denied_sort
),"%s/denied.int_log",tmp
);
654 snprintf(authfail_unsort
,sizeof(authfail_unsort
),"%s/authfail.int_unsort",tmp
);
657 debuga(_("Parameters:\n"));
658 debuga(_(" Hostname or IP address (-a) = %s\n"),addr
);
659 debuga(_(" Useragent log (-b) = %s\n"),uagent
);
660 debuga(_(" Exclude file (-c) = %s\n"),hexclude
);
661 debuga(_(" Date from-until (-d) = %s\n"),date
);
662 debuga(_(" Email address to send reports (-e) = %s\n"),email
);
663 debuga(_(" Config file (-f) = %s\n"),ConfigFile
);
664 if(strcmp(df
,"e") == 0)
665 debuga(_(" Date format (-g) = Europe (dd/mm/yyyy)\n"));
666 if(strcmp(df
,"u") == 0)
667 debuga(_(" Date format (-g) = USA (mm/dd/yyyy)\n"));
668 if(strcmp(df
,"w") == 0)
669 debuga(_(" Date format (-g) = Sites & Users (yyyy/ww)\n"));
670 debuga(_(" IP report (-i) = %s\n"),(iprel
) ? _("Yes") : _("No"));
671 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++)
672 debuga(_(" Input log (-l) = %s\n"),AccessLog
[iarq
]);
673 for (iarq
=0 ; iarq
<NRedirectorLogs
; iarq
++)
674 debuga(_(" Redirector log (-L) = %s\n"),RedirectorLogs
[iarq
]);
675 debuga(_(" Resolve IP Address (-n) = %s\n"),(Ip2Name
) ? _("Yes") : _("No"));
676 debuga(_(" Output dir (-o) = %s\n"),outdir
);
677 debuga(_("Use Ip Address instead of userid (-p) = %s\n"),(UserIp
) ? _("Yes") : _("No"));
678 debuga(_(" Accessed site (-s) = %s\n"),site
);
679 debuga(_(" Time (-t) = %s\n"),hm_str
);
680 debuga(_(" User (-u) = %s\n"),us
);
681 debuga(_(" Temporary dir (-w) = %s\n"),tmp
);
682 debuga(_(" Debug messages (-x) = %s\n"),(debug
) ? _("Yes") : _("No"));
683 debuga(_(" Process messages (-z) = %s\n"),(debugz
) ? _("Yes") : _("No"));
684 debuga(_(" Previous reports to keep (--lastlog) = %d\n"),LastLog
);
689 printf(_("Parameters:\n"));
690 printf(_(" Hostname or IP address (-a) = %s\n"),addr
);
691 printf(_(" Useragent log (-b) = %s\n"),uagent
);
692 printf(_(" Exclude file (-c) = %s\n"),hexclude
);
693 printf(_(" Date from-until (-d) = %s\n"),date
);
694 printf(_(" Email address to send reports (-e) = %s\n"),email
);
695 printf(_(" Config file (-f) = %s\n"),ConfigFile
);
696 if(strcmp(df
,"e") == 0)
697 printf(_(" Date format (-g) = Europe (dd/mm/yyyy)\n"));
698 if(strcmp(df
,"u") == 0)
699 printf(_(" Date format (-g) = USA (mm/dd/yyyy)\n"));
700 if(strcmp(df
,"w") == 0)
701 printf(_(" Date format (-g) = Sites & Users (yyyy/ww)\n"));
702 printf(_(" IP report (-i) = %s\n"),(iprel
) ? _("Yes") : _("No"));
703 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++)
704 printf(_(" Input log (-l) = %s\n"),AccessLog
[iarq
]);
705 for (iarq
=0 ; iarq
<NRedirectorLogs
; iarq
++)
706 printf(_(" Redirector log (-L) = %s\n"),RedirectorLogs
[iarq
]);
707 printf(_(" Resolve IP Address (-n) = %s\n"),(Ip2Name
) ? _("Yes") : _("No"));
708 printf(_(" Output dir (-o) = %s\n"),outdir
);
709 printf(_("Use Ip Address instead of userid (-p) = %s\n"),(UserIp
) ? _("Yes") : _("No"));
710 printf(_(" Accessed site (-s) = %s\n"),site
);
711 printf(_(" Time (-t) = %s\n"),hm_str
);
712 printf(_(" User (-u) = %s\n"),us
);
713 printf(_(" Temporary dir (-w) = %s\n"),tmp
);
714 printf(_(" Debug messages (-x) = %s\n"),(debug
) ? _("Yes") : _("No"));
715 printf(_(" Process messages (-z) = %s\n"),(debugz
) ? _("Yes") : _("No"));
716 printf(_(" Previous reports to keep (--lastlog) = %d\n"),LastLog
);
717 printf(_("sarg version: %s\n"),VERSION
);
721 debuga(_("sarg version: %s\n"),VERSION
);
723 #ifdef ENABLE_DOUBLE_CHECK_DATA
724 debuga(_("Sarg compiled to report warnings if the output is inconsistent\n"));
727 maxopenfiles
=MAX_OPEN_USER_FILES
;
729 if (Ulimit
[0] != '\0') {
734 #if defined(RLIMIT_NOFILE)
735 getrlimit (RLIMIT_NOFILE
, &rl
);
736 #elif defined(RLIMIT_OFILE)
737 getrlimit (RLIMIT_OFILE
, &rl
);
739 #warning "No rlimit resource for the number of open files"
744 rl
.rlim_cur
= atol(Ulimit
);
745 rl
.rlim_max
= atol(Ulimit
);
746 #if defined(RLIMIT_NOFILE)
747 rc
=setrlimit (RLIMIT_NOFILE
, &rl
);
748 #elif defined(RLIMIT_OFILE)
749 rc
=setrlimit (RLIMIT_OFILE
, &rl
);
751 #warning "No rlimit resource for the number of open files"
754 debuga(_("setrlimit error - %s\n"),strerror(errno
));
758 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
);
762 init_usertab(UserTabFile
);
764 if ((line
=longline_create())==NULL
) {
765 debuga(_("Not enough memory to read a log file\n"));
769 snprintf(sz_Download_Unsort
,sizeof(sz_Download_Unsort
),"%s/download.int_unsort", tmp
);
771 if(DataFile
[0]=='\0') {
772 if((ReportType
& REPORT_TYPE_DENIED
) != 0) {
773 if((fp_denied
=MY_FOPEN(denied_unsort
,"w"))==NULL
) {
774 debuga(_("(log) Cannot open file: %s - %s\n"),denied_unsort
,strerror(errno
));
779 if((ReportType
& REPORT_TYPE_DENIED
) != 0 || (ReportType
& REPORT_TYPE_AUTH_FAILURES
) != 0) {
780 if((fp_authfail
=MY_FOPEN(authfail_unsort
,"w"))==NULL
) {
781 debuga(_("(log) Cannot open file: %s - %s\n"),authfail_unsort
,strerror(errno
));
787 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++) {
788 strcpy(arq
,AccessLog
[iarq
]);
792 if(strcmp(arq
,"-")==0) {
794 debuga(_("Reading access log file: from stdin\n"));
799 if (stat(arq
,&logstat
)!=0) {
800 debuga(_("Cannot get the modification time of input log file %s (%s). Processing it anyway\n"),arq
,strerror(errno
));
802 struct tm
*logtime
=localtime(&logstat
.st_mtime
);
803 if ((logtime
->tm_year
+1900)*10000+(logtime
->tm_mon
+1)*100+logtime
->tm_mday
<dfrom
) {
804 debuga(_("Ignoring old log file %s\n"),arq
);
809 fp_in
=decomp(arq
,&from_pipe
);
811 debuga(_("(log) Cannot open log file: %s - %s\n"),arq
,strerror(errno
));
814 if(debug
) debuga(_("Reading access log file: %s\n"),arq
);
819 // pre-read the file only if we have to show stats
820 if(ShowReadStatistics
&& !from_stdin
&& !from_pipe
) {
828 while ((nread
=fread(tmp4
,1,sizeof(tmp4
),fp_in
))>0) {
829 for (i
=0 ; i
<nread
; i
++)
831 if (tmp4
[i
]!='\n' && tmp4
[i
]!='\r') {
835 if (tmp4
[i
]=='\n' || tmp4
[i
]=='\r') {
842 printf(_("SARG: Records in file: %lu, reading: %3.2f%%"),recs1
,(float) 0);
847 longline_reset(line
);
849 while ((linebuf
=longline_read(fp_in
,line
))!=NULL
) {
850 blen
=strlen(linebuf
);
852 if (ilf
==ILF_Unknown
) {
853 if(strncmp(linebuf
,"#Software: Mic",14) == 0) {
854 fixendofline(linebuf
);
856 debuga(_("Log is from Microsoft ISA: %s\n"),linebuf
);
862 if(strncmp(linebuf
,"*** SARG Log ***",16) == 0) {
863 if (getperiod_fromsarglog(arqtt
,&period
)<0) {
864 debuga(_("The name of the file is invalid: %s\n"),arq
);
873 if(!fp_log
&& ParsedOutputLog
[0] && ilf
!=ILF_Sarg
) {
874 if(access(ParsedOutputLog
,R_OK
) != 0) {
875 my_mkdir(ParsedOutputLog
);
877 if (snprintf(arq_log
,sizeof(arq_log
),"%s/sarg_temp.log",ParsedOutputLog
)>=sizeof(arq_log
)) {
878 debuga(_("File name too long: %s/sarg_temp.log\n"),ParsedOutputLog
);
881 if((fp_log
=MY_FOPEN(arq_log
,"w"))==NULL
) {
882 debuga(_("(log) Cannot open log file: %s - %s\n"),arq_log
,strerror(errno
));
885 fputs("*** SARG Log ***\n",fp_log
);
889 if( ShowReadStatistics
&& !from_stdin
&& !from_pipe
&& --OutputNonZero
<=0) {
890 double perc
= recs2
* 100. / recs1
;
891 printf(_("SARG: Records in file: %lu, reading: %3.2lf%%"),recs2
,perc
);
894 OutputNonZero
= REPORT_EVERY_X_LINES
;
896 if(blen
< 58) continue;
897 if(strstr(linebuf
,"HTTP/0.0") != 0) continue;
898 if(strstr(linebuf
,"logfile turned over") != 0) continue;
899 if(linebuf
[0] == ' ') continue;
902 if(ExcludeString
[0] != '\0') {
904 getword_start(&gwarea
,ExcludeString
);
905 while(strchr(gwarea
.current
,':') != 0) {
906 if (getword_multisep(val1
,sizeof(val1
),&gwarea
,':')<0) {
907 debuga(_("Maybe you have a broken record or garbage in your exclusion string\n"));
910 if((str
=(char *) strstr(linebuf
,val1
)) != (char *) NULL
) {
915 if(!exstring
&& (str
=(char *) strstr(linebuf
,gwarea
.current
)) != (char *) NULL
)
917 if(exstring
) continue;
922 printf("BUF=%s\n",linebuf
);
925 if (ilf
==ILF_Squid
|| ilf
==ILF_Common
|| ilf
==ILF_Unknown
) {
926 getword_start(&gwarea
,linebuf
);
927 if (getword(data
,sizeof(data
),&gwarea
,' ')<0) {
928 debuga(_("Maybe you have a broken time in your access.log file\n"));
931 if((str
=(char *) strchr(data
, '.')) != (char *) NULL
&& (str
=(char *) strchr(str
+1, '.')) != (char *) NULL
) {
935 if (getword(user
,sizeof(user
),&gwarea
,' ')<0 || getword_skip(255,&gwarea
,' ')<0) {
936 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
940 if (getword_skip(255,&gwarea
,' ')<0 || getword(user
,sizeof(user
),&gwarea
,' ')<0) {
941 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
945 if (getword(data
,sizeof(data
),&gwarea
,']')<0 || getword_skip(MAXLEN
,&gwarea
,'"')<0 ||
946 getword(fun
,sizeof(fun
),&gwarea
,' ')<0) {
947 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
950 if (getword_ptr(linebuf
,&full_url
,&gwarea
,' ')<0) {
951 debuga(_("Maybe you have a broken url in your %s file\n"),arq
);
954 if (getword_skip(MAXLEN
,&gwarea
,' ')<0) {
955 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
958 if (getword(code2
,sizeof(code2
),&gwarea
,' ')<0) {
959 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
962 if (getword(tam
,sizeof(tam
),&gwarea
,' ')<0) {
963 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
966 if((str
=(char *) strchr(gwarea
.current
, ' ')) != (char *) NULL
) {
967 if (getword(code
,sizeof(code
),&gwarea
,' ')<0) {
968 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
972 if (getword(code
,sizeof(code
),&gwarea
,'\0')<0) {
973 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
978 if ((str
= strchr(code
, ':')) != NULL
)
981 if(strcmp(tam
,"\0") == 0)
987 getword_start(&gwarea
,data
+1);
988 if (getword_multisep(data
,sizeof(data
),&gwarea
,':')<0){
989 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
992 if (getword_multisep(hora
,sizeof(hora
),&gwarea
,' ')<0){
993 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
996 getword_start(&gwarea
,data
);
997 if (getword_atoll(&iday
,&gwarea
,'/')<0){
998 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1001 if (getword(mes
,sizeof(mes
),&gwarea
,'/')<0){
1002 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1005 if (getword_atoll(&iyear
,&gwarea
,'/')<0){
1006 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1010 imonth
=month2num(mes
)+1;
1011 idata
=builddia(iday
,imonth
,iyear
);
1012 computedate(iyear
,imonth
,iday
,&tt
);
1013 if (sscanf(hora
,"%d:%d:%d",&tt
.tm_hour
,&tt
.tm_min
,&tt
.tm_sec
)!=3 || tt
.tm_hour
<0 || tt
.tm_hour
>=24 ||
1014 tt
.tm_min
<0 || tt
.tm_min
>=60 || tt
.tm_sec
<0 || tt
.tm_sec
>=60) {
1015 debuga(_("Invalid time found in %s\n"),arq
);
1021 if(ilf
==ILF_Unknown
|| ilf
==ILF_Squid
) {
1022 if (getword(elap
,sizeof(elap
),&gwarea
,' ')<0) {
1023 debuga(_("Maybe you have a broken elapsed time in your %s file\n"),arq
);
1026 while(strcmp(elap
,"") == 0 && gwarea
.current
[0] != '\0')
1027 if (getword(elap
,sizeof(elap
),&gwarea
,' ')<0) {
1028 debuga(_("Maybe you have a broken elapsed time in your %s file\n"),arq
);
1031 if(strlen(elap
) < 1) continue;
1032 if (getword(ip
,sizeof(ip
),&gwarea
,' ')<0){
1033 debuga(_("Maybe you have a broken client IP address in your %s file\n"),arq
);
1036 if (getword(code
,sizeof(code
),&gwarea
,' ')<0){
1037 debuga(_("Maybe you have a broken result code in your %s file\n"),arq
);
1040 if (getword(tam
,sizeof(tam
),&gwarea
,' ')<0){
1041 debuga(_("Maybe you have a broken amount of data in your %s file\n"),arq
);
1044 if (getword(fun
,sizeof(fun
),&gwarea
,' ')<0){
1045 debuga(_("Maybe you have a broken request method in your %s file\n"),arq
);
1048 if (getword_ptr(linebuf
,&full_url
,&gwarea
,' ')<0){
1049 debuga(_("Maybe you have a broken url in your %s file\n"),arq
);
1052 if (getword(user
,sizeof(user
),&gwarea
,' ')<0){
1053 debuga(_("Maybe you have a broken user ID in your %s file\n"),arq
);
1062 debuga(_("Cannot convert the timestamp from the squid log file\n"));
1066 strftime(tbuf2
, sizeof(tbuf2
), "%H%M", t
);
1068 idata
=(t
->tm_year
+1900)*10000+(t
->tm_mon
+1)*100+t
->tm_mday
;
1071 if (ilf
==ILF_Sarg
) {
1072 getword_start(&gwarea
,linebuf
);
1073 if (getword(data
,sizeof(data
),&gwarea
,'\t')<0){
1074 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1077 if (getword(hora
,sizeof(hora
),&gwarea
,'\t')<0) {
1078 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1081 if (getword(user
,sizeof(user
),&gwarea
,'\t')<0) {
1082 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1085 if (getword(ip
,sizeof(ip
),&gwarea
,'\t')<0) {
1086 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1089 if (getword_ptr(linebuf
,&full_url
,&gwarea
,'\t')<0){
1090 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1093 if (getword(tam
,sizeof(tam
),&gwarea
,'\t')<0){
1094 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1097 if (getword(code
,sizeof(code
),&gwarea
,'\t')<0){
1098 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1101 if (getword(elap
,sizeof(elap
),&gwarea
,'\t')<0){
1102 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1105 if (getword(smartfilter
,sizeof(smartfilter
),&gwarea
,'\0')<0){
1106 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1109 getword_start(&gwarea
,data
);
1110 if (getword_atoll(&iday
,&gwarea
,'/')<0 || iday
<1 || iday
>31){
1111 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1114 if (getword_atoll(&imonth
,&gwarea
,'/')<0 || imonth
<1 || imonth
>12){
1115 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1118 if (getword_atoll(&iyear
,&gwarea
,'\0')<0){
1119 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1122 idata
=builddia(iday
,imonth
,iyear
);
1123 computedate(iyear
,imonth
,iday
,&tt
);
1124 if (sscanf(hora
,"%d:%d:%d",&tt
.tm_hour
,&tt
.tm_min
,&tt
.tm_sec
)!=3 || tt
.tm_hour
<0 || tt
.tm_hour
>=24 ||
1125 tt
.tm_min
<0 || tt
.tm_min
>=60 || tt
.tm_sec
<0 || tt
.tm_sec
>=60) {
1126 debuga(_("Invalid time found in %s\n"),arq
);
1132 if (linebuf
[0] == '#') {
1133 int ncols
,cols
[ISACOL_Last
];
1135 fixendofline(linebuf
);
1136 getword_start(&gwarea
,linebuf
);
1137 // remove the #Fields: column at the beginning of the line
1138 if (getword_skip(1000,&gwarea
,' ')<0){
1139 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1142 for (ncols
=0 ; ncols
<ISACOL_Last
; ncols
++) cols
[ncols
]=-1;
1144 while(gwarea
.current
[0] != '\0') {
1145 if (getword(val1
,sizeof(val1
),&gwarea
,'\t')<0){
1146 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1149 if(strcmp(val1
,"c-ip") == 0) cols
[ISACOL_Ip
]=ncols
;
1150 if(strcmp(val1
,"cs-username") == 0) cols
[ISACOL_UserName
]=ncols
;
1151 if(strcmp(val1
,"date") == 0) cols
[ISACOL_Date
]=ncols
;
1152 if(strcmp(val1
,"time") == 0) cols
[ISACOL_Time
]=ncols
;
1153 if(strcmp(val1
,"time-taken") == 0) cols
[ISACOL_TimeTaken
]=ncols
;
1154 if(strcmp(val1
,"sc-bytes") == 0) cols
[ISACOL_Bytes
]=ncols
;
1155 if(strcmp(val1
,"cs-uri") == 0) cols
[ISACOL_Uri
]=ncols
;
1156 if(strcmp(val1
,"sc-status") == 0) cols
[ISACOL_Status
]=ncols
;
1159 if (cols
[ISACOL_Ip
]>=0) {
1161 for (ncols
=0 ; ncols
<ISACOL_Last
; ncols
++)
1162 isa_cols
[ncols
]=cols
[ncols
];
1166 if (!isa_ncols
) continue;
1167 getword_start(&gwarea
,linebuf
);
1168 for (x
=0 ; x
<isa_ncols
; x
++) {
1169 if (getword_ptr(linebuf
,&str
,&gwarea
,'\t')<0) {
1170 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1173 if (x
==isa_cols
[ISACOL_Ip
]) {
1174 if (strlen(str
)>=sizeof(ip
)) {
1175 debuga(_("Maybe you have a broken IP in your %s file\n"),arq
);
1179 } else if (x
==isa_cols
[ISACOL_UserName
]) {
1180 if (strlen(str
)>=sizeof(user
)) {
1181 debuga(_("Maybe you have a broken user ID in your %s file\n"),arq
);
1185 } else if (x
==isa_cols
[ISACOL_Date
]) {
1186 if (strlen(str
)>=sizeof(data
)) {
1187 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1191 } else if (x
==isa_cols
[ISACOL_Time
]) {
1192 if (strlen(str
)>=sizeof(hora
)) {
1193 debuga(_("Maybe you have a broken time in your %s file\n"),arq
);
1197 } else if (x
==isa_cols
[ISACOL_TimeTaken
]) {
1198 if (strlen(str
)>=sizeof(elap
)) {
1199 debuga(_("Maybe you have a broken download duration in your %s file\n"),arq
);
1203 } else if (x
==isa_cols
[ISACOL_Bytes
]) {
1204 if (strlen(str
)>=sizeof(tam
)) {
1205 debuga(_("Maybe you have a broken download size in your %s file\n"),arq
);
1209 } else if (x
==isa_cols
[ISACOL_Uri
]) {
1211 } else if (x
==isa_cols
[ISACOL_Status
]) {
1212 if (strlen(str
)>=sizeof(code
)) {
1213 debuga(_("Maybe you have a broken access code in your %s file\n"),arq
);
1220 if(strcmp(code
,"401") == 0 || strcmp(code
,"403") == 0 || strcmp(code
,"407") == 0) {
1221 sprintf(val1
,"DENIED/%s",code
);
1224 getword_start(&gwarea
,data
);
1225 if (getword_atoll(&iyear
,&gwarea
,'-')<0){
1226 debuga(_("Maybe you have a broken year in your %s file\n"),arq
);
1229 if (getword_atoll(&imonth
,&gwarea
,'-')<0){
1230 debuga(_("Maybe you have a broken month in your %s file\n"),arq
);
1233 if (getword_atoll(&iday
,&gwarea
,'\0')<0){
1234 debuga(_("Maybe you have a broken day in your %s file\n"),arq
);
1238 idata
=builddia(iday
,imonth
,iyear
);
1239 computedate(iyear
,imonth
,iday
,&tt
);
1240 if (isa_cols
[ISACOL_Time
]>=0) {
1241 if (sscanf(hora
,"%d:%d:%d",&tt
.tm_hour
,&tt
.tm_min
,&tt
.tm_sec
)!=3 || tt
.tm_hour
<0 || tt
.tm_hour
>=24 ||
1242 tt
.tm_min
<0 || tt
.tm_min
>=60 || tt
.tm_sec
<0 || tt
.tm_sec
>=60) {
1243 debuga(_("Invalid time found in %s\n"),arq
);
1250 debuga(_("Unknown input log file format\n"));
1254 strftime(dia
, sizeof(dia
), "%d/%m/%Y", t
);
1255 snprintf(hora
,sizeof(hora
),"%02d:%02d:%02d",t
->tm_hour
,t
->tm_min
,t
->tm_sec
);
1258 printf("DATE=%s IDATA=%d DFROM=%d DUNTIL=%d\n",date
,idata
,dfrom
,duntil
);
1260 if(date
[0] != '\0'){
1261 if(idata
< dfrom
|| idata
> duntil
) continue;
1264 // Record only hours usage which is required
1266 if( bsearch( &( t
-> tm_wday
), weekdays
.list
, weekdays
.len
, sizeof( int ), compar
) == NULL
)
1269 if( bsearch( &( t
-> tm_hour
), hours
.list
, hours
.len
, sizeof( int ), compar
) == NULL
)
1274 if(strlen(user
) > MAX_USER_LEN
) {
1275 if (debugm
) printf(_("User ID too long: %s\n"),user
);
1281 if(IncludeUsers
[0] != '\0') {
1282 snprintf(val1
,sizeof(val1
),":%s:",user
);
1283 if((str
=(char *) strstr(IncludeUsers
,val1
)) == (char *) NULL
)
1288 if (debugm
) printf(_("Excluded code: %s\n"),code
);
1293 if(testvaliduserchar(user
))
1297 if((str
= strstr(user
,"%20")) != NULL
) {
1299 This is a patch introduced to solve bug #1624251 reported at sourceforge but
1300 the side effect is to truncate the name at the first space and merge the reports
1301 of people whose name is identical up to the first space.
1303 The old code used to truncate the user name at the first % if a %20 was
1304 found anywhere in the string. That means the string could be truncated
1305 at the wrong place if another % occured before the %20. This new code should
1306 avoid that problem and only truncate at the space. There is no bug
1307 report indicating that anybody noticed this.
1313 Code prior to 2.2.7 used to replace any %xx by a dot as long as a %5c was
1314 found in the user name.
1316 while((str
= strstr(user
,"%5c")) != NULL
) {
1318 for (x
=3 ; str
[x
] ; x
++) str
[x
-2]=str
[x
];
1321 // replace any tab by a single space
1322 for (str
=full_url
; *str
; str
++)
1323 if (*str
=='\t') *str
=' ';
1324 for (str
=code
; *str
; str
++)
1325 if (*str
=='\t') *str
=' ';
1329 The full URL is not saved in sarg log. There is no point in testing the URL to detect
1332 download_flag
=is_download_suffix(full_url
);
1333 if (download_flag
) {
1334 safe_strcpy(download_url
,full_url
,sizeof(download_url
));
1338 download_flag
=false;
1340 url
=process_url(full_url
,LongUrl
);
1341 if (!url
|| 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 snprintf(wuser
,sizeof(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 (nbytes
<0) nbytes
=0;
1416 elap_time
=atol(elap
);
1417 if (elap_time
<0) elap_time
=0;
1419 if(elap_time
>max_elapsed
) {
1424 if((str
=(char *) strstr(linebuf
, "[SmartFilter:")) != (char *) NULL
) {
1426 snprintf(smartfilter
,sizeof(smartfilter
),"\"%s\"",str
+1);
1427 } else strcpy(smartfilter
,"\"\"");
1431 for (ufile
=first_user_file
; ufile
&& strcmp(user
,ufile
->user
->id
)!=0 ; ufile
=ufile
->next
) {
1433 if (ufile
->file
) nopen
++;
1436 ufile
=malloc(sizeof(*ufile
));
1438 debuga(_("Not enough memory to store the user %s\n"),user
);
1441 memset(ufile
,0,sizeof(*ufile
));
1442 ufile
->next
=first_user_file
;
1443 first_user_file
=ufile
;
1444 uinfo
=userinfo_create(user
);
1446 uinfo
->id_is_ip
=id_is_ip
;
1449 prev_ufile
->next
=ufile
->next
;
1450 ufile
->next
=first_user_file
;
1451 first_user_file
=ufile
;
1454 #ifdef ENABLE_DOUBLE_CHECK_DATA
1455 ufile
->user
->nbytes
+=nbytes
;
1456 ufile
->user
->elap
+=elap_time
;
1459 if (ufile
->file
==NULL
) {
1460 if (nopen
>=maxopenfiles
) {
1462 for (ufile1
=first_user_file
; ufile1
; ufile1
=ufile1
->next
) {
1463 if (ufile1
->file
!=NULL
) {
1464 if (x
>=maxopenfiles
) {
1465 if (fclose(ufile1
->file
)==EOF
) {
1466 debuga(_("Failed to close the log file of user %s - %s\n"),ufile1
->user
->id
,strerror(errno
));
1475 if (snprintf (tmp3
, sizeof(tmp3
), "%s/%s.unsort", tmp
, ufile
->user
->filename
)>=sizeof(tmp3
)) {
1476 debuga(_("Temporary user file name too long: %s/%s.unsort\n"), tmp
, ufile
->user
->filename
);
1479 if ((ufile
->file
= MY_FOPEN (tmp3
, "a")) == NULL
) {
1480 debuga(_("(log) Cannot open temporary file: %s - %s\n"), tmp3
, strerror(errno
));
1485 /*if ( strcmp ( user , sz_Last_User ) != 0 ) {
1486 if ( fp_Write_User )
1487 fclose( fp_Write_User ) ;
1488 sprintf (tmp3, "%s/%s.unsort", tmp, user);
1490 if ((fp_Write_User = MY_FOPEN (tmp3, "a")) == NULL) {
1491 fprintf (stderr, "%s: (log) %s: %s - %s\n", argv[0], _("Cannot open temporary file"), tmp3, strerror(errno));
1494 strcpy( sz_Last_User , user ) ;
1496 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) {
1497 debuga(_("Write error in the log file of user %s\n"),user
);
1501 if(fp_log
&& ilf
!=ILF_Sarg
)
1502 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
);
1506 if(!dataonly
&& download_flag
&& strstr(code
,"DENIED") == 0) {
1509 if ( ! fp_Download_Unsort
) {
1510 if ((fp_Download_Unsort
= MY_FOPEN ( sz_Download_Unsort
, "a")) == NULL
) {
1511 debuga(_("(log) Cannot open temporary file: %s - %s\n"),sz_Download_Unsort
, strerror(errno
));
1515 fprintf(fp_Download_Unsort
,"%s\t%s\t%s\t%s\t%s\n",dia
,hora
,user
,ip
,download_url
);
1518 if((ReportType
& REPORT_TYPE_DENIED
) != 0) {
1519 if(fp_denied
&& strstr(code
,"DENIED/403") != 0) {
1520 fprintf(fp_denied
, "%s\t%s\t%s\t%s\t%s\n",dia
,hora
,user
,ip
,full_url
);
1524 if((ReportType
& REPORT_TYPE_AUTH_FAILURES
) != 0) {
1525 if(fp_authfail
&& (strstr(code
,"DENIED/401") != 0 || strstr(code
,"DENIED/407") != 0)) {
1526 fprintf(fp_authfail
, "%s\t%s\t%s\t%s\t%s\n",dia
,hora
,user
,ip
,full_url
);
1531 if (ilf
!=ILF_Sarg
) {
1532 if(!totper
|| idata
<mindate
){
1534 memcpy(&period
.start
,t
,sizeof(*t
));
1535 strcpy(start_hour
,tbuf2
);
1537 if (!totper
|| idata
>maxdate
) {
1539 memcpy(&period
.end
,t
,sizeof(*t
));
1545 printf("IP=\t%s\n",ip
);
1546 printf("USER=\t%s\n",user
);
1547 printf("ELAP=\t%ld\n",elap_time
);
1548 printf("DATE=\t%s\n",dia
);
1549 printf("TIME=\t%s\n",hora
);
1550 printf("FUNC=\t%s\n",fun
);
1551 printf("URL=\t%s\n",url
);
1552 printf("CODE=\t%s\n",code
);
1553 printf("LEN=\t%ld\n",nbytes
);
1561 if( ShowReadStatistics
)
1562 printf(_("SARG: Records in file: %lu, reading: %3.2f%%\n"),recs1
, (float) 100 );
1568 debuga(_(" Records read: %ld, written: %ld, excluded: %ld\n"),totregsl
,totregsg
,totregsx
);
1570 longline_destroy(&line
);
1571 if ( fp_Download_Unsort
)
1572 fclose (fp_Download_Unsort
);
1574 for (ufile
=first_user_file
; ufile
; ufile
=ufile1
) {
1576 if (ufile
->file
!=NULL
) fclose(ufile
->file
);
1581 free_excludecodes();
1587 for (ilf
=0 ; ilf
<ILF_Last
; ilf
++) totalcount
+=ilf_count
[ilf
];
1589 if(ilf_count
[ILF_Common
]>0 && ilf_count
[ILF_Squid
]>0)
1590 debuga(_("Log with mixed records format (squid and common log)\n"));
1592 if(ilf_count
[ILF_Common
]>0 && ilf_count
[ILF_Squid
]==0)
1593 debuga(_("Common log format\n"));
1595 if(ilf_count
[ILF_Common
]==0 && ilf_count
[ILF_Squid
]>0)
1596 debuga(_("Squid log format\n"));
1598 if(ilf_count
[ILF_Sarg
]>0)
1599 debuga(_("Sarg log format\n"));
1601 if(totalcount
==0 && totregsg
)
1602 debuga(_("Log with invalid format\n"));
1606 debuga(_("No records found\n"));
1608 if(fp_denied
) fclose(fp_denied
);
1609 if(fp_authfail
) fclose(fp_authfail
);
1611 if(userfile
) free(userfile
);
1616 if (date
[0]!='\0') {
1617 char date0
[30], date1
[30];
1619 strftime(date0
,sizeof(date0
),"%d/%m/%Y",&period
.start
);
1620 strftime(date1
,sizeof(date1
),"%d/%m/%Y",&period
.end
);
1621 debuga(_("Period covered by log files: %s-%s\n"),date0
,date1
);
1622 getperiod_fromrange(&period
,dfrom
,duntil
);
1624 if (getperiod_buildtext(&period
)<0) {
1625 debuga(_("Failed to build the string representation of the date range\n"));
1630 debugaz(_("date=%s\n"),dia
);
1631 debugaz(_("period=%s\n"),period
.text
);
1635 debuga(_("Period: %s\n"),period
.text
);
1640 fclose(fp_authfail
);
1642 if(fp_log
!= NULL
) {
1645 char val4
[255];//val4 must not be bigger than arq_log without fixing the strcpy below
1648 safe_strcpy(end_hour
,tbuf2
,sizeof(end_hour
));
1649 strftime(val2
,sizeof(val2
),"%d%m%Y",&period
.start
);
1650 strftime(val1
,sizeof(val1
),"%d%m%Y",&period
.end
);
1651 if (snprintf(val4
,sizeof(val4
),"%s/sarg-%s_%s-%s_%s.log",ParsedOutputLog
,val2
,start_hour
,val1
,end_hour
)>=sizeof(val4
)) {
1652 debuga(_("File name too long: %s/sarg-%s_%s-%s_%s.log\n"),ParsedOutputLog
,val2
,start_hour
,val1
,end_hour
);
1655 if (rename(arq_log
,val4
)) {
1656 debuga(_("failed to rename %s to %s - %s\n"),arq_log
,val4
,strerror(errno
));
1658 strcpy(arq_log
,val4
);
1660 if(strcmp(ParsedOutputLogCompress
,"nocompress") != 0 && ParsedOutputLogCompress
[0] != '\0') {
1662 No double quotes around ParsedOutputLogCompress because it may contain command line options. If double quotes are
1663 necessary around the command name, put them in the configuration file.
1665 if (snprintf(val1
,sizeof(val1
),"%s \"%s\"",ParsedOutputLogCompress
,arq_log
)>=sizeof(val1
)) {
1666 debuga(_("Command too long: %s \"%s\"\n"),ParsedOutputLogCompress
,arq_log
);
1669 cstatus
=system(val1
);
1670 if (!WIFEXITED(cstatus
) || WEXITSTATUS(cstatus
)) {
1671 debuga(_("command return status %d\n"),WEXITSTATUS(cstatus
));
1672 debuga(_("command: %s\n"),val1
);
1678 debuga(_("Sarg parsed log saved as %s\n"),arq_log
);
1681 if(DataFile
[0] == '\0' && (ReportType
& REPORT_TYPE_DENIED
) != 0) {
1682 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
)) {
1683 debuga(_("Sort command too long when sorting file \"%s\" to \"%s\"\n"),denied_unsort
,denied_sort
);
1686 cstatus
=system(csort
);
1687 if (!WIFEXITED(cstatus
) || WEXITSTATUS(cstatus
)) {
1688 debuga(_("sort command return status %d\n"),WEXITSTATUS(cstatus
));
1689 debuga(_("sort command: %s\n"),csort
);
1692 if (unlink(denied_unsort
)) {
1693 debuga(_("Cannot delete %s - %s\n"),denied_unsort
,strerror(errno
));
1698 if(DataFile
[0] != '\0')
1703 if((ReportType
& REPORT_TYPE_DENIED
) != 0) {
1704 unlink(denied_sort
);
1707 if(strcmp(tmp
,"/tmp") != 0) {
1724 static void getusers(const char *pwdfile
, int debug
)
1732 debuga(_("Loading password file from %s\n"),pwdfile
);
1734 if ((fp_usr
= fopen(pwdfile
, "r")) == NULL
) {
1735 debuga(_("(getusers) Cannot open file %s - %s\n"),pwdfile
,strerror(errno
));
1739 if (fseek(fp_usr
, 0, SEEK_END
)==-1) {
1740 debuga(_("Failed to move till the end of the users file %s: %s\n"),pwdfile
,strerror(errno
));
1743 nreg
= ftell(fp_usr
);
1745 debuga(_("Cannot get the size of file %s\n"),pwdfile
);
1749 if (fseek(fp_usr
, 0, SEEK_SET
)==-1) {
1750 debuga(_("Failed to rewind the users file %s: %s\n"),pwdfile
,strerror(errno
));
1754 if((userfile
=(char *) malloc(nreg
))==NULL
){
1755 debuga(_("malloc error (%ld)\n"),nreg
);
1759 bzero(userfile
,nreg
);
1760 strcpy(userfile
,":");
1762 while(fgets(buf
,sizeof(buf
),fp_usr
)!=NULL
) {
1763 str
=strchr(buf
,':');
1765 debuga(_("You have an invalid user in your %s file\n"),pwdfile
);
1769 strcat(userfile
,buf
);