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 char splitprefix
[MAXLEN
];
118 enum InputLogFormat ilf
;
119 int ilf_count
[ILF_Last
];
131 int isa_ncols
=0,isa_cols
[ISACOL_Last
];
143 long int max_elapsed
=0;
144 long long int iyear
, imonth
, iday
;
149 unsigned long recs1
=0UL;
150 unsigned long recs2
=0UL;
151 int OutputNonZero
= REPORT_EVERY_X_LINES
;
152 bool download_flag
=false;
153 char *download_url
=NULL
;
154 struct getwordstruct gwarea
;
158 struct userinfostruct
*uinfo
;
159 struct userfilestruct
*first_user_file
, *ufile
, *ufile1
, *prev_ufile
;
161 static int convert
=0;
162 static int output_css
=0;
164 static struct option long_options
[]=
166 {"convert",no_argument
,&convert
,1},
167 {"css",no_argument
,&output_css
,1},
168 {"lastlog",required_argument
,NULL
,2},
169 {"keeplogs",no_argument
,NULL
,3},
170 {"split",no_argument
,&split
,1},
171 {"splitprefix",required_argument
,NULL
,'P'},
176 setlocale(LC_TIME
,"");
179 #if defined(ENABLE_NLS) && defined(HAVE_LOCALE_H)
180 if (!setlocale (LC_ALL
, "")) {
181 fprintf(stderr
,"SARG: Cannot set the locale LC_ALL to the environment variable\n");
184 if (!bindtextdomain (PACKAGE_NAME
, LOCALEDIR
)) {
185 fprintf(stderr
,"SARG: Cannot bind to text domain %s in directory %s (%s)\n",PACKAGE_NAME
,LOCALEDIR
,strerror(errno
));
188 if (!textdomain (PACKAGE_NAME
)) {
189 fprintf(stderr
,"SARG: Cannot set gettext domain for %s PACKAGE_NAME (%s)\n",PACKAGE_NAME
,strerror(errno
));
199 UserAgentLog
[0]='\0';
200 ExcludeHosts
[0]='\0';
201 ExcludeUsers
[0]='\0';
208 ExternalCSSFile
[0]='\0';
209 RedirectorLogFormat
[0]='\0';
211 for (ilf
=0 ; ilf
<ILF_Last
; ilf
++) ilf_count
[ilf
]=0;
213 sprintf(ExcludeCodes
,"%s/exclude_codes",SYSCONFDIR
);
214 strcpy(GraphDaysBytesBarColor
,"orange");
215 strcpy(BgColor
,"#ffffff");
216 strcpy(TxColor
,"#000000");
217 strcpy(TxBgColor
,"lavender");
218 strcpy(TiColor
,"darkblue");
221 strcpy(LogoTextColor
,"#000000");
222 strcpy(HeaderColor
,"darkblue");
223 strcpy(HeaderBgColor
,"#dddddd");
224 strcpy(LogoTextColor
,"#006699");
225 strcpy(FontSize
,"9px");
226 strcpy(TempDir
,"/tmp");
227 strcpy(OutputDir
,"/var/www/html/squid-reports");
228 AnonymousOutputFiles
=false;
230 strcpy(DateFormat
,"u");
231 OverwriteReport
=false;
232 RemoveTempFiles
=true;
233 strcpy(ReplaceIndex
,"index.html");
235 RecordsWithoutUser
=RECORDWITHOUTUSER_IP
;
237 strcpy(MailUtility
,"mailx");
241 TopuserSort
=TOPUSER_SORT_BYTES
| TOPUSER_SORT_REVERSE
;
242 UserSort
=USER_SORT_BYTES
| USER_SORT_REVERSE
;
243 TopsitesSort
=TOPSITE_SORT_CONNECT
| TOPSITE_SORT_REVERSE
;
245 strcpy(FontFace
,"Verdana,Tahoma,Arial");
246 datetimeby
=DATETIME_BYTE
;
247 strcpy(CharSet
,"ISO-8859-1");
249 strcpy(PrivacyString
,"***.***.***.***");
250 strcpy(PrivacyStringColor
,"blue");
252 TopUserFields
=TOPUSERFIELDS_NUM
| TOPUSERFIELDS_DATE_TIME
| TOPUSERFIELDS_USERID
| TOPUSERFIELDS_CONNECT
|
253 TOPUSERFIELDS_BYTES
| TOPUSERFIELDS_SETYB
| TOPUSERFIELDS_IN_CACHE_OUT
|
254 TOPUSERFIELDS_USED_TIME
| TOPUSERFIELDS_MILISEC
| TOPUSERFIELDS_PTIME
|
255 TOPUSERFIELDS_TOTAL
| TOPUSERFIELDS_AVERAGE
;
256 UserReportFields
=USERREPORTFIELDS_CONNECT
| USERREPORTFIELDS_BYTES
| USERREPORTFIELDS_SETYB
|
257 USERREPORTFIELDS_IN_CACHE_OUT
| USERREPORTFIELDS_USED_TIME
| USERREPORTFIELDS_MILISEC
|
258 USERREPORTFIELDS_PTIME
| USERREPORTFIELDS_TOTAL
| USERREPORTFIELDS_AVERAGE
;
259 strcpy(DataFileDelimiter
,";");
260 DataFileFields
=DATA_FIELD_USER
| DATA_FIELD_DATE
| DATA_FIELD_TIME
| DATA_FIELD_URL
| DATA_FIELD_CONNECT
|
261 DATA_FIELD_BYTES
| DATA_FIELD_IN_CACHE
| DATA_FIELD_OUT_CACHE
| DATA_FIELD_ELAPSED
;
262 ShowReadStatistics
=true;
263 strcpy(IndexSortOrder
,"D");
266 ParsedOutputLog
[0]='\0';
267 strcpy(ParsedOutputLogCompress
,"/bin/gzip -f");
268 DisplayedValues
=DISPLAY_ABBREV
;
269 strcpy(HeaderFontSize
,"9px");
270 strcpy(TitleFontSize
,"11px");
271 strcpy(AuthUserTemplateFile
,"sarg_htaccess");
272 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");
275 strcpy(GraphFont
,FONTDIR
"/DejaVuSans.ttf");
279 strcpy(Ulimit
,"20000");
280 NtlmUserFormat
=NTLMUSERFORMAT_DOMAINUSER
;
281 IndexTree
=INDEX_TREE_FILE
;
282 IndexFields
=INDEXFIELDS_DIRSIZE
;
283 strcpy(RealtimeTypes
,"GET,PUT,CONNECT");
284 RealtimeUnauthRec
=REALTIME_UNAUTH_REC_SHOW
;
285 RedirectorFilterOutDate
=true;
286 DansguardianFilterOutDate
=true;
287 DataFileUrl
=DATAFILEURL_IP
;
288 strcpy(MaxElapsed
,"28800000");
289 BytesInSitesUsersReport
=0;
290 UserAuthentication
=0;
291 strcpy(LDAPHost
,"127.0.0.1");
293 LDAPProtocolVersion
=3;
296 LDAPBaseSearch
[0]='\0';
297 strcpy(LDAPFilterSearch
, "(uid=%s)");
298 strcpy(LDAPTargetAttr
, "cn");
322 UserInvalidChar
[0]='\0';
324 SquidGuardConf
[0]='\0';
325 DansGuardianConf
[0]='\0';
329 HostAliasFile
[0]='\0';
334 dansguardian_count
=0;
337 DeniedReportLimit
=10;
338 AuthfailReportLimit
=10;
339 DansGuardianReportLimit
=10;
340 SquidGuardReportLimit
=10;
341 DownloadReportLimit
=50;
350 realtime_access_log_lines
=1000;
358 bzero(IncludeUsers
, sizeof(IncludeUsers
));
359 bzero(ExcludeString
, sizeof(ExcludeString
));
360 first_user_file
=NULL
;
361 memset(&period
,0,sizeof(period
));
364 for(x
=0; x
<MAXLOGS
; x
++)
365 AccessLog
[x
][0]='\0';
366 AccessLogFromCmdLine
=0;
367 RedirectorLogFromCmdLine
=0;
369 strcpy(Title
,_("Squid User Access Report"));
371 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){
377 lastlog
=atoi(optarg
);
386 strcpy(uagent
,optarg
);
389 strcpy(hexclude
,optarg
);
392 strncpy(date
,optarg
,sizeof(date
)-1);
393 date
[sizeof(date
)-1]='\0';
394 date_from(date
, &dfrom
, &duntil
);
397 strcpy(email
,optarg
);
400 strcpy(ConfigFile
,optarg
);
412 if (NAccessLog
>=MAXLOGS
) {
413 debuga(_("Too many log files passed on command line with option -l.\n"));
416 if (strlen(optarg
)>=MAX_LOG_FILELEN
) {
417 debuga(_("Log file name too long passed on command line with option -l: %s\n"),optarg
);
420 strcpy(AccessLog
[NAccessLog
],optarg
);
422 AccessLogFromCmdLine
++;
425 if (NRedirectorLogs
>MAX_REDIRECTOR_LOGS
) {
426 debuga(_("Too many redirector logs passed on command line with option -L.\n"));
429 if (strlen(optarg
)>=MAX_REDIRECTOR_FILELEN
) {
430 debuga(_("Redirector log file name too long passed on command line with opton -L: %s\n"),optarg
);
433 strcpy(RedirectorLogs
[NRedirectorLogs
],optarg
);
435 RedirectorLogFromCmdLine
++;
444 strcpy(outdir
,optarg
);
450 strcpy(splitprefix
,optarg
);
462 if(strstr(optarg
,"-") == 0) {
463 if(sscanf(optarg
,"%d:%d",&h1
,&m1
)!=2) {
464 debuga(_("Time period passed on the command line with option -t must be MM:SS\n"));
469 snprintf(hm_str
,sizeof(hm_str
),"%02d:%02d",h1
,m1
);
471 if(sscanf(optarg
,"%d:%d-%d:%d",&h1
,&m1
,&h2
,&m2
)!=4) {
472 debuga(_("Time range passed on the command line with option -t must be MM:SS-MM:SS\n"));
477 snprintf(hm_str
,sizeof(hm_str
),"%02d:%02d-%02d:%02d",h1
,m1
,h2
,m2
);
500 debuga(_("Option -%c requires an argument\n"),optopt
);
516 for (iarq
=optind
; iarq
<argc
; iarq
++) {
517 if (NAccessLog
>=MAXLOGS
) {
518 debuga(_("Too many log files passed on command line.\n"));
521 if (strlen(argv
[iarq
])>=MAX_LOG_FILELEN
) {
522 debuga(_("Log file name too long passed on command line: %s\n"),argv
[iarq
]);
525 strcpy(AccessLog
[NAccessLog
],argv
[iarq
]);
527 AccessLogFromCmdLine
++;
531 if(debug
) debuga(_("Init\n"));
533 if(ConfigFile
[0] == '\0') snprintf(ConfigFile
,sizeof(ConfigFile
),"%s/sarg.conf",SYSCONFDIR
);
534 if(access(ConfigFile
, R_OK
) != 0) {
535 debuga(_("Cannot open config file: %s - %s\n"),ConfigFile
,strerror(errno
));
539 if(access(ConfigFile
, R_OK
) == 0)
542 if(userip
) UserIp
=true;
544 if(dns
) Ip2Name
=true;
546 if (lastlog
>=0) LastLog
=lastlog
;
548 if(outdir
[0] == '\0') strcpy(outdir
,OutputDir
);
549 if(outdir
[0] != '\0') strcat(outdir
,"/");
556 if(IndexTree
== INDEX_TREE_FILE
)
557 strcpy(ImageFile
,"../images");
559 strcpy(ImageFile
,"../../../images");
562 if(DataFile
[0] != '\0')
565 if(df
[0] == '\0') strcpy(df
,DateFormat
);
566 else strcpy(DateFormat
,df
);
570 strcpy(DateFormat
,"u");
573 IndexTree
=INDEX_TREE_FILE
;
575 if(NAccessLog
== 0) {
576 strcpy(AccessLog
[0],"/var/log/squid/access.log");
585 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++)
586 splitlog(AccessLog
[iarq
], df
, dfrom
, duntil
, convert
, splitprefix
);
590 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++)
591 convlog(AccessLog
[iarq
], df
, dfrom
, duntil
);
595 load_excludecodes(ExcludeCodes
);
597 if(access(PasswdFile
, R_OK
) == 0) {
598 getusers(PasswdFile
,debug
);
602 if(hexclude
[0] == '\0')
603 strcpy(hexclude
,ExcludeHosts
);
604 if(hexclude
[0] != '\0') {
605 gethexclude(hexclude
,debug
);
609 if(ReportType
== 0) {
610 ReportType
=REPORT_TYPE_TOPUSERS
| REPORT_TYPE_TOPSITES
| REPORT_TYPE_USERS_SITES
|
611 REPORT_TYPE_SITES_USERS
| REPORT_TYPE_DATE_TIME
| REPORT_TYPE_DENIED
|
612 REPORT_TYPE_AUTH_FAILURES
| REPORT_TYPE_SITE_USER_TIME_DATE
| REPORT_TYPE_DOWNLOADS
;
615 if(access(ExcludeUsers
, R_OK
) == 0) {
616 getuexclude(ExcludeUsers
,debug
);
619 if (HostAliasFile
[0] != '\0')
620 read_hostalias(HostAliasFile
);
627 if(strcmp(ExcludeUsers
,"indexonly") == 0) indexonly
=true;
628 if(Index
== INDEX_ONLY
) indexonly
=true;
630 if(MaxElapsed
[0] != '\0') max_elapsed
=atol(MaxElapsed
);
632 if(uagent
[0] == '\0') strcpy(uagent
,UserAgentLog
);
634 if(tmp
[0] == '\0') strcpy(tmp
,TempDir
);
635 else strcpy(TempDir
,tmp
);
637 For historical reasons, the temporary directory is the subdirectory "sarg" of the path
638 provided by the user.
642 if (tmp
[0]!='\0' && strncmp(outdir
,tmp
,strlen(tmp
))==0) {
643 debuga(_("The output directory \"%s\" must be outside of the temporary directory \"%s\"\n"),outdir
,tmp
);
647 if(email
[0] == '\0' && OutputEmail
[0] != '\0') strcpy(email
,OutputEmail
);
649 if(email
[0] != '\0') {
655 if(access(tmp
, R_OK
) == 0) {
659 snprintf(denied_unsort
,sizeof(denied_unsort
),"%s/denied.log.unsort",tmp
);
660 snprintf(denied_sort
,sizeof(denied_sort
),"%s/denied.log",tmp
);
661 snprintf(authfail_unsort
,sizeof(authfail_unsort
),"%s/authfail.log.unsort",tmp
);
664 debuga(_("Parameters:\n"));
665 debuga(_(" Hostname or IP address (-a) = %s\n"),addr
);
666 debuga(_(" Useragent log (-b) = %s\n"),uagent
);
667 debuga(_(" Exclude file (-c) = %s\n"),hexclude
);
668 debuga(_(" Date from-until (-d) = %s\n"),date
);
669 debuga(_(" Email address to send reports (-e) = %s\n"),email
);
670 debuga(_(" Config file (-f) = %s\n"),ConfigFile
);
671 if(strcmp(df
,"e") == 0)
672 debuga(_(" Date format (-g) = Europe (dd/mm/yyyy)\n"));
673 if(strcmp(df
,"u") == 0)
674 debuga(_(" Date format (-g) = USA (mm/dd/yyyy)\n"));
675 if(strcmp(df
,"w") == 0)
676 debuga(_(" Date format (-g) = Sites & Users (yyyy/ww)\n"));
677 debuga(_(" IP report (-i) = %s\n"),(iprel
) ? _("Yes") : _("No"));
678 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++)
679 debuga(_(" Input log (-l) = %s\n"),AccessLog
[iarq
]);
680 for (iarq
=0 ; iarq
<NRedirectorLogs
; iarq
++)
681 debuga(_(" Redirector log (-L) = %s\n"),RedirectorLogs
[iarq
]);
682 debuga(_(" Resolve IP Address (-n) = %s\n"),(Ip2Name
) ? _("Yes") : _("No"));
683 debuga(_(" Output dir (-o) = %s\n"),outdir
);
684 debuga(_("Use Ip Address instead of userid (-p) = %s\n"),(UserIp
) ? _("Yes") : _("No"));
685 debuga(_(" Accessed site (-s) = %s\n"),site
);
686 debuga(_(" Time (-t) = %s\n"),hm_str
);
687 debuga(_(" User (-u) = %s\n"),us
);
688 debuga(_(" Temporary dir (-w) = %s\n"),tmp
);
689 debuga(_(" Debug messages (-x) = %s\n"),(debug
) ? _("Yes") : _("No"));
690 debuga(_(" Process messages (-z) = %s\n"),(debugz
) ? _("Yes") : _("No"));
691 debuga(_(" Previous reports to keep (--lastlog) = %d\n"),LastLog
);
696 printf(_("Parameters:\n"));
697 printf(_(" Hostname or IP address (-a) = %s\n"),addr
);
698 printf(_(" Useragent log (-b) = %s\n"),uagent
);
699 printf(_(" Exclude file (-c) = %s\n"),hexclude
);
700 printf(_(" Date from-until (-d) = %s\n"),date
);
701 printf(_(" Email address to send reports (-e) = %s\n"),email
);
702 printf(_(" Config file (-f) = %s\n"),ConfigFile
);
703 if(strcmp(df
,"e") == 0)
704 printf(_(" Date format (-g) = Europe (dd/mm/yyyy)\n"));
705 if(strcmp(df
,"u") == 0)
706 printf(_(" Date format (-g) = USA (mm/dd/yyyy)\n"));
707 if(strcmp(df
,"w") == 0)
708 printf(_(" Date format (-g) = Sites & Users (yyyy/ww)\n"));
709 printf(_(" IP report (-i) = %s\n"),(iprel
) ? _("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
,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.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 sprintf(arq_log
,"%s/sarg_temp.log",ParsedOutputLog
);
885 if((fp_log
=MY_FOPEN(arq_log
,"w"))==NULL
) {
886 debuga(_("(log) Cannot open log file: %s - %s\n"),arq_log
,strerror(errno
));
889 fputs("*** SARG Log ***\n",fp_log
);
893 if( ShowReadStatistics
&& !from_stdin
&& !from_pipe
&& --OutputNonZero
<=0) {
894 double perc
= recs2
* 100. / recs1
;
895 printf(_("SARG: Records in file: %lu, reading: %3.2lf%%"),recs2
,perc
);
898 OutputNonZero
= REPORT_EVERY_X_LINES
;
900 if(blen
< 58) continue;
901 if(strstr(linebuf
,"HTTP/0.0") != 0) continue;
902 if(strstr(linebuf
,"logfile turned over") != 0) continue;
903 if(linebuf
[0] == ' ') continue;
906 if(ExcludeString
[0] != '\0') {
908 getword_start(&gwarea
,ExcludeString
);
909 while(strchr(gwarea
.current
,':') != 0) {
910 if (getword_multisep(val1
,sizeof(val1
),&gwarea
,':')<0) {
911 debuga(_("Maybe you have a broken record or garbage in your exclusion string\n"));
914 if((str
=(char *) strstr(linebuf
,val1
)) != (char *) NULL
) {
919 if(!exstring
&& (str
=(char *) strstr(linebuf
,gwarea
.current
)) != (char *) NULL
)
921 if(exstring
) continue;
926 printf("BUF=%s\n",linebuf
);
929 if (ilf
==ILF_Squid
|| ilf
==ILF_Common
|| ilf
==ILF_Unknown
) {
930 getword_start(&gwarea
,linebuf
);
931 if (getword(data
,sizeof(data
),&gwarea
,' ')<0) {
932 debuga(_("Maybe you have a broken time in your access.log file\n"));
935 if((str
=(char *) strchr(data
, '.')) != (char *) NULL
&& (str
=(char *) strchr(str
+1, '.')) != (char *) NULL
) {
939 if (getword(user
,sizeof(user
),&gwarea
,' ')<0 || getword_skip(255,&gwarea
,' ')<0) {
940 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
944 if (getword_skip(255,&gwarea
,' ')<0 || getword(user
,sizeof(user
),&gwarea
,' ')<0) {
945 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
949 if (getword(data
,sizeof(data
),&gwarea
,']')<0 || getword_skip(MAXLEN
,&gwarea
,'"')<0 ||
950 getword(fun
,sizeof(fun
),&gwarea
,' ')<0) {
951 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
954 if (getword_ptr(linebuf
,&full_url
,&gwarea
,' ')<0) {
955 debuga(_("Maybe you have a broken url in your %s file\n"),arq
);
958 if (getword_skip(MAXLEN
,&gwarea
,' ')<0) {
959 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
962 if (getword(code2
,sizeof(code2
),&gwarea
,' ')<0) {
963 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
966 if (getword(tam
,sizeof(tam
),&gwarea
,' ')<0) {
967 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
970 if((str
=(char *) strchr(gwarea
.current
, ' ')) != (char *) NULL
) {
971 if (getword(code
,sizeof(code
),&gwarea
,' ')<0) {
972 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
976 if (getword(code
,sizeof(code
),&gwarea
,'\0')<0) {
977 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
982 if ((str
= strchr(code
, ':')) != NULL
)
985 if(strcmp(tam
,"\0") == 0)
991 getword_start(&gwarea
,data
+1);
992 if (getword_multisep(data
,sizeof(data
),&gwarea
,':')<0){
993 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
996 if (getword_multisep(hora
,sizeof(hora
),&gwarea
,' ')<0){
997 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1000 getword_start(&gwarea
,data
);
1001 if (getword_atoll(&iday
,&gwarea
,'/')<0){
1002 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1005 if (getword(mes
,sizeof(mes
),&gwarea
,'/')<0){
1006 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1009 if (getword_atoll(&iyear
,&gwarea
,'/')<0){
1010 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1014 imonth
=month2num(mes
)+1;
1015 idata
=builddia(iday
,imonth
,iyear
);
1016 computedate(iyear
,imonth
,iday
,&tt
);
1017 if (sscanf(hora
,"%d:%d:%d",&tt
.tm_hour
,&tt
.tm_min
,&tt
.tm_sec
)!=3 || tt
.tm_hour
<0 || tt
.tm_hour
>=24 ||
1018 tt
.tm_min
<0 || tt
.tm_min
>=60 || tt
.tm_sec
<0 || tt
.tm_sec
>=60) {
1019 debuga(_("Invalid time found in %s\n"),arq
);
1025 if(ilf
==ILF_Unknown
|| ilf
==ILF_Squid
) {
1026 if (getword(elap
,sizeof(elap
),&gwarea
,' ')<0) {
1027 debuga(_("Maybe you have a broken elapsed time in your %s file\n"),arq
);
1030 while(strcmp(elap
,"") == 0 && gwarea
.current
[0] != '\0')
1031 if (getword(elap
,sizeof(elap
),&gwarea
,' ')<0) {
1032 debuga(_("Maybe you have a broken elapsed time in your %s file\n"),arq
);
1035 if(strlen(elap
) < 1) continue;
1036 if (getword(ip
,sizeof(ip
),&gwarea
,' ')<0){
1037 debuga(_("Maybe you have a broken client IP address in your %s file\n"),arq
);
1040 if (getword(code
,sizeof(code
),&gwarea
,' ')<0){
1041 debuga(_("Maybe you have a broken result code in your %s file\n"),arq
);
1044 if (getword(tam
,sizeof(tam
),&gwarea
,' ')<0){
1045 debuga(_("Maybe you have a broken amount of data in your %s file\n"),arq
);
1048 if (getword(fun
,sizeof(fun
),&gwarea
,' ')<0){
1049 debuga(_("Maybe you have a broken request method in your %s file\n"),arq
);
1052 if (getword_ptr(linebuf
,&full_url
,&gwarea
,' ')<0){
1053 debuga(_("Maybe you have a broken url in your %s file\n"),arq
);
1056 if (getword(user
,sizeof(user
),&gwarea
,' ')<0){
1057 debuga(_("Maybe you have a broken user ID in your %s file\n"),arq
);
1066 debuga(_("Cannot convert the timestamp from the squid log file\n"));
1070 strftime(tbuf2
, sizeof(tbuf2
), "%H%M", t
);
1072 idata
=(t
->tm_year
+1900)*10000+(t
->tm_mon
+1)*100+t
->tm_mday
;
1075 if (ilf
==ILF_Sarg
) {
1076 getword_start(&gwarea
,linebuf
);
1077 if (getword(data
,sizeof(data
),&gwarea
,'\t')<0){
1078 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1081 if (getword(hora
,sizeof(hora
),&gwarea
,'\t')<0) {
1082 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1085 if (getword(user
,sizeof(user
),&gwarea
,'\t')<0) {
1086 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1089 if (getword(ip
,sizeof(ip
),&gwarea
,'\t')<0) {
1090 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1093 if (getword_ptr(linebuf
,&full_url
,&gwarea
,'\t')<0){
1094 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1097 if (getword(tam
,sizeof(tam
),&gwarea
,'\t')<0){
1098 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1101 if (getword(code
,sizeof(code
),&gwarea
,'\t')<0){
1102 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1105 if (getword(elap
,sizeof(elap
),&gwarea
,'\t')<0){
1106 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1109 if (getword(smartfilter
,sizeof(smartfilter
),&gwarea
,'\0')<0){
1110 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1113 getword_start(&gwarea
,data
);
1114 if (getword_atoll(&iday
,&gwarea
,'/')<0 || iday
<1 || iday
>31){
1115 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1118 if (getword_atoll(&imonth
,&gwarea
,'/')<0 || imonth
<1 || imonth
>12){
1119 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1122 if (getword_atoll(&iyear
,&gwarea
,'\0')<0){
1123 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1126 idata
=builddia(iday
,imonth
,iyear
);
1127 computedate(iyear
,imonth
,iday
,&tt
);
1128 if (sscanf(hora
,"%d:%d:%d",&tt
.tm_hour
,&tt
.tm_min
,&tt
.tm_sec
)!=3 || tt
.tm_hour
<0 || tt
.tm_hour
>=24 ||
1129 tt
.tm_min
<0 || tt
.tm_min
>=60 || tt
.tm_sec
<0 || tt
.tm_sec
>=60) {
1130 debuga(_("Invalid time found in %s\n"),arq
);
1136 if (linebuf
[0] == '#') {
1137 int ncols
,cols
[ISACOL_Last
];
1139 fixendofline(linebuf
);
1140 getword_start(&gwarea
,linebuf
);
1141 // remove the #Fields: column at the beginning of the line
1142 if (getword_skip(1000,&gwarea
,' ')<0){
1143 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1146 for (ncols
=0 ; ncols
<ISACOL_Last
; ncols
++) cols
[ncols
]=-1;
1148 while(gwarea
.current
[0] != '\0') {
1149 if (getword(val1
,sizeof(val1
),&gwarea
,'\t')<0){
1150 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1153 if(strcmp(val1
,"c-ip") == 0) cols
[ISACOL_Ip
]=ncols
;
1154 if(strcmp(val1
,"cs-username") == 0) cols
[ISACOL_UserName
]=ncols
;
1155 if(strcmp(val1
,"date") == 0) cols
[ISACOL_Date
]=ncols
;
1156 if(strcmp(val1
,"time") == 0) cols
[ISACOL_Time
]=ncols
;
1157 if(strcmp(val1
,"time-taken") == 0) cols
[ISACOL_TimeTaken
]=ncols
;
1158 if(strcmp(val1
,"sc-bytes") == 0) cols
[ISACOL_Bytes
]=ncols
;
1159 if(strcmp(val1
,"cs-uri") == 0) cols
[ISACOL_Uri
]=ncols
;
1160 if(strcmp(val1
,"sc-status") == 0) cols
[ISACOL_Status
]=ncols
;
1163 if (cols
[ISACOL_Ip
]>=0) {
1165 for (ncols
=0 ; ncols
<ISACOL_Last
; ncols
++)
1166 isa_cols
[ncols
]=cols
[ncols
];
1170 if (!isa_ncols
) continue;
1171 getword_start(&gwarea
,linebuf
);
1172 for (x
=0 ; x
<isa_ncols
; x
++) {
1173 if (getword_ptr(linebuf
,&str
,&gwarea
,'\t')<0) {
1174 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq
);
1177 if (x
==isa_cols
[ISACOL_Ip
]) {
1178 if (strlen(str
)>=sizeof(ip
)) {
1179 debuga(_("Maybe you have a broken IP in your %s file\n"),arq
);
1183 } else if (x
==isa_cols
[ISACOL_UserName
]) {
1184 if (strlen(str
)>=sizeof(user
)) {
1185 debuga(_("Maybe you have a broken user ID in your %s file\n"),arq
);
1189 } else if (x
==isa_cols
[ISACOL_Date
]) {
1190 if (strlen(str
)>=sizeof(data
)) {
1191 debuga(_("Maybe you have a broken date in your %s file\n"),arq
);
1195 } else if (x
==isa_cols
[ISACOL_Time
]) {
1196 if (strlen(str
)>=sizeof(hora
)) {
1197 debuga(_("Maybe you have a broken time in your %s file\n"),arq
);
1201 } else if (x
==isa_cols
[ISACOL_TimeTaken
]) {
1202 if (strlen(str
)>=sizeof(elap
)) {
1203 debuga(_("Maybe you have a broken download duration in your %s file\n"),arq
);
1207 } else if (x
==isa_cols
[ISACOL_Bytes
]) {
1208 if (strlen(str
)>=sizeof(tam
)) {
1209 debuga(_("Maybe you have a broken download size in your %s file\n"),arq
);
1213 } else if (x
==isa_cols
[ISACOL_Uri
]) {
1215 } else if (x
==isa_cols
[ISACOL_Status
]) {
1216 if (strlen(str
)>=sizeof(code
)) {
1217 debuga(_("Maybe you have a broken access code in your %s file\n"),arq
);
1224 if(strcmp(code
,"401") == 0 || strcmp(code
,"403") == 0 || strcmp(code
,"407") == 0) {
1225 sprintf(val1
,"DENIED/%s",code
);
1228 getword_start(&gwarea
,data
);
1229 if (getword_atoll(&iyear
,&gwarea
,'-')<0){
1230 debuga(_("Maybe you have a broken year in your %s file\n"),arq
);
1233 if (getword_atoll(&imonth
,&gwarea
,'-')<0){
1234 debuga(_("Maybe you have a broken month in your %s file\n"),arq
);
1237 if (getword_atoll(&iday
,&gwarea
,'\0')<0){
1238 debuga(_("Maybe you have a broken day in your %s file\n"),arq
);
1242 idata
=builddia(iday
,imonth
,iyear
);
1243 computedate(iyear
,imonth
,iday
,&tt
);
1244 if (isa_cols
[ISACOL_Time
]>=0) {
1245 if (sscanf(hora
,"%d:%d:%d",&tt
.tm_hour
,&tt
.tm_min
,&tt
.tm_sec
)!=3 || tt
.tm_hour
<0 || tt
.tm_hour
>=24 ||
1246 tt
.tm_min
<0 || tt
.tm_min
>=60 || tt
.tm_sec
<0 || tt
.tm_sec
>=60) {
1247 debuga(_("Invalid time found in %s\n"),arq
);
1254 debuga(_("Unknown input log file format\n"));
1258 strftime(dia
, sizeof(dia
), "%d/%m/%Y", t
);
1259 snprintf(hora
,sizeof(hora
),"%02d:%02d:%02d",t
->tm_hour
,t
->tm_min
,t
->tm_sec
);
1262 printf("DATE=%s IDATA=%d DFROM=%d DUNTIL=%d\n",date
,idata
,dfrom
,duntil
);
1264 if(date
[0] != '\0'){
1265 if(idata
< dfrom
|| idata
> duntil
) continue;
1268 // Record only hours usage which is required
1270 if( bsearch( &( t
-> tm_wday
), weekdays
.list
, weekdays
.len
, sizeof( int ), compar
) == NULL
)
1273 if( bsearch( &( t
-> tm_hour
), hours
.list
, hours
.len
, sizeof( int ), compar
) == NULL
)
1278 if(strlen(user
) > MAX_USER_LEN
) {
1279 if (debugm
) printf(_("User ID too long: %s\n"),user
);
1285 if(IncludeUsers
[0] != '\0') {
1286 sprintf(val1
,":%s:",user
);
1287 if((str
=(char *) strstr(IncludeUsers
,val1
)) == (char *) NULL
)
1292 if (debugm
) printf(_("Excluded code: %s\n"),code
);
1297 if(testvaliduserchar(user
))
1301 if((str
= strstr(user
,"%20")) != NULL
) {
1303 This is a patch introduced to solve bug #1624251 reported at sourceforge but
1304 the side effect is to truncate the name at the first space and merge the reports
1305 of people whose name is identical up to the first space.
1307 The old code used to truncate the user name at the first % if a %20 was
1308 found anywhere in the string. That means the string could be truncated
1309 at the wrong place if another % occured before the %20. This new code should
1310 avoid that problem and only truncate at the space. There is no bug
1311 report indicating that anybody noticed this.
1317 Code prior to 2.2.7 used to replace any %xx by a dot as long as a %5c was
1318 found in the user name.
1320 while((str
= strstr(user
,"%5c")) != NULL
) {
1322 for (x
=3 ; str
[x
] ; x
++) str
[x
-2]=str
[x
];
1330 The full URL is not saved in sarg log. There is no point in testing the URL to detect
1333 download_flag
=is_download_suffix(full_url
);
1334 if (download_flag
) {
1335 download_url
=full_url
;
1339 download_flag
=false;
1341 url
=process_url(full_url
,LongUrl
);
1342 if (!url
|| url
[0] == '\0') continue;
1344 if(addr
[0] != '\0'){
1345 if(strcmp(addr
,ip
)!=0) continue;
1348 if(!vhexclude(url
)) {
1349 if (debugm
) printf(_("Excluded site: %s\n"),url
);
1355 if(hm
>= 0 && hmf
>= 0) {
1356 hmr
=t
->tm_hour
*100+t
->tm_min
;
1357 if(hmr
< hm
|| hmr
> hmf
) continue;
1360 if(site
[0] != '\0'){
1361 if(strstr(url
,site
)==0) continue;
1369 if(strcmp(user
,"-") == 0 || strcmp(user
," ") == 0 || strcmp(user
,"") == 0) {
1370 if(RecordsWithoutUser
== RECORDWITHOUTUSER_IP
) {
1374 if(RecordsWithoutUser
== RECORDWITHOUTUSER_IGNORE
)
1376 if(RecordsWithoutUser
== RECORDWITHOUTUSER_EVERYBODY
)
1377 strcpy(user
,"everybody");
1380 if(NtlmUserFormat
== NTLMUSERFORMAT_USER
) {
1381 if((str
= strchr(user
,'_')) != 0) {
1382 strcpy(warea
,str
+1);
1385 if((str
= strchr(user
,'+')) != 0) {
1386 strcpy(warea
,str
+1);
1394 if(strcmp(user
,us
)!=0) continue;
1398 sprintf(wuser
,":%s:",user
);
1399 if(strstr(userfile
, wuser
) == 0)
1404 if(!vuexclude(user
)) {
1405 if (debugm
) printf(_("Excluded user: %s\n"),user
);
1411 if(strcmp(user
,"-") ==0 || strcmp(user
," ") ==0 || strcmp(user
,"") ==0 || strcmp(user
,":") ==0)
1415 if(atol(elap
)>max_elapsed
) {
1421 if((str
=(char *) strstr(linebuf
, "[SmartFilter:")) != (char *) NULL
) {
1423 sprintf(smartfilter
,"\"%s\"",str
+1);
1424 } else sprintf(smartfilter
,"\"\"");
1428 for (ufile
=first_user_file
; ufile
&& strcmp(user
,ufile
->user
->id
)!=0 ; ufile
=ufile
->next
) {
1430 if (ufile
->file
) nopen
++;
1433 ufile
=malloc(sizeof(*ufile
));
1435 debuga(_("Not enough memory to store the user %s\n"),user
);
1438 memset(ufile
,0,sizeof(*ufile
));
1439 ufile
->next
=first_user_file
;
1440 first_user_file
=ufile
;
1441 uinfo
=userinfo_create(user
);
1443 uinfo
->id_is_ip
=id_is_ip
;
1446 prev_ufile
->next
=ufile
->next
;
1447 ufile
->next
=first_user_file
;
1448 first_user_file
=ufile
;
1452 if (ufile
->file
==NULL
) {
1453 if (nopen
>=maxopenfiles
) {
1455 for (ufile1
=first_user_file
; ufile1
; ufile1
=ufile1
->next
) {
1456 if (ufile1
->file
!=NULL
) {
1457 if (x
>=maxopenfiles
) {
1458 if (fclose(ufile1
->file
)==EOF
) {
1459 debuga(_("Failed to close the log file of user %s - %s\n"),ufile1
->user
->id
,strerror(errno
));
1468 if (snprintf (tmp3
, sizeof(tmp3
), "%s/%s.unsort", tmp
, ufile
->user
->filename
)>=sizeof(tmp3
)) {
1469 debuga(_("Temporary user file name too long: %s/%s.unsort\n"), tmp
, ufile
->user
->filename
);
1472 if ((ufile
->file
= MY_FOPEN (tmp3
, "a")) == NULL
) {
1473 debuga(_("(log) Cannot open temporary file: %s - %s\n"), tmp3
, strerror(errno
));
1478 /*if ( strcmp ( user , sz_Last_User ) != 0 ) {
1479 if ( fp_Write_User )
1480 fclose( fp_Write_User ) ;
1481 sprintf (tmp3, "%s/%s.unsort", tmp, user);
1483 if ((fp_Write_User = MY_FOPEN (tmp3, "a")) == NULL) {
1484 fprintf (stderr, "%s: (log) %s: %s - %s\n", argv[0], _("Cannot open temporary file"), tmp3, strerror(errno));
1487 strcpy( sz_Last_User , user ) ;
1489 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) {
1490 debuga(_("Write error in the log file of user %s\n"),user
);
1494 if(fp_log
&& ilf
!=ILF_Sarg
)
1495 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
);
1499 if(!dataonly
&& download_flag
&& download_url
&& strstr(code
,"DENIED") == 0) {
1502 if ( ! fp_Download_Unsort
) {
1503 if ((fp_Download_Unsort
= MY_FOPEN ( sz_Download_Unsort
, "a")) == NULL
) {
1504 debuga(_("(log) Cannot open temporary file: %s - %s\n"),sz_Download_Unsort
, strerror(errno
));
1508 fprintf(fp_Download_Unsort
,"%s\t%s\t%s\t%s\t%s\n",dia
,hora
,user
,ip
,download_url
);
1511 if((ReportType
& REPORT_TYPE_DENIED
) != 0 || (ReportType
& REPORT_TYPE_AUTH_FAILURES
) != 0) {
1512 if(fp_denied
&& strstr(code
,"DENIED/403") != 0) {
1513 fprintf(fp_denied
, "%s\t%s\t%s\t%s\t%s\n",dia
,hora
,user
,ip
,urly
);
1516 if(fp_authfail
&& (strstr(code
,"DENIED/401") != 0 || strstr(code
,"DENIED/407") != 0)) {
1517 fprintf(fp_authfail
, "%s\t%s\t%s\t%s\t%s\n",dia
,hora
,user
,ip
,urly
);
1522 if (ilf
!=ILF_Sarg
) {
1523 if(!totper
|| idata
<mindate
){
1525 memcpy(&period
.start
,t
,sizeof(*t
));
1526 strcpy(start_hour
,tbuf2
);
1528 if (!totper
|| idata
>maxdate
) {
1530 memcpy(&period
.end
,t
,sizeof(*t
));
1536 printf("IP=\t%s\n",ip
);
1537 printf("USER=\t%s\n",user
);
1538 printf("ELAP=\t%s\n",elap
);
1539 printf("DATE=\t%s\n",dia
);
1540 printf("TIME=\t%s\n",hora
);
1541 printf("FUNC=\t%s\n",fun
);
1542 printf("URL=\t%s\n",url
);
1543 printf("CODE=\t%s\n",code
);
1544 printf("LEN=\t%s\n",tam
);
1552 if( ShowReadStatistics
)
1553 printf(_("SARG: Records in file: %lu, reading: %3.2f%%\n"),recs1
, (float) 100 );
1559 debuga(_(" Records read: %ld, written: %ld, excluded: %ld\n"),totregsl
,totregsg
,totregsx
);
1561 longline_destroy(&line
);
1562 if ( fp_Download_Unsort
)
1563 fclose (fp_Download_Unsort
);
1565 for (ufile
=first_user_file
; ufile
; ufile
=ufile1
) {
1567 if (ufile
->file
!=NULL
) fclose(ufile
->file
);
1572 free_excludecodes();
1578 for (ilf
=0 ; ilf
<ILF_Last
; ilf
++) totalcount
+=ilf_count
[ilf
];
1580 if(ilf_count
[ILF_Common
]>0 && ilf_count
[ILF_Squid
]>0)
1581 debuga(_("Log with mixed records format (squid and common log)\n"));
1583 if(ilf_count
[ILF_Common
]>0 && ilf_count
[ILF_Squid
]==0)
1584 debuga(_("Common log format\n"));
1586 if(ilf_count
[ILF_Common
]==0 && ilf_count
[ILF_Squid
]>0)
1587 debuga(_("Squid log format\n"));
1589 if(ilf_count
[ILF_Sarg
]>0)
1590 debuga(_("Sarg log format\n"));
1592 if(totalcount
==0 && totregsg
)
1593 debuga(_("Log with invalid format\n"));
1597 debuga(_("No records found\n"));
1599 if(fp_denied
) fclose(fp_denied
);
1600 if(fp_authfail
) fclose(fp_authfail
);
1602 if(userfile
) free(userfile
);
1607 if (date
[0]!='\0') {
1608 char date0
[30], date1
[30];
1610 strftime(date0
,sizeof(date0
),"%d/%m/%Y",&period
.start
);
1611 strftime(date1
,sizeof(date1
),"%d/%m/%Y",&period
.end
);
1612 debuga(_("Period covered by log files: %s-%s\n"),date0
,date1
);
1613 getperiod_fromrange(&period
,dfrom
,duntil
);
1615 if (getperiod_buildtext(&period
)<0) {
1616 debuga(_("Failed to build the string representation of the date range\n"));
1621 debugaz("data",dia
);
1622 debugaz("period",period
.text
);
1626 debuga(_("Period: %s\n"),period
.text
);
1631 fclose(fp_authfail
);
1633 if(fp_log
!= NULL
) {
1635 strcpy(end_hour
,tbuf2
);
1636 strftime(val2
,sizeof(val2
),"%d%m%Y",&period
.start
);
1637 strftime(val1
,sizeof(val1
),"%d%m%Y",&period
.end
);
1638 sprintf(val4
,"%s/sarg-%s_%s-%s_%s.log",ParsedOutputLog
,val2
,start_hour
,val1
,end_hour
);
1639 if (rename(arq_log
,val4
)) {
1640 debuga(_("failed to rename %s to %s - %s\n"),arq_log
,val4
,strerror(errno
));
1642 strcpy(arq_log
,val4
);
1644 if(strcmp(ParsedOutputLogCompress
,"nocompress") != 0 && ParsedOutputLogCompress
[0] != '\0') {
1646 No double quotes around ParsedOutputLogCompress because it may contain command line options. If double quotes are
1647 necessary around the command name, put them in the configuration file.
1649 sprintf(val1
,"%s \"%s\"",ParsedOutputLogCompress
,arq_log
);
1650 cstatus
=system(val1
);
1651 if (!WIFEXITED(cstatus
) || WEXITSTATUS(cstatus
)) {
1652 debuga(_("command return status %d\n"),WEXITSTATUS(cstatus
));
1653 debuga(_("command: %s\n"),val1
);
1659 debuga(_("Sarg parsed log saved as %s\n"),arq_log
);
1662 if(DataFile
[0] == '\0' && (ReportType
& REPORT_TYPE_DENIED
) != 0) {
1663 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
)) {
1664 debuga(_("Sort command too long when sorting file \"%s\" to \"%s\"\n"),denied_unsort
,denied_sort
);
1667 cstatus
=system(csort
);
1668 if (!WIFEXITED(cstatus
) || WEXITSTATUS(cstatus
)) {
1669 debuga(_("sort command return status %d\n"),WEXITSTATUS(cstatus
));
1670 debuga(_("sort command: %s\n"),csort
);
1673 if (unlink(denied_unsort
)) {
1674 debuga(_("Cannot delete %s - %s\n"),denied_unsort
,strerror(errno
));
1679 sort_users_log(tmp
, debug
);
1681 if(DataFile
[0] != '\0')
1686 if((ReportType
& REPORT_TYPE_DENIED
) != 0) {
1687 unlink(denied_sort
);
1690 if(strcmp(tmp
,"/tmp") != 0) {
1707 static void getusers(const char *pwdfile
, int debug
)
1715 debuga(_("Loading password file from %s\n"),pwdfile
);
1717 if ((fp_usr
= fopen(pwdfile
, "r")) == NULL
) {
1718 debuga(_("(getusers) Cannot open file %s - %s\n"),pwdfile
,strerror(errno
));
1722 if (fseek(fp_usr
, 0, SEEK_END
)==-1) {
1723 debuga(_("Failed to move till the end of the users file %s: %s\n"),pwdfile
,strerror(errno
));
1726 nreg
= ftell(fp_usr
);
1728 debuga(_("Cannot get the size of file %s\n"),pwdfile
);
1732 if (fseek(fp_usr
, 0, SEEK_SET
)==-1) {
1733 debuga(_("Failed to rewind the users file %s: %s\n"),pwdfile
,strerror(errno
));
1737 if((userfile
=(char *) malloc(nreg
))==NULL
){
1738 debuga(_("malloc error (%ld)\n"),nreg
);
1742 bzero(userfile
,nreg
);
1743 strcpy(userfile
,":");
1745 while(fgets(buf
,sizeof(buf
),fp_usr
)!=NULL
) {
1746 str
=strchr(buf
,':');
1748 debuga(_("You have an invalid user in your %s file\n"),pwdfile
);
1752 strcat(userfile
,buf
);