]> git.ipfire.org Git - thirdparty/sarg.git/blob - log.c
Add dynamic sorting of some tables
[thirdparty/sarg.git] / log.c
1 /*
2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
3 * 1998, 2010
4 *
5 * SARG donations:
6 * please look at http://sarg.sourceforge.net/donations.php
7 * Support:
8 * http://sourceforge.net/projects/sarg/forums/forum/363374
9 * ---------------------------------------------------------------------
10 *
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.
15 *
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.
20 *
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.
24 *
25 */
26
27 #include "include/conf.h"
28 #include "include/defs.h"
29
30 #ifdef HAVE_GETOPT_H
31 #include <getopt.h>
32 #endif
33
34 #define REPORT_EVERY_X_LINES 5000
35 #define MAX_OPEN_USER_FILES 10
36
37 struct userfilestruct
38 {
39 struct userfilestruct *next;
40 struct userinfostruct *user;
41 FILE *file;
42 };
43
44 /*@null@*/static char *userfile=NULL;
45
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,
48 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 }, 24 };
49
50 static void getusers(const char *pwdfile, int debug);
51
52 int main(int argc,char *argv[])
53 {
54 enum isa_col_id {
55 ISACOL_Ip,
56 ISACOL_UserName,
57 ISACOL_Date,
58 ISACOL_Time,
59 ISACOL_TimeTaken,
60 ISACOL_Bytes,
61 ISACOL_Uri,
62 ISACOL_Status,
63 ISACOL_Last //last entry of the list !
64 };
65 enum InputLogFormat {
66 ILF_Unknown,
67 ILF_Squid,
68 ILF_Common,
69 ILF_Sarg,
70 ILF_Isa,
71 ILF_Last //last entry of the list !
72 };
73
74 FILE *fp_in = NULL, *fp_denied=NULL, *fp_authfail=NULL, *fp_log=NULL;
75
76 char sz_Download_Unsort[ 20000 ] ;
77 FILE * fp_Download_Unsort = NULL ;
78
79 extern int optind;
80 extern int optopt;
81 extern char *optarg;
82
83 char data[255];
84 char elap[255];
85 char ip[MAXLEN];
86 char tam[255];
87 char fun[MAXLEN];
88 char wuser[MAXLEN];
89 char smartfilter[MAXLEN];
90 char dia[128];
91 char mes[30];
92 char ano[30];
93 char hora[30];
94 char wtemp[MAXLEN];
95 char date[255];
96 char arq[255];
97 char arq_log[255];
98 int hm, hmf, hmr;
99 char hm_str[15];
100 char uagent[MAXLEN];
101 char hexclude[MAXLEN];
102 char csort[MAXLEN];
103 int cstatus;
104 char tbuf2[128];
105 char zip[20];
106 char *str;
107 char tmp3[MAXLEN];
108 char denied_unsort[MAXLEN];
109 char denied_sort[MAXLEN];
110 char authfail_unsort[MAXLEN];
111 char start_hour[128];
112 char end_hour[128];
113 char *linebuf;
114 char hostname[512];
115 char *url;
116 char *urly;
117 char user[MAX_USER_LEN];
118 enum InputLogFormat ilf;
119 int ilf_count[ILF_Last];
120 int ch;
121 int x;
122 int errflg=0;
123 int puser=0;
124 bool fhost=false;
125 bool dns=false;
126 bool fuser=false;
127 int idata=0;
128 int mindate=0;
129 int maxdate=0;
130 int iarq=0;
131 int isa_ncols=0,isa_cols[ISACOL_Last];
132 bool from_stdin;
133 bool from_pipe;
134 int blen;
135 int maxopenfiles;
136 int nopen;
137 bool id_is_ip;
138 long totregsl=0;
139 long totregsg=0;
140 long totregsx=0;
141 bool totper=false;
142 long int max_elapsed=0;
143 long long int iyear, imonth, iday;
144 bool realt;
145 bool userip;
146 struct tm tt;
147 struct tm *t;
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;
154 longline line;
155 time_t tnum;
156 struct stat logstat;
157 struct userinfostruct *uinfo;
158 struct userfilestruct *first_user_file, *ufile, *ufile1, *prev_ufile;
159 static int split=0;
160 static int convert=0;
161 static int output_css=0;
162 int option_index;
163 static struct option long_options[]=
164 {
165 {"convert",no_argument,&convert,1},
166 {"css",no_argument,&output_css,1},
167 {"split",no_argument,&split,1},
168 {0,0,0,0}
169 };
170
171 #ifdef HAVE_LOCALE_H
172 setlocale(LC_TIME,"");
173 #endif
174
175 #if defined(ENABLE_NLS) && defined(HAVE_LOCALE_H)
176 if (!setlocale (LC_ALL, "")) {
177 fprintf(stderr,"SARG: Cannot set the locale LC_ALL to the environment variable\n");
178 exit(EXIT_FAILURE);
179 }
180 if (!bindtextdomain (PACKAGE_NAME, LOCALEDIR)) {
181 fprintf(stderr,"SARG: Cannot bind to text domain %s in directory %s (%s)\n",PACKAGE_NAME,LOCALEDIR,strerror(errno));
182 exit(EXIT_FAILURE);
183 }
184 if (!textdomain (PACKAGE_NAME)) {
185 fprintf(stderr,"SARG: Cannot set gettext domain for %s PACKAGE_NAME (%s)\n",PACKAGE_NAME,strerror(errno));
186 exit(EXIT_FAILURE);
187 }
188 #endif //ENABLE_NLS
189
190 BgImage[0]='\0';
191 LogoImage[0]='\0';
192 LogoText[0]='\0';
193 PasswdFile[0]='\0';
194 OutputEmail[0]='\0';
195 UserAgentLog[0]='\0';
196 ExcludeHosts[0]='\0';
197 ExcludeUsers[0]='\0';
198 ConfigFile[0]='\0';
199 code[0]='\0';
200 LastLog=0;
201 ReportType=0UL;
202 UserTabFile[0]='\0';
203 BlockIt[0]='\0';
204 ExternalCSSFile[0]='\0';
205 RedirectorLogFormat[0]='\0';
206 NRedirectorLogs=0;
207 for (ilf=0 ; ilf<ILF_Last ; ilf++) ilf_count[ilf]=0;
208
209 sprintf(ExcludeCodes,"%s/exclude_codes",SYSCONFDIR);
210 strcpy(GraphDaysBytesBarColor,"orange");
211 strcpy(BgColor,"#ffffff");
212 strcpy(TxColor,"#000000");
213 strcpy(TxBgColor,"lavender");
214 strcpy(TiColor,"darkblue");
215 strcpy(Width,"80");
216 strcpy(Height,"45");
217 strcpy(LogoTextColor,"#000000");
218 strcpy(HeaderColor,"darkblue");
219 strcpy(HeaderBgColor,"#dddddd");
220 strcpy(LogoTextColor,"#006699");
221 strcpy(FontSize,"9px");
222 strcpy(TempDir,"/tmp");
223 strcpy(OutputDir,"/var/www/html/squid-reports");
224 Ip2Name=false;
225 strcpy(DateFormat,"u");
226 OverwriteReport=false;
227 RemoveTempFiles=true;
228 strcpy(ReplaceIndex,"index.html");
229 Index=INDEX_YES;
230 RecordsWithoutUser=RECORDWITHOUTUSER_IP;
231 UseComma=0;
232 strcpy(MailUtility,"mailx");
233 TopSitesNum=100;
234 TopUsersNum=0;
235 UserIp=0;
236 TopuserSort=TOPUSER_SORT_BYTES | TOPUSER_SORT_REVERSE;
237 UserSort=USER_SORT_BYTES | USER_SORT_REVERSE;
238 TopsitesSort=TOPSITE_SORT_CONNECT | TOPSITE_SORT_REVERSE;
239 LongUrl=0;
240 strcpy(FontFace,"Verdana,Tahoma,Arial");
241 datetimeby=DATETIME_BYTE;
242 strcpy(CharSet,"ISO-8859-1");
243 Privacy=0;
244 strcpy(PrivacyString,"***.***.***.***");
245 strcpy(PrivacyStringColor,"blue");
246 SuccessfulMsg=true;
247 TopUserFields=TOPUSERFIELDS_NUM | TOPUSERFIELDS_DATE_TIME | TOPUSERFIELDS_USERID | TOPUSERFIELDS_CONNECT |
248 TOPUSERFIELDS_BYTES | TOPUSERFIELDS_SETYB | TOPUSERFIELDS_IN_CACHE_OUT |
249 TOPUSERFIELDS_USED_TIME | TOPUSERFIELDS_MILISEC | TOPUSERFIELDS_PTIME |
250 TOPUSERFIELDS_TOTAL | TOPUSERFIELDS_AVERAGE;
251 UserReportFields=USERREPORTFIELDS_CONNECT | USERREPORTFIELDS_BYTES | USERREPORTFIELDS_SETYB |
252 USERREPORTFIELDS_IN_CACHE_OUT | USERREPORTFIELDS_USED_TIME | USERREPORTFIELDS_MILISEC |
253 USERREPORTFIELDS_PTIME | USERREPORTFIELDS_TOTAL | USERREPORTFIELDS_AVERAGE;
254 strcpy(DataFileDelimiter,";");
255 DataFileFields=DATA_FIELD_USER | DATA_FIELD_DATE | DATA_FIELD_TIME | DATA_FIELD_URL | DATA_FIELD_CONNECT |
256 DATA_FIELD_BYTES | DATA_FIELD_IN_CACHE | DATA_FIELD_OUT_CACHE | DATA_FIELD_ELAPSED;
257 ShowReadStatistics=true;
258 strcpy(IndexSortOrder,"D");
259 ShowSargInfo=true;
260 ShowSargLogo=true;
261 strcpy(ParsedOutputLog,"no");
262 strcpy(ParsedOutputLogCompress,"/bin/gzip -f");
263 DisplayedValues=DISPLAY_ABBREV;
264 strcpy(HeaderFontSize,"9px");
265 strcpy(TitleFontSize,"11px");
266 strcpy(AuthUserTemplateFile,"sarg_htaccess");
267 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");
268 Graphs=true;
269 #if defined(FONTDIR)
270 strcpy(GraphFont,FONTDIR"/DejaVuSans.ttf");
271 #else
272 GraphFont[0]='\0';
273 #endif
274 strcpy(Ulimit,"20000");
275 NtlmUserFormat=NTLMUSERFORMAT_DOMAINUSER;
276 IndexTree=INDEX_TREE_FILE;
277 strcpy(RealtimeTypes,"GET,PUT,CONNECT");
278 RealtimeUnauthRec=REALTIME_UNAUTH_REC_SHOW;
279 RedirectorFilterOutDate=true;
280 DansguardianFilterOutDate=true;
281 DataFileUrl=DATAFILEURL_IP;
282 strcpy(MaxElapsed,"28800000");
283 BytesInSitesUsersReport=0;
284 UserAuthentication=0;
285 strcpy(LDAPHost,"127.0.0.1");
286 LDAPPort=389;
287 LDAPProtocolVersion=3;
288 LDAPBindDN[0]='\0';
289 LDAPBindPW[0]='\0';
290 LDAPBaseSearch[0]='\0';
291 strcpy(LDAPFilterSearch, "(uid=%s)");
292 strcpy(LDAPTargetAttr, "cn");
293 SortTableJs[0]='\0';
294
295 dia[0]='\0';
296 mes[0]='\0';
297 ano[0]='\0';
298 hora[0]='\0';
299 tmp[0]='\0';
300 tmp3[0]='\0';
301 wtemp[0]='\0';
302 us[0]='\0';
303 date[0]='\0';
304 df[0]='\0';
305 uagent[0]='\0';
306 hexclude[0]='\0';
307 addr[0]='\0';
308 hm=-1;
309 hmf=-1;
310 site[0]='\0';
311 outdir[0]='\0';
312 elap[0]='\0';
313 email[0]='\0';
314 zip[0]='\0';
315 UserInvalidChar[0]='\0';
316 DataFile[0]='\0';
317 SquidGuardConf[0]='\0';
318 DansGuardianConf[0]='\0';
319 start_hour[0]='\0';
320 end_hour[0]='\0';
321
322 denied_count=0;
323 download_count=0;
324 authfail_count=0;
325 dansguardian_count=0;
326 squidguard_count=0;
327 useragent_count=0;
328 DeniedReportLimit=10;
329 AuthfailReportLimit=10;
330 DansGuardianReportLimit=10;
331 SquidGuardReportLimit=10;
332 DownloadReportLimit=50;
333 UserReportLimit=0;
334 debug=0;
335 debugz=0;
336 debugm=0;
337 iprel=false;
338 userip=false;
339 realt=false;
340 realtime_refresh=3;
341 realtime_access_log_lines=1000;
342 cost=0.01;
343 nocost=50000000;
344 ndownload=0;
345 squid24=false;
346 dfrom=0;
347 duntil=0;
348
349 bzero(IncludeUsers, sizeof(IncludeUsers));
350 bzero(ExcludeString, sizeof(ExcludeString));
351 first_user_file=NULL;
352 memset(&period,0,sizeof(period));
353
354 NAccessLog=0;
355 for(x=0; x<MAXLOGS; x++)
356 AccessLog[x][0]='\0';
357 AccessLogFromCmdLine=0;
358 RedirectorLogFromCmdLine=0;
359
360 strcpy(Title,_("Squid User Access Report"));
361
362 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){
363 switch(ch)
364 {
365 case 0:
366 break;
367 case 'a':
368 strcpy(addr,optarg);
369 break;
370 case 'b':
371 strcpy(uagent,optarg);
372 break;
373 case 'c':
374 strcpy(hexclude,optarg);
375 break;
376 case 'd':
377 strncpy(date,optarg,sizeof(date)-1);
378 date[sizeof(date)-1]='\0';
379 date_from(date, &dfrom, &duntil);
380 break;
381 case 'e':
382 strcpy(email,optarg);
383 break;
384 case 'f':
385 strcpy(ConfigFile,optarg);
386 break;
387 case 'g':
388 strcpy(df,optarg);
389 break;
390 case 'h':
391 usage(argv[0]);
392 exit(EXIT_SUCCESS);
393 case 'i':
394 iprel=true;
395 break;
396 case 'l':
397 if (NAccessLog>=MAXLOGS) {
398 debuga(_("Too many log files passed on command line with option -l.\n"));
399 exit(EXIT_FAILURE);
400 }
401 if (strlen(optarg)>=MAX_LOG_FILELEN) {
402 debuga(_("Log file name too long passed on command line with option -l: %s\n"),optarg);
403 exit(EXIT_FAILURE);
404 }
405 strcpy(AccessLog[NAccessLog],optarg);
406 NAccessLog++;
407 AccessLogFromCmdLine++;
408 break;
409 case 'L':
410 if (NRedirectorLogs>MAX_REDIRECTOR_LOGS) {
411 debuga(_("Too many redirector logs passed on command line with option -L.\n"));
412 exit(EXIT_FAILURE);
413 }
414 if (strlen(optarg)>=MAX_REDIRECTOR_FILELEN) {
415 debuga(_("Redirector log file name too long passed on command line with opton -L: %s\n"),optarg);
416 exit(EXIT_FAILURE);
417 }
418 strcpy(RedirectorLogs[NRedirectorLogs],optarg);
419 NRedirectorLogs++;
420 RedirectorLogFromCmdLine++;
421 break;
422 case 'm':
423 debugm++;
424 break;
425 case 'n':
426 dns=true;
427 break;
428 case 'o':
429 strcpy(outdir,optarg);
430 break;
431 case 'p':
432 userip=true;
433 break;
434 case 'r':
435 realt=true;
436 break;
437 case 's':
438 strcpy(site,optarg);
439 break;
440 case 't':
441 {
442 int h1,m1,h2,m2;
443
444 if(strstr(optarg,"-") == 0) {
445 if(sscanf(optarg,"%d:%d",&h1,&m1)!=2) {
446 debuga(_("Time period passed on the command line with option -t must be MM:SS\n"));
447 exit(EXIT_FAILURE);
448 }
449 hm=h1*100+m1;
450 hmf=hm;
451 snprintf(hm_str,sizeof(hm_str),"%02d:%02d",h1,m1);
452 } else {
453 if(sscanf(optarg,"%d:%d-%d:%d",&h1,&m1,&h2,&m2)!=4) {
454 debuga(_("Time range passed on the command line with option -t must be MM:SS-MM:SS\n"));
455 exit(EXIT_FAILURE);
456 }
457 hm=h1*100+m1;
458 hmf=h2*100+m2;
459 snprintf(hm_str,sizeof(hm_str),"%02d:%02d-%02d:%02d",h1,m1,h2,m2);
460 }
461 break;
462 }
463 case 'u':
464 strcpy(us,optarg);
465 break;
466 case 'v':
467 version();
468 break;
469 case 'w':
470 strcpy(tmp,optarg);
471 break;
472 case 'x':
473 debug++;
474 break;
475 case 'y':
476 langcode++;
477 break;
478 case 'z':
479 debugz++;
480 break;
481 /*case ':':
482 debuga(_("Option -%c require an argument\n"),optopt);
483 errflg++;
484 break;*/
485 case '?':
486 usage(argv[0]);
487 exit(EXIT_FAILURE);
488 default:
489 abort();
490 }
491 }
492
493 if (errflg>0) {
494 usage(argv[0]);
495 exit(2);
496 }
497
498 if (optind<argc) {
499 for (iarq=optind ; iarq<argc ; iarq++) {
500 if (NAccessLog>=MAXLOGS) {
501 debuga(_("Too many log files passed on command line.\n"));
502 exit(EXIT_FAILURE);
503 }
504 if (strlen(argv[iarq])>=MAX_LOG_FILELEN) {
505 debuga(_("Log file name too long passed on command line: %s\n"),argv[iarq]);
506 exit(EXIT_FAILURE);
507 }
508 strcpy(AccessLog[NAccessLog],argv[iarq]);
509 NAccessLog++;
510 AccessLogFromCmdLine++;
511 }
512 }
513
514 if(debug) debuga(_("Init\n"));
515
516 if(ConfigFile[0] == '\0') snprintf(ConfigFile,sizeof(ConfigFile),"%s/sarg.conf",SYSCONFDIR);
517 if(access(ConfigFile, R_OK) != 0) {
518 debuga(_("Cannot open config file: %s - %s\n"),ConfigFile,strerror(errno));
519 exit(EXIT_FAILURE);
520 }
521
522 if(access(ConfigFile, R_OK) == 0)
523 getconf();
524
525 if(userip) UserIp=true;
526
527 if(dns) Ip2Name=true;
528
529 if(realt) {
530 realtime();
531 exit(EXIT_SUCCESS);
532 }
533
534 if(IndexTree == INDEX_TREE_FILE)
535 strcpy(ImageFile,"../images");
536 else
537 strcpy(ImageFile,"../../../images");
538
539 dataonly=0;
540 if(DataFile[0] != '\0')
541 dataonly++;
542
543 if(NAccessLog == 0) {
544 strcpy(AccessLog[0],"/var/log/squid/access.log");
545 NAccessLog++;
546 }
547
548 if(output_css) {
549 css_content(stdout);
550 exit(EXIT_SUCCESS);
551 }
552 if(split) {
553 for (iarq=0 ; iarq<NAccessLog ; iarq++)
554 splitlog(AccessLog[iarq], df, dfrom, duntil, convert);
555 exit(EXIT_SUCCESS);
556 }
557 if(convert) {
558 for (iarq=0 ; iarq<NAccessLog ; iarq++)
559 convlog(AccessLog[iarq], df, dfrom, duntil);
560 exit(EXIT_SUCCESS);
561 }
562
563 load_excludecodes(ExcludeCodes);
564
565 if(access(PasswdFile, R_OK) == 0) {
566 getusers(PasswdFile,debug);
567 puser++;
568 }
569
570 if(hexclude[0] == '\0')
571 strcpy(hexclude,ExcludeHosts);
572 if(hexclude[0] != '\0') {
573 gethexclude(hexclude,debug);
574 fhost=true;
575 }
576
577 if(ReportType == 0) {
578 ReportType=REPORT_TYPE_TOPUSERS | REPORT_TYPE_TOPSITES | REPORT_TYPE_USERS_SITES |
579 REPORT_TYPE_SITES_USERS | REPORT_TYPE_DATE_TIME | REPORT_TYPE_DENIED |
580 REPORT_TYPE_AUTH_FAILURES | REPORT_TYPE_SITE_USER_TIME_DATE | REPORT_TYPE_DOWNLOADS;
581 }
582
583 if(access(ExcludeUsers, R_OK) == 0) {
584 getuexclude(ExcludeUsers,debug);
585 fuser=true;
586 }
587
588 indexonly=0;
589 if(fuser) {
590 if(is_indexonly())
591 indexonly++;
592 }
593 if(strcmp(ExcludeUsers,"indexonly") == 0) indexonly++;
594 if(Index == INDEX_ONLY) indexonly++;
595
596 if(MaxElapsed[0] != '\0') max_elapsed=atol(MaxElapsed);
597
598 if(outdir[0] == '\0') strcpy(outdir,OutputDir);
599 strcat(outdir,"/");
600
601 if(uagent[0] == '\0') strcpy(uagent,UserAgentLog);
602
603 if(tmp[0] == '\0') strcpy(tmp,TempDir);
604 else strcpy(TempDir,tmp);
605 /*
606 For historical reasons, the temporary directory is the subdirectory "sarg" of the path
607 provided by the user.
608 */
609 strcat(tmp,"/sarg");
610
611 if (tmp[0]!='\0' && strncmp(outdir,tmp,strlen(tmp))==0) {
612 debuga(_("The output directory \"%s\" must be outside of the temporary directory \"%s\"\n"),outdir,tmp);
613 exit(EXIT_FAILURE);
614 }
615
616 if(df[0] == '\0') strcpy(df,DateFormat);
617 else strcpy(DateFormat,df);
618
619 if(df[0] == '\0') {
620 strcpy(df,"u");
621 strcpy(DateFormat,"u");
622 }
623 if (df[0]=='w')
624 IndexTree=INDEX_TREE_FILE;
625
626 if(email[0] == '\0' && OutputEmail[0] != '\0') strcpy(email,OutputEmail);
627
628 if(email[0] != '\0') {
629 my_mkdir(tmp);
630 strcpy(outdir,tmp);
631 strcat(outdir,"/");
632 }
633
634 if(access(tmp, R_OK) == 0) {
635 unlinkdir(tmp,1);
636 }
637 my_mkdir(tmp);
638 snprintf(denied_unsort,sizeof(denied_unsort),"%s/denied.log.unsort",tmp);
639 snprintf(denied_sort,sizeof(denied_sort),"%s/denied.log",tmp);
640 snprintf(authfail_unsort,sizeof(authfail_unsort),"%s/authfail.log.unsort",tmp);
641
642 if(debug) {
643 debuga(_("Parameters:\n"));
644 debuga(_(" Hostname or IP address (-a) = %s\n"),addr);
645 debuga(_(" Useragent log (-b) = %s\n"),uagent);
646 debuga(_(" Exclude file (-c) = %s\n"),hexclude);
647 debuga(_(" Date from-until (-d) = %s\n"),date);
648 debuga(_(" Email address to send reports (-e) = %s\n"),email);
649 debuga(_(" Config file (-f) = %s\n"),ConfigFile);
650 if(strcmp(df,"e") == 0)
651 debuga(_(" Date format (-g) = Europe (dd/mm/yyyy)\n"));
652 if(strcmp(df,"u") == 0)
653 debuga(_(" Date format (-g) = USA (mm/dd/yyyy)\n"));
654 if(strcmp(df,"w") == 0)
655 debuga(_(" Date format (-g) = Sites & Users (yyyy/ww)\n"));
656 debuga(_(" IP report (-i) = %s\n"),(iprel) ? _("Yes") : _("No"));
657 for (iarq=0 ; iarq<NAccessLog ; iarq++)
658 debuga(_(" Input log (-l) = %s\n"),AccessLog[iarq]);
659 for (iarq=0 ; iarq<NRedirectorLogs ; iarq++)
660 debuga(_(" Redirector log (-L) = %s\n"),RedirectorLogs[iarq]);
661 debuga(_(" Resolve IP Address (-n) = %s\n"),(Ip2Name) ? _("Yes") : _("No"));
662 debuga(_(" Output dir (-o) = %s\n"),outdir);
663 debuga(_("Use Ip Address instead of userid (-p) = %s\n"),(UserIp) ? _("Yes") : _("No"));
664 debuga(_(" Accessed site (-s) = %s\n"),site);
665 debuga(_(" Time (-t) = %s\n"),hm_str);
666 debuga(_(" User (-u) = %s\n"),us);
667 debuga(_(" Temporary dir (-w) = %s\n"),tmp);
668 debuga(_(" Debug messages (-x) = %s\n"),(debug) ? _("Yes") : _("No"));
669 debuga(_(" Process messages (-z) = %s\n"),(debugz) ? _("Yes") : _("No"));
670 debuga("\n");
671 }
672
673 if(debugm) {
674 printf(_("Parameters:\n"));
675 printf(_(" Hostname or IP address (-a) = %s\n"),addr);
676 printf(_(" Useragent log (-b) = %s\n"),uagent);
677 printf(_(" Exclude file (-c) = %s\n"),hexclude);
678 printf(_(" Date from-until (-d) = %s\n"),date);
679 printf(_(" Email address to send reports (-e) = %s\n"),email);
680 printf(_(" Config file (-f) = %s\n"),ConfigFile);
681 if(strcmp(df,"e") == 0)
682 printf(_(" Date format (-g) = Europe (dd/mm/yyyy)\n"));
683 if(strcmp(df,"u") == 0)
684 printf(_(" Date format (-g) = USA (mm/dd/yyyy)\n"));
685 if(strcmp(df,"w") == 0)
686 printf(_(" Date format (-g) = Sites & Users (yyyy/ww)\n"));
687 printf(_(" IP report (-i) = %s\n"),(iprel) ? _("Yes") : _("No"));
688 for (iarq=0 ; iarq<NAccessLog ; iarq++)
689 printf(_(" Input log (-l) = %s\n"),AccessLog[iarq]);
690 for (iarq=0 ; iarq<NRedirectorLogs ; iarq++)
691 printf(_(" Redirector log (-L) = %s\n"),RedirectorLogs[iarq]);
692 printf(_(" Resolve IP Address (-n) = %s\n"),(Ip2Name) ? _("Yes") : _("No"));
693 printf(_(" Output dir (-o) = %s\n"),outdir);
694 printf(_("Use Ip Address instead of userid (-p) = %s\n"),(UserIp) ? _("Yes") : _("No"));
695 printf(_(" Accessed site (-s) = %s\n"),site);
696 printf(_(" Time (-t) = %s\n"),hm_str);
697 printf(_(" User (-u) = %s\n"),us);
698 printf(_(" Temporary dir (-w) = %s\n"),tmp);
699 printf(_(" Debug messages (-x) = %s\n"),(debug) ? _("Yes") : _("No"));
700 printf(_(" Process messages (-z) = %s\n"),(debugz) ? _("Yes") : _("No"));
701 printf(_("sarg version: %s\n"),VERSION);
702 }
703
704 if(debug)
705 debuga(_("sarg version: %s\n"),VERSION);
706
707 #ifdef ENABLE_DOUBLE_CHECK_DATA
708 debuga(_("Sarg compiled to report warnings if the output is inconsistent\n"));
709 #endif
710
711 maxopenfiles=MAX_OPEN_USER_FILES;
712 #ifdef HAVE_RLIM_T
713 if (Ulimit[0] != '\0') {
714 struct rlimit rl;
715 long l1, l2;
716 int rc=0;
717
718 #if defined(RLIMIT_NOFILE)
719 getrlimit (RLIMIT_NOFILE, &rl);
720 #elif defined(RLIMIT_OFILE)
721 getrlimit (RLIMIT_OFILE, &rl);
722 #else
723 #warning "No rlimit resource for the number of open files"
724 #endif
725 l1 = rl.rlim_cur;
726 l2 = rl.rlim_max;
727
728 rl.rlim_cur = atol(Ulimit);
729 rl.rlim_max = atol(Ulimit);
730 #if defined(RLIMIT_NOFILE)
731 rc=setrlimit (RLIMIT_NOFILE, &rl);
732 #elif defined(RLIMIT_OFILE)
733 rc=setrlimit (RLIMIT_OFILE, &rl);
734 #else
735 #warning "No rlimit resource for the number of open files"
736 #endif
737 if(rc == -1) {
738 debuga(_("setrlimit error - %s\n"),strerror(errno));
739 }
740
741 if(debug)
742 debuga("Maximum file descriptor: cur=%ld max=%ld, changed to cur="RLIM_STRING" max="RLIM_STRING,l1,l2,rl.rlim_cur,rl.rlim_max);
743 }
744 #endif
745
746 init_usertab(UserTabFile);
747
748 if ((line=longline_create())==NULL) {
749 debuga(_("Not enough memory to read a log file\n"));
750 exit(EXIT_FAILURE);
751 }
752
753 snprintf(sz_Download_Unsort,sizeof(sz_Download_Unsort),"%s/download.unsort", tmp);
754
755 if(DataFile[0]=='\0') {
756 if((ReportType & REPORT_TYPE_DENIED) != 0) {
757 if((fp_denied=MY_FOPEN(denied_unsort,"w"))==NULL) {
758 debuga(_("(log) Cannot open file: %s - %s\n"),denied_unsort,strerror(errno));
759 exit(EXIT_FAILURE);
760 }
761 }
762
763 if((ReportType & REPORT_TYPE_DENIED) != 0 || (ReportType & REPORT_TYPE_AUTH_FAILURES) != 0) {
764 if((fp_authfail=MY_FOPEN(authfail_unsort,"w"))==NULL) {
765 debuga(_("(log) Cannot open file: %s - %s\n"),authfail_unsort,strerror(errno));
766 exit(EXIT_FAILURE);
767 }
768 }
769 }
770
771 for (iarq=0 ; iarq<NAccessLog ; iarq++) {
772 strcpy(arq,AccessLog[iarq]);
773
774 strcpy(arqtt,arq);
775
776 if(strcmp(arq,"-")==0) {
777 if(debug)
778 debuga(_("Reading access log file: from stdin\n"));
779 fp_in=stdin;
780 from_stdin=true;
781 } else {
782 if (date[0]!='\0') {
783 if (stat(arq,&logstat)!=0) {
784 debuga(_("Cannot get the modification time of input log file %s (%s). Processing it anyway\n"),arq,strerror(errno));
785 } else {
786 struct tm *logtime=localtime(&logstat.st_mtime);
787 if ((logtime->tm_year+1900)*10000+(logtime->tm_mon+1)*100+logtime->tm_mday<dfrom) {
788 debuga(_("Ignoring old log file %s\n"),arq);
789 continue;
790 }
791 }
792 }
793 fp_in=decomp(arq,&from_pipe);
794 if(fp_in==NULL) {
795 debuga(_("(log) Cannot open log file: %s - %s\n"),arq,strerror(errno));
796 exit(EXIT_FAILURE);
797 }
798 if(debug) debuga(_("Reading access log file: %s\n"),arq);
799 from_stdin=false;
800 }
801 ilf=ILF_Unknown;
802 download_flag=false;
803 // pre-read the file only if we have to show stats
804 if(ShowReadStatistics && !from_stdin && !from_pipe) {
805 size_t nread,i;
806 bool skipcr=false;
807 char tmp4[MAXLEN];
808
809 recs1=0UL;
810 recs2=0UL;
811
812 while ((nread=fread(tmp4,1,sizeof(tmp4),fp_in))>0) {
813 for (i=0 ; i<nread ; i++)
814 if (skipcr) {
815 if (tmp4[i]!='\n' && tmp4[i]!='\r') {
816 skipcr=false;
817 }
818 } else {
819 if (tmp4[i]=='\n' || tmp4[i]=='\r') {
820 skipcr=true;
821 recs1++;
822 }
823 }
824 }
825 rewind(fp_in);
826 printf(_("SARG: Records in file: %lu, reading: %3.2f%%"),recs1,(float) 0);
827 putchar('\r');
828 fflush( stdout ) ;
829 }
830
831 longline_reset(line);
832
833 while ((linebuf=longline_read(fp_in,line))!=NULL) {
834 blen=strlen(linebuf);
835
836 if (ilf==ILF_Unknown) {
837 if(strncmp(linebuf,"#Software: Mic",14) == 0) {
838 fixendofline(linebuf);
839 if (debug)
840 debuga(_("Log is from Microsoft ISA: %s\n"),linebuf);
841 ilf=ILF_Isa;
842 ilf_count[ilf]++;
843 continue;
844 }
845
846 if(strncmp(linebuf,"*** SARG Log ***",16) == 0) {
847 if (getperiod_fromsarglog(arqtt,&period)<0) {
848 debuga(_("The name of the file is invalid: %s\n"),arq);
849 exit(EXIT_FAILURE);
850 }
851 ilf=ILF_Sarg;
852 ilf_count[ilf]++;
853 continue;
854 }
855 }
856
857 if(!fp_log && strcmp(ParsedOutputLog, "no") != 0 && ilf!=ILF_Sarg) {
858 if(access(ParsedOutputLog,R_OK) != 0) {
859 my_mkdir(ParsedOutputLog);
860 }
861 sprintf(arq_log,"%s/sarg_temp.log",ParsedOutputLog);
862 if((fp_log=MY_FOPEN(arq_log,"w"))==NULL) {
863 debuga(_("(log) Cannot open log file: %s - %s\n"),arq_log,strerror(errno));
864 exit(EXIT_FAILURE);
865 }
866 fputs("*** SARG Log ***\n",fp_log);
867 }
868
869 recs2++;
870 if( ShowReadStatistics && !from_stdin && !from_pipe && --OutputNonZero<=0) {
871 double perc = recs2 * 100. / recs1 ;
872 printf(_("SARG: Records in file: %lu, reading: %3.2lf%%"),recs2,perc);
873 putchar('\r');
874 fflush (stdout);
875 OutputNonZero = REPORT_EVERY_X_LINES ;
876 }
877 if(blen < 58) continue;
878 if(strstr(linebuf,"HTTP/0.0") != 0) continue;
879 if(strstr(linebuf,"logfile turned over") != 0) continue;
880 if(linebuf[0] == ' ') continue;
881
882 // exclude_string
883 if(ExcludeString[0] != '\0') {
884 bool exstring=false;
885 getword_start(&gwarea,ExcludeString);
886 while(strchr(gwarea.current,':') != 0) {
887 if (getword_multisep(val1,sizeof(val1),&gwarea,':')<0) {
888 debuga(_("Maybe you have a broken record or garbage in your exclusion string\n"));
889 exit(EXIT_FAILURE);
890 }
891 if((str=(char *) strstr(linebuf,val1)) != (char *) NULL ) {
892 exstring=true;
893 break;
894 }
895 }
896 if(!exstring && (str=(char *) strstr(linebuf,gwarea.current)) != (char *) NULL )
897 exstring=true;
898 if(exstring) continue;
899 }
900
901 totregsl++;
902 if(debugm)
903 printf("BUF=%s\n",linebuf);
904
905 t=NULL;
906 if (ilf==ILF_Squid || ilf==ILF_Common || ilf==ILF_Unknown) {
907 getword_start(&gwarea,linebuf);
908 if (getword(data,sizeof(data),&gwarea,' ')<0) {
909 debuga(_("Maybe you have a broken time in your access.log file\n"));
910 exit(EXIT_FAILURE);
911 }
912 if((str=(char *) strchr(data, '.')) != (char *) NULL && (str=(char *) strchr(str+1, '.')) != (char *) NULL ) {
913 strcpy(ip,data);
914 strcpy(elap,"0");
915 if(squid24) {
916 if (getword(user,sizeof(user),&gwarea,' ')<0 || getword_skip(255,&gwarea,' ')<0) {
917 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
918 exit(EXIT_FAILURE);
919 }
920 } else {
921 if (getword_skip(255,&gwarea,' ')<0 || getword(user,sizeof(user),&gwarea,' ')<0) {
922 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
923 exit(EXIT_FAILURE);
924 }
925 }
926 if (getword(data,sizeof(data),&gwarea,']')<0 || getword_skip(MAXLEN,&gwarea,'"')<0 ||
927 getword(fun,sizeof(fun),&gwarea,' ')<0) {
928 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
929 exit(EXIT_FAILURE);
930 }
931 if (getword_ptr(linebuf,&url,&gwarea,' ')<0) {
932 debuga(_("Maybe you have a broken url in your %s file\n"),arq);
933 exit(EXIT_FAILURE);
934 }
935 if (getword_skip(MAXLEN,&gwarea,' ')<0) {
936 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
937 exit(EXIT_FAILURE);
938 }
939 if (getword(code2,sizeof(code2),&gwarea,' ')<0) {
940 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
941 exit(EXIT_FAILURE);
942 }
943 if (getword(tam,sizeof(tam),&gwarea,' ')<0) {
944 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
945 exit(EXIT_FAILURE);
946 }
947 if((str=(char *) strchr(gwarea.current, ' ')) != (char *) NULL ) {
948 if (getword(code,sizeof(code),&gwarea,' ')<0) {
949 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
950 exit(EXIT_FAILURE);
951 }
952 } else {
953 if (getword(code,sizeof(code),&gwarea,'\0')<0) {
954 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
955 exit(EXIT_FAILURE);
956 }
957 }
958
959 if ((str = strchr(code, ':')) != NULL)
960 *str = '/';
961
962 if(strcmp(tam,"\0") == 0)
963 strcpy(tam,"0");
964
965 ilf=ILF_Common;
966 ilf_count[ilf]++;
967
968 getword_start(&gwarea,data+1);
969 if (getword_multisep(data,sizeof(data),&gwarea,':')<0){
970 debuga(_("Maybe you have a broken date in your %s file\n"),arq);
971 exit(EXIT_FAILURE);
972 }
973 if (getword_multisep(hora,sizeof(hora),&gwarea,' ')<0){
974 debuga(_("Maybe you have a broken date in your %s file\n"),arq);
975 exit(EXIT_FAILURE);
976 }
977 getword_start(&gwarea,data);
978 if (getword_atoll(&iday,&gwarea,'/')<0){
979 debuga(_("Maybe you have a broken date in your %s file\n"),arq);
980 exit(EXIT_FAILURE);
981 }
982 if (getword(mes,sizeof(mes),&gwarea,'/')<0){
983 debuga(_("Maybe you have a broken date in your %s file\n"),arq);
984 exit(EXIT_FAILURE);
985 }
986 if (getword_atoll(&iyear,&gwarea,'/')<0){
987 debuga(_("Maybe you have a broken date in your %s file\n"),arq);
988 exit(EXIT_FAILURE);
989 }
990
991 imonth=month2num(mes)+1;
992 idata=builddia(iday,imonth,iyear);
993 computedate(iyear,imonth,iday,&tt);
994 t=&tt;
995 }
996
997 if(ilf==ILF_Unknown || ilf==ILF_Squid) {
998 if (getword(elap,sizeof(elap),&gwarea,' ')<0) {
999 debuga(_("Maybe you have a broken elapsed time in your %s file\n"),arq);
1000 exit(EXIT_FAILURE);
1001 }
1002 while(strcmp(elap,"") == 0 && gwarea.current[0] != '\0')
1003 if (getword(elap,sizeof(elap),&gwarea,' ')<0) {
1004 debuga(_("Maybe you have a broken elapsed time in your %s file\n"),arq);
1005 exit(EXIT_FAILURE);
1006 }
1007 if(strlen(elap) < 1) continue;
1008 if (getword(ip,sizeof(ip),&gwarea,' ')<0){
1009 debuga(_("Maybe you have a broken client IP address in your %s file\n"),arq);
1010 exit(EXIT_FAILURE);
1011 }
1012 if (getword(code,sizeof(code),&gwarea,' ')<0){
1013 debuga(_("Maybe you have a broken result code in your %s file\n"),arq);
1014 exit(EXIT_FAILURE);
1015 }
1016 if (getword(tam,sizeof(tam),&gwarea,' ')<0){
1017 debuga(_("Maybe you have a broken amount of data in your %s file\n"),arq);
1018 exit(EXIT_FAILURE);
1019 }
1020 if (getword(fun,sizeof(fun),&gwarea,' ')<0){
1021 debuga(_("Maybe you have a broken request method in your %s file\n"),arq);
1022 exit(EXIT_FAILURE);
1023 }
1024 if (getword_ptr(linebuf,&url,&gwarea,' ')<0){
1025 debuga(_("Maybe you have a broken url in your %s file\n"),arq);
1026 exit(EXIT_FAILURE);
1027 }
1028 if (getword(user,sizeof(user),&gwarea,' ')<0){
1029 debuga(_("Maybe you have a broken user ID in your %s file\n"),arq);
1030 exit(EXIT_FAILURE);
1031 }
1032 ilf=ILF_Squid;
1033 ilf_count[ilf]++;
1034
1035 tnum=atoi(data);
1036 t=localtime(&tnum);
1037 if (t == NULL) {
1038 debuga(_("Cannot convert the timestamp from the squid log file\n"));
1039 exit(EXIT_FAILURE);
1040 }
1041
1042 strftime(tbuf2, sizeof(tbuf2), "%H%M", t);
1043
1044 idata=(t->tm_year+1900)*10000+(t->tm_mon+1)*100+t->tm_mday;
1045 }
1046 }
1047 if (ilf==ILF_Sarg) {
1048 getword_start(&gwarea,linebuf);
1049 if (getword(data,sizeof(data),&gwarea,'\t')<0){
1050 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
1051 exit(EXIT_FAILURE);
1052 }
1053 if (getword(hora,sizeof(hora),&gwarea,'\t')<0) {
1054 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
1055 exit(EXIT_FAILURE);
1056 }
1057 if (getword(user,sizeof(user),&gwarea,'\t')<0) {
1058 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
1059 exit(EXIT_FAILURE);
1060 }
1061 if (getword(ip,sizeof(ip),&gwarea,'\t')<0) {
1062 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
1063 exit(EXIT_FAILURE);
1064 }
1065 if (getword_ptr(linebuf,&url,&gwarea,'\t')<0){
1066 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
1067 exit(EXIT_FAILURE);
1068 }
1069 if (getword(tam,sizeof(tam),&gwarea,'\t')<0){
1070 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
1071 exit(EXIT_FAILURE);
1072 }
1073 if (getword(code,sizeof(code),&gwarea,'\t')<0){
1074 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
1075 exit(EXIT_FAILURE);
1076 }
1077 if (getword(elap,sizeof(elap),&gwarea,'\t')<0){
1078 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
1079 exit(EXIT_FAILURE);
1080 }
1081 if (getword(smartfilter,sizeof(smartfilter),&gwarea,'\0')<0){
1082 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
1083 exit(EXIT_FAILURE);
1084 }
1085 getword_start(&gwarea,data);
1086 if (getword_atoll(&iday,&gwarea,'/')<0 || iday<1 || iday>31){
1087 debuga(_("Maybe you have a broken date in your %s file\n"),arq);
1088 exit(EXIT_FAILURE);
1089 }
1090 if (getword_atoll(&imonth,&gwarea,'/')<0 || imonth<1 || imonth>12){
1091 debuga(_("Maybe you have a broken date in your %s file\n"),arq);
1092 exit(EXIT_FAILURE);
1093 }
1094 if (getword_atoll(&iyear,&gwarea,'\0')<0){
1095 debuga(_("Maybe you have a broken date in your %s file\n"),arq);
1096 exit(EXIT_FAILURE);
1097 }
1098 idata=builddia(iday,imonth,iyear);
1099 computedate(iyear,imonth,iday,&tt);
1100 t=&tt;
1101 }
1102 if (ilf==ILF_Isa) {
1103 if (linebuf[0] == '#') {
1104 int ncols,cols[ISACOL_Last];
1105
1106 fixendofline(linebuf);
1107 getword_start(&gwarea,linebuf);
1108 // remove the #Fields: column at the beginning of the line
1109 if (getword_skip(1000,&gwarea,' ')<0){
1110 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
1111 exit(EXIT_FAILURE);
1112 }
1113 for (ncols=0 ; ncols<ISACOL_Last ; ncols++) cols[ncols]=-1;
1114 ncols=0;
1115 while(gwarea.current[0] != '\0') {
1116 if (getword(val1,sizeof(val1),&gwarea,'\t')<0){
1117 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
1118 exit(EXIT_FAILURE);
1119 }
1120 if(strcmp(val1,"c-ip") == 0) cols[ISACOL_Ip]=ncols;
1121 if(strcmp(val1,"cs-username") == 0) cols[ISACOL_UserName]=ncols;
1122 if(strcmp(val1,"date") == 0) cols[ISACOL_Date]=ncols;
1123 if(strcmp(val1,"time") == 0) cols[ISACOL_Time]=ncols;
1124 if(strcmp(val1,"time-taken") == 0) cols[ISACOL_TimeTaken]=ncols;
1125 if(strcmp(val1,"sc-bytes") == 0) cols[ISACOL_Bytes]=ncols;
1126 if(strcmp(val1,"cs-uri") == 0) cols[ISACOL_Uri]=ncols;
1127 if(strcmp(val1,"sc-status") == 0) cols[ISACOL_Status]=ncols;
1128 ncols++;
1129 }
1130 if (cols[ISACOL_Ip]>=0) {
1131 isa_ncols=ncols;
1132 for (ncols=0 ; ncols<ISACOL_Last ; ncols++)
1133 isa_cols[ncols]=cols[ncols];
1134 }
1135 continue;
1136 }
1137 if (!isa_ncols) continue;
1138 getword_start(&gwarea,linebuf);
1139 for (x=0 ; x<isa_ncols ; x++) {
1140 if (getword_ptr(linebuf,&str,&gwarea,'\t')<0) {
1141 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
1142 exit(EXIT_FAILURE);
1143 }
1144 if (x==isa_cols[ISACOL_Ip]) {
1145 if (strlen(str)>=sizeof(ip)) {
1146 debuga(_("Maybe you have a broken IP in your %s file\n"),arq);
1147 exit(EXIT_FAILURE);
1148 }
1149 strcpy(ip,str);
1150 } else if (x==isa_cols[ISACOL_UserName]) {
1151 if (strlen(str)>=sizeof(user)) {
1152 debuga(_("Maybe you have a broken user ID in your %s file\n"),arq);
1153 exit(EXIT_FAILURE);
1154 }
1155 strcpy(user,str);
1156 } else if (x==isa_cols[ISACOL_Date]) {
1157 if (strlen(str)>=sizeof(data)) {
1158 debuga(_("Maybe you have a broken date in your %s file\n"),arq);
1159 exit(EXIT_FAILURE);
1160 }
1161 strcpy(data,str);
1162 } else if (x==isa_cols[ISACOL_Time]) {
1163 if (strlen(str)>=sizeof(hora)) {
1164 debuga(_("Maybe you have a broken time in your %s file\n"),arq);
1165 exit(EXIT_FAILURE);
1166 }
1167 strcpy(hora,str);
1168 } else if (x==isa_cols[ISACOL_TimeTaken]) {
1169 if (strlen(str)>=sizeof(elap)) {
1170 debuga(_("Maybe you have a broken download duration in your %s file\n"),arq);
1171 exit(EXIT_FAILURE);
1172 }
1173 strcpy(elap,str);
1174 } else if (x==isa_cols[ISACOL_Bytes]) {
1175 if (strlen(str)>=sizeof(tam)) {
1176 debuga(_("Maybe you have a broken download size in your %s file\n"),arq);
1177 exit(EXIT_FAILURE);
1178 }
1179 strcpy(tam,str);
1180 } else if (x==isa_cols[ISACOL_Uri]) {
1181 url=str;
1182 } else if (x==isa_cols[ISACOL_Status]) {
1183 if (strlen(str)>=sizeof(code)) {
1184 debuga(_("Maybe you have a broken access code in your %s file\n"),arq);
1185 exit(EXIT_FAILURE);
1186 }
1187 strcpy(code,str);
1188 }
1189 }
1190
1191 if(strcmp(code,"401") == 0 || strcmp(code,"403") == 0 || strcmp(code,"407") == 0) {
1192 sprintf(val1,"DENIED/%s",code);
1193 strcpy(code,val1);
1194 }
1195 getword_start(&gwarea,data);
1196 if (getword_atoll(&iyear,&gwarea,'-')<0){
1197 debuga(_("Maybe you have a broken year in your %s file\n"),arq);
1198 exit(EXIT_FAILURE);
1199 }
1200 if (getword_atoll(&imonth,&gwarea,'-')<0){
1201 debuga(_("Maybe you have a broken month in your %s file\n"),arq);
1202 exit(EXIT_FAILURE);
1203 }
1204 if (getword_atoll(&iday,&gwarea,'\0')<0){
1205 debuga(_("Maybe you have a broken day in your %s file\n"),arq);
1206 exit(EXIT_FAILURE);
1207 }
1208
1209 idata=builddia(iday,imonth,iyear);
1210 computedate(iyear,imonth,iday,&tt);
1211 t=&tt;
1212 }
1213 if (t==NULL) {
1214 debuga(_("Unknown input log file format\n"));
1215 break;
1216 }
1217
1218 strftime(dia, sizeof(dia), "%d/%m/%Y", t);
1219 snprintf(hora,sizeof(hora),"%02d:%02d:%02d",t->tm_hour,t->tm_min,t->tm_sec);
1220
1221 if(debugm)
1222 printf("DATE=%s IDATA=%d DFROM=%d DUNTIL=%d\n",date,idata,dfrom,duntil);
1223
1224 if(date[0] != '\0'){
1225 if(idata < dfrom || idata > duntil) continue;
1226 }
1227
1228 // Record only hours usage which is required
1229 if (t) {
1230 if( bsearch( &( t -> tm_wday ), weekdays.list, weekdays.len,
1231 sizeof( int ), compar ) == NULL )
1232 continue;
1233
1234 if( bsearch( &( t -> tm_hour ), hours.list, hours.len,
1235 sizeof( int ), compar ) == NULL )
1236 continue;
1237 }
1238
1239
1240 if(strlen(user) > MAX_USER_LEN) {
1241 if (debugm) printf(_("User ID too long: %s\n"),user);
1242 totregsx++;
1243 continue;
1244 }
1245
1246 // include_users
1247 if(IncludeUsers[0] != '\0') {
1248 sprintf(val1,":%s:",user);
1249 if((str=(char *) strstr(IncludeUsers,val1)) == (char *) NULL )
1250 continue;
1251 }
1252
1253 if(vercode(code)) {
1254 if (debugm) printf(_("Excluded code: %s\n"),code);
1255 totregsx++;
1256 continue;
1257 }
1258
1259 if(testvaliduserchar(user))
1260 continue;
1261
1262 #if 0
1263 if((str = strstr(user,"%20")) != NULL) {
1264 /*
1265 This is a patch introduced to solve bug #1624251 reported at sourceforge but
1266 the side effect is to truncate the name at the first space and merge the reports
1267 of people whose name is identical up to the first space.
1268
1269 The old code used to truncate the user name at the first % if a %20 was
1270 found anywhere in the string. That means the string could be truncated
1271 at the wrong place if another % occured before the %20. This new code should
1272 avoid that problem and only truncate at the space. There is no bug
1273 report indicating that anybody noticed this.
1274 */
1275 *str='\0';
1276 }
1277
1278 /*
1279 Code prior to 2.2.7 used to replace any %xx by a dot as long as a %5c was
1280 found in the user name.
1281 */
1282 while((str = strstr(user,"%5c")) != NULL) {
1283 *str='.';
1284 for (x=3 ; str[x] ; x++) str[x-2]=str[x];
1285 }
1286 #endif
1287
1288 urly=url;
1289
1290 if(ilf!=ILF_Sarg) {
1291 /*
1292 The full URL is not saved in sarg log. There is no point in testing the URL to detect
1293 a downloaded file.
1294 */
1295 download_flag=is_download_suffix(url);
1296 if (download_flag) {
1297 download_url=url;
1298 download_count++;
1299 }
1300 } else
1301 download_flag=false;
1302
1303 // remove any protocol:// at the beginning of the URL
1304 if ((str = strchr(url,'/')) != NULL && str[1] == '/') {
1305 int i;
1306
1307 str+=2;
1308 for (i=0 ; str[i] ; i++)
1309 url[i]=str[i];
1310 url[i]='\0';
1311 }
1312
1313 if(!LongUrl) {
1314 url_hostname(url,hostname,sizeof(hostname));
1315 url=hostname;
1316 }
1317
1318 if(url[0] == '\0') continue;
1319
1320 if(addr[0] != '\0'){
1321 if(strcmp(addr,ip)!=0) continue;
1322 }
1323 if(fhost) {
1324 if(!vhexclude(url)) {
1325 if (debugm) printf(_("Excluded site: %s\n"),url);
1326 totregsx++;
1327 continue;
1328 }
1329 }
1330
1331 if(hm >= 0 && hmf >= 0) {
1332 hmr=t->tm_hour*100+t->tm_min;
1333 if(hmr < hm || hmr > hmf) continue;
1334 }
1335
1336 if(site[0] != '\0'){
1337 if(strstr(url,site)==0) continue;
1338 }
1339
1340 if(UserIp) {
1341 strcpy(user,ip);
1342 id_is_ip=true;
1343 } else {
1344 id_is_ip=false;
1345 if(strcmp(user,"-") == 0 || strcmp(user," ") == 0 || strcmp(user,"") == 0) {
1346 if(RecordsWithoutUser == RECORDWITHOUTUSER_IP) {
1347 strcpy(user,ip);
1348 id_is_ip=true;
1349 }
1350 if(RecordsWithoutUser == RECORDWITHOUTUSER_IGNORE)
1351 continue;
1352 if(RecordsWithoutUser == RECORDWITHOUTUSER_EVERYBODY)
1353 strcpy(user,"everybody");
1354 } else {
1355 strlow(user);
1356 if(NtlmUserFormat == NTLMUSERFORMAT_USER) {
1357 if((str = strchr(user,'_')) != 0) {
1358 strcpy(warea,str+1);
1359 strcpy(user,warea);
1360 }
1361 if((str = strchr(user,'+')) != 0) {
1362 strcpy(warea,str+1);
1363 strcpy(user,warea);
1364 }
1365 }
1366 }
1367 }
1368
1369 if(us[0] != '\0'){
1370 if(strcmp(user,us)!=0) continue;
1371 }
1372
1373 if(puser) {
1374 sprintf(wuser,":%s:",user);
1375 if(strstr(userfile, wuser) == 0)
1376 continue;
1377 }
1378
1379 if(fuser) {
1380 if(!vuexclude(user)) {
1381 if (debugm) printf(_("Excluded user: %s\n"),user);
1382 totregsx++;
1383 continue;
1384 }
1385 }
1386
1387 if(strcmp(user,"-") ==0 || strcmp(user," ") ==0 || strcmp(user,"") ==0 || strcmp(user,":") ==0)
1388 continue;
1389
1390 if(max_elapsed) {
1391 if(atol(elap)>max_elapsed) {
1392 elap[0]='0';
1393 elap[1]='\0';
1394 }
1395 }
1396
1397 if((str=(char *) strstr(linebuf, "[SmartFilter:")) != (char *) NULL ) {
1398 fixendofline(str);
1399 sprintf(smartfilter,"\"%s\"",str+1);
1400 } else sprintf(smartfilter,"\"\"");
1401
1402 nopen=0;
1403 prev_ufile=NULL;
1404 for (ufile=first_user_file ; ufile && strcmp(user,ufile->user->id)!=0 ; ufile=ufile->next) {
1405 prev_ufile=ufile;
1406 if (ufile->file) nopen++;
1407 }
1408 if (!ufile) {
1409 ufile=malloc(sizeof(*ufile));
1410 if (!ufile) {
1411 debuga(_("Not enough memory to store the user %s\n"),user);
1412 exit(EXIT_FAILURE);
1413 }
1414 memset(ufile,0,sizeof(*ufile));
1415 ufile->next=first_user_file;
1416 first_user_file=ufile;
1417 uinfo=userinfo_create(user);
1418 ufile->user=uinfo;
1419 uinfo->id_is_ip=id_is_ip;
1420 } else {
1421 if (prev_ufile) {
1422 prev_ufile->next=ufile->next;
1423 ufile->next=first_user_file;
1424 first_user_file=ufile;
1425 }
1426 }
1427
1428 if (ufile->file==NULL) {
1429 if (nopen>=maxopenfiles) {
1430 x=0;
1431 for (ufile1=first_user_file ; ufile1 ; ufile1=ufile1->next) {
1432 if (ufile1->file!=NULL) {
1433 if (x>=maxopenfiles) {
1434 if (fclose(ufile1->file)==EOF) {
1435 debuga(_("Failed to close the log file of user %s - %s\n"),ufile1->user->id,strerror(errno));
1436 exit(EXIT_FAILURE);
1437 }
1438 ufile1->file=NULL;
1439 }
1440 x++;
1441 }
1442 }
1443 }
1444 if (snprintf (tmp3, sizeof(tmp3), "%s/%s.unsort", tmp, ufile->user->filename)>=sizeof(tmp3)) {
1445 debuga(_("Temporary user file name too long: %s/%s.unsort\n"), tmp, ufile->user->filename);
1446 exit(EXIT_FAILURE);
1447 }
1448 if ((ufile->file = MY_FOPEN (tmp3, "a")) == NULL) {
1449 debuga(_("(log) Cannot open temporary file: %s - %s\n"), tmp3, strerror(errno));
1450 exit (1);
1451 }
1452 }
1453
1454 /*if ( strcmp ( user , sz_Last_User ) != 0 ) {
1455 if ( fp_Write_User )
1456 fclose( fp_Write_User ) ;
1457 sprintf (tmp3, "%s/%s.unsort", tmp, user);
1458
1459 if ((fp_Write_User = MY_FOPEN (tmp3, "a")) == NULL) {
1460 fprintf (stderr, "%s: (log) %s: %s - %s\n", argv[0], _("Cannot open temporary file"), tmp3, strerror(errno));
1461 exit (1);
1462 }
1463 strcpy( sz_Last_User , user ) ;
1464 }*/
1465 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) {
1466 debuga(_("Write error in the log file of user %s\n"),user);
1467 exit(EXIT_FAILURE);
1468 }
1469
1470 if(fp_log && ilf!=ILF_Sarg)
1471 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);
1472
1473 totregsg++;
1474
1475 if(!dataonly && download_flag && download_url && strstr(code,"DENIED") == 0) {
1476 ndownload = 1;
1477
1478 if ( ! fp_Download_Unsort ) {
1479 if ((fp_Download_Unsort = MY_FOPEN ( sz_Download_Unsort, "a")) == NULL) {
1480 debuga(_("(log) Cannot open temporary file: %s - %s\n"),sz_Download_Unsort, strerror(errno));
1481 exit (1);
1482 }
1483 }
1484 fprintf(fp_Download_Unsort,"%s\t%s\t%s\t%s\t%s\n",dia,hora,user,ip,download_url);
1485 }
1486
1487 if((ReportType & REPORT_TYPE_DENIED) != 0 || (ReportType & REPORT_TYPE_AUTH_FAILURES) != 0) {
1488 if(fp_denied && strstr(code,"DENIED/403") != 0) {
1489 fprintf(fp_denied, "%s\t%s\t%s\t%s\t%s\n",dia,hora,user,ip,urly);
1490 denied_count++;
1491 }
1492 if(fp_authfail && (strstr(code,"DENIED/401") != 0 || strstr(code,"DENIED/407") != 0)) {
1493 fprintf(fp_authfail, "%s\t%s\t%s\t%s\t%s\n",dia,hora,user,ip,urly);
1494 authfail_count++;
1495 }
1496 }
1497
1498 if (ilf!=ILF_Sarg) {
1499 if(!totper || idata<mindate){
1500 mindate=idata;
1501 memcpy(&period.start,t,sizeof(*t));
1502 strcpy(start_hour,tbuf2);
1503 }
1504 if (!totper || idata>maxdate) {
1505 maxdate=idata;
1506 memcpy(&period.end,t,sizeof(*t));
1507 }
1508 totper=true;
1509 }
1510
1511 if(debugm){
1512 printf("IP=\t%s\n",ip);
1513 printf("USER=\t%s\n",user);
1514 printf("ELAP=\t%s\n",elap);
1515 printf("DATE=\t%s\n",dia);
1516 printf("TIME=\t%s\n",hora);
1517 printf("FUNC=\t%s\n",fun);
1518 printf("URL=\t%s\n",url);
1519 printf("CODE=\t%s\n",code);
1520 printf("LEN=\t%s\n",tam);
1521 }
1522 }
1523 if (!from_stdin) {
1524 if (from_pipe)
1525 pclose(fp_in);
1526 else {
1527 fclose(fp_in);
1528 if( ShowReadStatistics )
1529 printf(_("SARG: Records in file: %lu, reading: %3.2f%%\n"),recs1, (float) 100 );
1530 }
1531 }
1532 }
1533
1534 if (debug)
1535 debuga(_(" Records read: %ld, written: %ld, excluded: %ld\n"),totregsl,totregsg,totregsx);
1536
1537 longline_destroy(&line);
1538 if ( fp_Download_Unsort )
1539 fclose (fp_Download_Unsort);
1540
1541 for (ufile=first_user_file ; ufile ; ufile=ufile1) {
1542 ufile1=ufile->next;
1543 if (ufile->file!=NULL) fclose(ufile->file);
1544 free(ufile);
1545 }
1546
1547 free_download();
1548 free_excludecodes();
1549 free_exclude();
1550
1551 if(debug) {
1552 int totalcount=0;
1553
1554 for (ilf=0 ; ilf<ILF_Last ; ilf++) totalcount+=ilf_count[ilf];
1555
1556 if(ilf_count[ILF_Common]>0 && ilf_count[ILF_Squid]>0)
1557 debuga(_("Log with mixed records format (squid and common log)\n"));
1558
1559 if(ilf_count[ILF_Common]>0 && ilf_count[ILF_Squid]==0)
1560 debuga(_("Common log format\n"));
1561
1562 if(ilf_count[ILF_Common]==0 && ilf_count[ILF_Squid]>0)
1563 debuga(_("Squid log format\n"));
1564
1565 if(ilf_count[ILF_Sarg]>0)
1566 debuga(_("Sarg log format\n"));
1567
1568 if(totalcount==0 && totregsg)
1569 debuga(_("Log with invalid format\n"));
1570 }
1571
1572 if(!totregsg){
1573 debuga(_("No records found\n"));
1574 debuga(_("End\n"));
1575 if(fp_denied) fclose(fp_denied);
1576 if(fp_authfail) fclose(fp_authfail);
1577 userinfo_free();
1578 if(userfile) free(userfile);
1579 close_usertab();
1580 exit(EXIT_SUCCESS);
1581 }
1582
1583 if (date[0]!='\0') {
1584 char date0[30], date1[30];
1585
1586 strftime(date0,sizeof(date0),"%d/%m/%Y",&period.start);
1587 strftime(date1,sizeof(date1),"%d/%m/%Y",&period.end);
1588 debuga(_("Period covered by log files: %s-%s\n"),date0,date1);
1589 getperiod_fromrange(&period,dfrom,duntil);
1590 }
1591 if (getperiod_buildtext(&period)<0) {
1592 debuga(_("Failed to build the string representation of the date range\n"));
1593 exit(EXIT_FAILURE);
1594 }
1595
1596 if(debugz){
1597 debugaz("data",dia);
1598 debugaz("period",period.text);
1599 }
1600
1601 if(debug)
1602 debuga(_("Period: %s\n"),period.text);
1603
1604 // fclose(fp_ou);
1605 if(fp_denied)
1606 fclose(fp_denied);
1607 if(fp_authfail)
1608 fclose(fp_authfail);
1609
1610 if(fp_log != NULL) {
1611 fclose(fp_log);
1612 strcpy(end_hour,tbuf2);
1613 strftime(val2,sizeof(val2),"%d%m%Y",&period.start);
1614 strftime(val1,sizeof(val1),"%d%m%Y",&period.end);
1615 sprintf(val4,"%s/sarg-%s_%s-%s_%s.log",ParsedOutputLog,val2,start_hour,val1,end_hour);
1616 if (rename(arq_log,val4)) {
1617 debuga(_("failed to rename %s to %s - %s\n"),arq_log,val4,strerror(errno));
1618 } else {
1619 strcpy(arq_log,val4);
1620
1621 if(strcmp(ParsedOutputLogCompress,"nocompress") != 0 && ParsedOutputLogCompress[0] != '\0') {
1622 /*
1623 No double quotes around ParsedOutputLogCompress because it may contain command line options. If double quotes are
1624 necessary around the command name, put them in the configuration file.
1625 */
1626 sprintf(val1,"%s \"%s\"",ParsedOutputLogCompress,arq_log);
1627 cstatus=system(val1);
1628 if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
1629 debuga(_("command return status %d\n"),WEXITSTATUS(cstatus));
1630 debuga(_("command: %s\n"),val1);
1631 exit(EXIT_FAILURE);
1632 }
1633 }
1634 }
1635 if(debug)
1636 debuga(_("Sarg parsed log saved as %s\n"),arq_log);
1637 }
1638
1639 if(DataFile[0] == '\0' && (ReportType & REPORT_TYPE_DENIED) != 0) {
1640 sprintf(csort,"sort -T \"%s\" -k 3,3 -k 5,5 -o \"%s\" \"%s\"",tmp,denied_sort,denied_unsort);
1641 cstatus=system(csort);
1642 if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
1643 debuga(_("sort command return status %d\n"),WEXITSTATUS(cstatus));
1644 debuga(_("sort command: %s\n"),csort);
1645 exit(EXIT_FAILURE);
1646 }
1647 unlink(denied_unsort);
1648 }
1649
1650 sort_users_log(tmp, debug);
1651
1652 if(DataFile[0] != '\0')
1653 data_file(tmp);
1654 else
1655 gerarel();
1656
1657 if((ReportType & REPORT_TYPE_DENIED) != 0)
1658 unlink(denied_sort);
1659
1660 if(strcmp(tmp,"/tmp") != 0) {
1661 unlinkdir(tmp,0);
1662 }
1663
1664 userinfo_free();
1665 if(userfile)
1666 free(userfile);
1667 close_usertab();
1668
1669 if(debug)
1670 debuga(_("End\n"));
1671
1672 exit(EXIT_SUCCESS);
1673
1674 }
1675
1676
1677 static void getusers(const char *pwdfile, int debug)
1678 {
1679
1680 FILE *fp_usr;
1681 char buf[255];
1682 char *str;
1683 long int nreg=0;
1684
1685 if(debug)
1686 debuga(_("Loading password file from %s\n"),pwdfile);
1687
1688 if ((fp_usr = fopen(pwdfile, "r")) == NULL) {
1689 debuga(_("(getusers) Cannot open file %s - %s\n"),pwdfile,strerror(errno));
1690 exit(EXIT_FAILURE);
1691 }
1692
1693 if (fseek(fp_usr, 0, SEEK_END)==-1) {
1694 debuga(_("Failed to move till the end of the users file %s: %s\n"),pwdfile,strerror(errno));
1695 exit(EXIT_FAILURE);
1696 }
1697 nreg = ftell(fp_usr);
1698 if (nreg<0) {
1699 debuga(_("Cannot get the size of file %s\n"),pwdfile);
1700 exit(EXIT_FAILURE);
1701 }
1702 nreg = nreg+5000;
1703 if (fseek(fp_usr, 0, SEEK_SET)==-1) {
1704 debuga(_("Failed to rewind the users file %s: %s\n"),pwdfile,strerror(errno));
1705 exit(EXIT_FAILURE);
1706 }
1707
1708 if((userfile=(char *) malloc(nreg))==NULL){
1709 debuga(_("malloc error (%ld)\n"),nreg);
1710 exit(EXIT_FAILURE);
1711 }
1712
1713 bzero(userfile,nreg);
1714 strcpy(userfile,":");
1715
1716 while(fgets(buf,sizeof(buf),fp_usr)!=NULL) {
1717 str=strchr(buf,':');
1718 if (!str) {
1719 debuga(_("You have an invalid user in your %s file\n"),pwdfile);
1720 exit(EXIT_FAILURE);
1721 }
1722 str[1]='\0';
1723 strcat(userfile,buf);
1724 }
1725
1726 fclose(fp_usr);
1727
1728 return;
1729 }