]> git.ipfire.org Git - thirdparty/sarg.git/blobdiff - log.c
Build the .htaccess of each report out of a template file.
[thirdparty/sarg.git] / log.c
diff --git a/log.c b/log.c
index a7a1002b4eb5ded83f7b3067e946d6a14ed50a77..d9c2fc811331e76a6a61f38f7a13cbb4575ed1d9 100644 (file)
--- a/log.c
+++ b/log.c
@@ -1,10 +1,11 @@
 /*
- * AUTHOR: Pedro Lineu Orso                         pedro.orso@gmail.com
- *                                                            1998, 2009
  * SARG Squid Analysis Report Generator      http://sarg.sourceforge.net
+ *                                                            1998, 2010
  *
  * SARG donations:
  *      please look at http://sarg.sourceforge.net/donations.php
+ * Support:
+ *     http://sourceforge.net/projects/sarg/forums/forum/363374
  * ---------------------------------------------------------------------
  *
  *  This program is free software; you can redistribute it and/or modify
 #include "include/defs.h"
 
 #define REPORT_EVERY_X_LINES 5000
+#define MAX_OPEN_USER_FILES 10
 
+struct userfilestruct
+{
+   struct userfilestruct *next;
+   struct userinfostruct *user;
+   FILE *file;
+};
 
-char *userfile;
-char *excludefile;
-char *excludeuser;
-
-int bool_ShowReadStatistics ;
+static char *userfile=NULL;
 
 numlist weekdays = { { 0, 1, 2, 3, 4, 5, 6 }, 7 };
 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 };
 
 static void getusers(const char *pwdfile, int debug);
-static void gethexclude(const char *hexfile, int debug);
-static void getuexclude(const char *uexfile, int debug);
 
 int main(int argc,char *argv[])
 {
@@ -69,7 +71,6 @@ int main(int argc,char *argv[])
 
    char sz_Download_Unsort[ 20000 ] ;
    FILE * fp_Download_Unsort = NULL ;
-   FILE * fp_Write_User = NULL ;
 
    extern int optind;
    extern int optopt;
@@ -78,7 +79,6 @@ int main(int argc,char *argv[])
    char data[255];
    char elap[255];
    char ip[MAXLEN];
-   char msg[MAXLEN];
    char tam[255];
    char fun[MAXLEN];
    char wuser[MAXLEN];
@@ -103,12 +103,22 @@ int main(int argc,char *argv[])
    char tbuf2[128];
    char zip[20];
    char *str;
-   char bufz[MAXLEN];
-   char bufy[MAXLEN];
+   char tmp2[MAXLEN];
+   char tmp3[MAXLEN];
+   char denied_unsort[MAXLEN];
+   char denied_sort[MAXLEN];
+   char authfail_unsort[MAXLEN];
+   char start_hour[128];
+   char end_hour[128];
+   char *linebuf;
+   char hostname[512];
+   char *url;
+   char *urly;
+   char user[MAX_USER_LEN];
    enum InputLogFormat ilf;
    int ilf_count[ILF_Last];
    int  ch;
-   int  x, l;
+   int  x;
    int  errflg=0;
    int  puser=0;
    int  fhost=0;
@@ -120,6 +130,10 @@ int main(int argc,char *argv[])
    int  exstring=0;
    int isa_ncols=0,isa_cols[ISACOL_Last];
    int from_stdin;
+   int blen;
+   int maxopenfiles;
+   int nopen;
+   int id_is_ip;
    long totregsl=0;
    long totregsg=0;
    long totregsx=0;
@@ -130,25 +144,35 @@ int main(int argc,char *argv[])
    unsigned long recs1=0UL;
    unsigned long recs2=0UL;
    int OutputNonZero = REPORT_EVERY_X_LINES ;
-   int download_flag;
-   char download_url[MAXLEN];
-   char sz_Last_User[MAXLEN]="";
+   int download_flag=0;
+   char *download_url=NULL;
    struct getwordstruct gwarea;
+   struct longlinestruct line;
+   struct userinfostruct *uinfo;
+   struct userfilestruct *first_user_file, *ufile, *ufile1, *prev_ufile;
+
+#ifdef HAVE_LOCALE_H
+   setlocale(LC_TIME,"");
+#endif
+
+#if defined(ENABLE_NLS) && defined(HAVE_LOCALE_H)
+   setlocale (LC_ALL, "");
+   bindtextdomain (PACKAGE_NAME, LOCALEDIR);
+   textdomain (PACKAGE_NAME);
+#endif //ENABLE_NLS
 
    BgImage[0]='\0';
    LogoImage[0]='\0';
    LogoText[0]='\0';
    PasswdFile[0]='\0';
    OutputEmail[0]='\0';
-   Ip2Name[0]='\0';
    UserAgentLog[0]='\0';
    ExcludeHosts[0]='\0';
    ExcludeUsers[0]='\0';
    ConfigFile[0]='\0';
    code[0]='\0';
-   LastLog[0]='\0';
-   UserIp[0]='\0';
-   ReportType[0]='\0';
+   LastLog=0;
+   ReportType=0UL;
    UserTabFile[0]='\0';
    BlockIt[0]='\0';
    ExternalCSSFile[0]='\0';
@@ -171,62 +195,78 @@ int main(int argc,char *argv[])
    strcpy(FontSize,"9px");
    strcpy(TempDir,"/tmp");
    strcpy(OutputDir,"/var/www/html/squid-reports");
-   strcpy(Ip2Name,"no");
+   Ip2Name=0;
    strcpy(DateFormat,"u");
-   strcpy(OverwriteReport,"no");
-   strcpy(RemoveTempFiles,"yes");
+   OverwriteReport=0;
+   RemoveTempFiles=1;
    strcpy(ReplaceIndex,"index.html");
-   strcpy(Index,"yes");
-   strcpy(RecordsWithoutUser,"ip");
-   strcpy(UseComma,"no");
+   Index=INDEX_YES;
+   RecordsWithoutUser=RECORDWITHOUTUSER_IP;
+   UseComma=0;
    strcpy(MailUtility,"mailx");
-   strcpy(TopSitesNum,"100");
-   strcpy(UserIp,"no");
+   TopSitesNum=100;
+   TopUsersNum=0;
+   UserIp=0;
    strcpy(TopuserSortField,"BYTES");
    strcpy(UserSortField,"BYTES");
    strcpy(TopuserSortOrder,"reverse");
    strcpy(UserSortOrder,"reverse");
    strcpy(TopsitesSortField,"CONNECT");
    strcpy(TopsitesSortType,"D");
-   strcpy(LongUrl,"no");
-   strcpy(language,"English");
+   LongUrl=0;
    strcpy(FontFace,"Verdana,Tahoma,Arial");
    strcpy(datetimeby,"elap");
    strcpy(CharSet,"ISO-8859-1");
-   strcpy(Privacy,"no");
+   Privacy=0;
    strcpy(PrivacyString,"***.***.***.***");
    strcpy(PrivacyStringColor,"blue");
-   strcpy(SuccessfulMsg,"yes");
-   strcpy(TopUserFields,"NUM DATE_TIME USERID CONNECT BYTES %BYTES IN-CACHE-OUT USED_TIME MILISEC %TIME TOTAL AVERAGE");
-   strcpy(UserReportFields,"CONNECT BYTES %BYTES IN-CACHE-OUT USED_TIME MILISEC %TIME TOTAL AVERAGE");
+   SuccessfulMsg=1;
+   TopUserFields=TOPUSERFIELDS_NUM | TOPUSERFIELDS_DATE_TIME | TOPUSERFIELDS_USERID | TOPUSERFIELDS_CONNECT |
+                 TOPUSERFIELDS_BYTES | TOPUSERFIELDS_SETYB | TOPUSERFIELDS_IN_CACHE_OUT |
+                 TOPUSERFIELDS_USED_TIME | TOPUSERFIELDS_MILISEC | TOPUSERFIELDS_PTIME |
+                 TOPUSERFIELDS_TOTAL | TOPUSERFIELDS_AVERAGE;
+   UserReportFields=USERREPORTFIELDS_CONNECT | USERREPORTFIELDS_BYTES | USERREPORTFIELDS_SETYB |
+                    USERREPORTFIELDS_IN_CACHE_OUT | USERREPORTFIELDS_USED_TIME | USERREPORTFIELDS_MILISEC |
+                    USERREPORTFIELDS_PTIME | USERREPORTFIELDS_TOTAL | USERREPORTFIELDS_AVERAGE;
    strcpy(DataFileDelimiter,";");
-   strcpy(DataFileFields,"user;date;time;url;connect;bytes;in_cache;out_cache;elapsed");
-   strcpy(SiteUserTimeDateType,"table");
-   strcpy(ShowReadStatistics,"yes");
+   DataFileFields=DATA_FIELD_USER | DATA_FIELD_DATE | DATA_FIELD_TIME | DATA_FIELD_URL | DATA_FIELD_CONNECT |
+                  DATA_FIELD_BYTES | DATA_FIELD_IN_CACHE | DATA_FIELD_OUT_CACHE | DATA_FIELD_ELAPSED;
+   ShowReadStatistics=1;
    strcpy(IndexSortOrder,"D");
-   strcpy(ShowSargInfo,"yes");
-   strcpy(ShowSargLogo,"yes");
+   ShowSargInfo=1;
+   ShowSargLogo=1;
    strcpy(ParsedOutputLog,"no");
-   strcpy(ParsedOutputLogCompress,"/bin/gzip");
+   strcpy(ParsedOutputLogCompress,"/bin/gzip -f");
    strcpy(DisplayedValues,"abbreviation");
    strcpy(HeaderFontSize,"9px");
    strcpy(TitleFontSize,"11px");
-   strcpy(AuthUserFile,"/usr/local/sarg/passwd");
-   strcpy(AuthName,"SARG, Restricted Access");
-   strcpy(AuthType,"basic");
-   strcpy(Require,"require user admin %u");
-   strcpy(DownloadSuffix,"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");
-   strcpy(Graphs,"yes");
+   strcpy(AuthUserTemplateFile,"sarg_htaccess");
+   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");
+   Graphs=1;
+#if defined(FONTDIR)
+   strcpy(GraphFont,FONTDIR"/DejaVuSans.ttf");
+#else
+   GraphFont[0]='\0';
+#endif
    strcpy(Ulimit,"20000");
-   strcpy(NtlmUserFormat,"domainname+username");
-   strcpy(IndexTree,"file");
+   NtlmUserFormat=NTLMUSERFORMAT_DOMAINUSER;
+   IndexTree=INDEX_TREE_FILE;
    strcpy(RealtimeTypes,"GET,PUT,CONNECT");
    strcpy(RealtimeUnauthRec,"show");
-   strcpy(SquidguardIgnoreDate,"off");
-   strcpy(DansguardianIgnoreDate,"off");
-   strcpy(DataFileUrl,"ip");
+   SquidguardIgnoreDate=0;
+   DansguardianIgnoreDate=0;
+   DataFileUrl=DATAFILEURL_IP;
    strcpy(MaxElapsed,"28800000");
-   strcpy(BytesInSitesUsersReport,"no");
+   BytesInSitesUsersReport=0;
+   UserAuthentication=0;
+   strcpy(LDAPHost,"127.0.0.1");
+   LDAPPort=389;
+   LDAPProtocolVersion=3;
+   LDAPBindDN[0]='\0';
+   LDAPBindPW[0]='\0';
+   LDAPBaseSearch[0]='\0';
+   strcpy(LDAPFilterSearch, "uid=%s");
+   strcpy(LDAPTargetAttr, "cn");
 
    dia[0]='\0';
    mes[0]='\0';
@@ -254,12 +294,15 @@ int main(int argc,char *argv[])
    DataFile[0]='\0';
    SquidGuardConf[0]='\0';
    DansGuardianConf[0]='\0';
+   start_hour[0]='\0';
+   end_hour[0]='\0';
 
    denied_count=0;
    download_count=0;
    authfail_count=0;
    dansguardian_count=0;
    squidguard_count=0;
+   useragent_count=0;
    DeniedReportLimit=10;
    AuthfailReportLimit=10;
    DansGuardianReportLimit=10;
@@ -274,7 +317,6 @@ int main(int argc,char *argv[])
    color1=0;
    color2=0;
    color3=0;
-   dotinuser=0;
    realt=0;
    realtime_refresh=3;
    realtime_access_log_lines=1000;
@@ -283,20 +325,16 @@ int main(int argc,char *argv[])
    ndownload=0;
    squid24=0;
 
-   bzero(IncludeUsers, MAXLEN);
-   bzero(ExcludeString, MAXLEN);
-
-#ifdef HAVE_LOCALE_H
-   setlocale(LC_TIME,"");
-#endif
+   bzero(IncludeUsers, sizeof(IncludeUsers));
+   bzero(ExcludeString, sizeof(ExcludeString));
+   first_user_file=NULL;
 
    NAccessLog=0;
-   for(x=0; x<=MAXLOGS; x++)
+   for(x=0; x<MAXLOGS; x++)
       AccessLog[x][0]='\0';
    AccessLogFromCmdLine=0;
 
-   language_load(language);
-   strcpy(Title,text[88]);
+   strcpy(Title,_("Squid User Access Report"));
 
    while((ch = getopt(argc, argv, "a:b:c:d:e:f:g:u:l:L:o:s:t:w:hijmnprvxyz")) != -1){
       switch(ch)
@@ -315,7 +353,7 @@ int main(int argc,char *argv[])
             date[sizeof(date)-1]='\0';
             getword_start(&gwarea,optarg);
             if (getword(cdfrom,sizeof(cdfrom),&gwarea,'-')<0 || getword(cduntil,sizeof(cduntil),&gwarea,0)<0) {
-               printf("SARG: Maybe you have a broken record or garbage in your date range.\n");
+               printf(_("SARG: The date range requested on the command line by option -d is invalid.\n"));
                exit(1);
             }
             date_from(date, cdfrom, cduntil);
@@ -340,7 +378,7 @@ int main(int argc,char *argv[])
             break;
          case 'l':
             if (NAccessLog>=MAXLOGS) {
-               printf("SARG: Too many log files.\n");
+               printf(_("SARG: Too many log files passed on command line with option -l.\n"));
                exit(1);
             }
             strcpy(AccessLog[NAccessLog],optarg);
@@ -378,17 +416,17 @@ int main(int argc,char *argv[])
             } else {
                getword_start(&gwarea,optarg);
                if (getword(hm,sizeof(hm),&gwarea,'-')<0 || getword(hmf,sizeof(hmf),&gwarea,0)<0) {
-                  fprintf(stderr,"SARG: Maybe you have a broken record or garbage in your time range.\n");
+                  debuga(_("The time range passed on the command line with option -t is invalid\n"));
                   exit(1);
                }
             }
             if(sscanf(hm,"%d:%d",&h,&m)!=2) {
-               fprintf(stderr,"SARG: time period must be MM or MM:SS. Exit.\n");
+               debuga(_("Time period must be MM or MM:SS. Exit\n"));
                exit(1);
             }
             sprintf(hm,"%02d%02d",h,m);
             if(sscanf(hmf,"%d:%d",&h,&m)!=2) {
-               fprintf(stderr,"SARG: time period must be MM or MM:SS. Exit.\n");
+               debuga(_("Time period must be MM or MM:SS. Exit\n"));
                exit(1);
             }
             sprintf(hmf,"%02d%02d",h,m);
@@ -413,7 +451,7 @@ int main(int argc,char *argv[])
             debugz++;
             break;
          case ':':
-            fprintf(stderr, "Option -%c require an argument\n",optopt);
+            debuga(_("Option -%c require an argument\n"),optopt);
             errflg++;
             break;
          case '?':
@@ -429,23 +467,27 @@ int main(int argc,char *argv[])
       exit(2);
    }
 
-   if(debug) debuga("Init");
+   if(debug) debuga(_("Init\n"));
 
    if(ConfigFile[0] == '\0') sprintf(ConfigFile,"%s/sarg.conf",SYSCONFDIR);
    if(access(ConfigFile, R_OK) != 0) {
-      debuga("Cannot open config file: %s - %s",ConfigFile,strerror(errno));
+      debuga(_("Cannot open config file: %s - %s\n"),ConfigFile,strerror(errno));
       exit(1);
    }
 
    if(access(ConfigFile, R_OK) == 0)
       getconf();
 
+   if(UserIp) userip++;
+
+   if(dns) Ip2Name=1;
+
    if(realt) {
       realtime();
       exit(0);
    }
 
-   if(strcmp(IndexTree,"file") == 0)
+   if(IndexTree == INDEX_TREE_FILE)
       strcpy(ImageFile,"../images");
    else
       strcpy(ImageFile,"../../../images");
@@ -454,10 +496,6 @@ int main(int argc,char *argv[])
    if(DataFile[0] != '\0')
       dataonly++;
 
-   subs(TopUserFields,sizeof(TopUserFields),"%BYTES","SETYB");
-
-   subs(UserReportFields,sizeof(UserReportFields),"%BYTES","SETYB");
-
    if(!NAccessLog) {
       strcpy(AccessLog[0],"/var/log/squid/access.log");
       NAccessLog++;
@@ -482,17 +520,16 @@ int main(int argc,char *argv[])
 
    if(hexclude[0] == '\0')
       strcpy(hexclude,ExcludeHosts);
-   if(strlen(hexclude) > 0) {
-      if(access(hexclude, R_OK) != 0) {
-         debuga("Cannot open exclude_hosts file: %s - %s",hexclude,strerror(errno));
-         exit(1);
-      }
+   if(hexclude[0] != '\0') {
       gethexclude(hexclude,debug);
       fhost++;
    }
 
-   if(ReportType[0] == '\0')
-      strcpy(ReportType,"topusers topsites users_sites sites_users date_time denied auth_failures site_user_time_date downloads");
+   if(ReportType == 0) {
+      ReportType=REPORT_TYPE_TOPUSERS | REPORT_TYPE_TOPSITES | REPORT_TYPE_USERS_SITES |
+                 REPORT_TYPE_SITES_USERS | REPORT_TYPE_DATE_TIME | REPORT_TYPE_DENIED |
+                 REPORT_TYPE_AUTH_FAILURES | REPORT_TYPE_SITE_USER_TIME_DATE | REPORT_TYPE_DOWNLOADS;
+   }
 
    if(access(ExcludeUsers, R_OK) == 0) {
       getuexclude(ExcludeUsers,debug);
@@ -501,19 +538,15 @@ int main(int argc,char *argv[])
 
    indexonly=0;
    if(fuser) {
-      if(strstr(excludeuser,"indexonly") != 0)
+      if(is_indexonly())
          indexonly++;
    }
    if(strcmp(ExcludeUsers,"indexonly") == 0) indexonly++;
-   if(strcmp(Index,"only") == 0) indexonly++;
-
-   if(dns) strcpy(Ip2Name,"yes");
+   if(Index == INDEX_ONLY) indexonly++;
 
-   if(strcmp(UserIp,"yes") == 0) userip++;
+   if(MaxElapsed[0] != '\0') max_elapsed=atol(MaxElapsed);
 
-   if(strlen(MaxElapsed)>1) max_elapsed=atol(MaxElapsed);
-
-   if(strlen(outdir)<1) strcpy(outdir,OutputDir);
+   if(outdir[0] == '\0') strcpy(outdir,OutputDir);
    strcat(outdir,"/");
 
    if(uagent[0] == '\0') strcpy(uagent,UserAgentLog);
@@ -533,7 +566,7 @@ int main(int argc,char *argv[])
 
    strcpy(tmp2,tmp);
 
-   if(strlen(email) > 0) {
+   if(email[0] != '\0') {
       sprintf(wtemp2,"%s/sarg",tmp2);
       my_mkdir(wtemp2);
       strcat(tmp2,"/sarg");
@@ -543,121 +576,80 @@ int main(int argc,char *argv[])
 
    strcat(tmp2,"/sarg.log");
 
-   sprintf(warea,"%s/sarg",tmp);
-   if(access(warea, R_OK) == 0) {
-      if (snprintf(tmp3,sizeof(tmp3),"rm -rf \"%s\"",warea)>=sizeof(tmp3)) {
-         fprintf(stderr,"SARG: Directory name too long: %s\n",warea);
-         exit(1);
-      }
-      cstatus=system(tmp3);
-      if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
-         fprintf(stderr, "SARG: command return status %d\n",WEXITSTATUS(cstatus));
-         fprintf(stderr, "SARG: command: %s\n",tmp3);
-         exit(1);
-      }
-   }
-
    sprintf(tmp3,"%s/sarg",tmp);
+   if(access(tmp3, R_OK) == 0) {
+      unlinkdir(tmp3,1);
+   }
    my_mkdir(tmp3);
-   strcpy(tmp4,tmp3);
-   strcpy(tmp5,tmp3);
-   strcpy(tmp6,tmp3);
-   strcat(tmp4,"/denied.log.unsort");
-   strcat(tmp5,"/denied.log");
-   strcat(tmp6,"/authfail.log.unsort");
+   strcpy(denied_unsort,tmp3);
+   strcpy(denied_sort,tmp3);
+   strcpy(authfail_unsort,tmp3);
+   strcat(denied_unsort,"/denied.log.unsort");
+   strcat(denied_sort,"/denied.log");
+   strcat(authfail_unsort,"/authfail.log.unsort");
 
    if(debug) {
-      fprintf(stderr, "SARG: %s:\nSARG:\n",text[22]);
-      fprintf(stderr, "SARG: %35s (-a) = %s\n",text[23],addr);
-      fprintf(stderr, "SARG: %35s (-b) = %s\n",text[71],uagent);
-      fprintf(stderr, "SARG: %35s (-c) = %s\n",text[69],hexclude);
-      fprintf(stderr, "SARG: %35s (-d) = %s\n",text[24],date);
-      fprintf(stderr, "SARG: %35s (-e) = %s\n",text[41],email);
-      fprintf(stderr, "SARG: %35s (-f) = %s\n",text[70],ConfigFile);
+      debuga(_("Parameters:\n"));
+      debuga(_("          Hostname or IP address (-a) = %s\n"),addr);
+      debuga(_("                   Useragent log (-b) = %s\n"),uagent);
+      debuga(_("                    Exclude file (-c) = %s\n"),hexclude);
+      debuga(_("                 Date from-until (-d) = %s\n"),date);
+      debuga(_("   Email address to send reports (-e) = %s\n"),email);
+      debuga(_("                     Config file (-f) = %s\n"),ConfigFile);
       if(strcmp(df,"e") == 0)
-         fprintf(stderr, "SARG: %35s (-g) = %s (dd/mm/yyyy)\n",text[25],text[26]);
+         debuga(_("                     Date format (-g) = Europe (dd/mm/yyyy)\n"));
       if(strcmp(df,"u") == 0)
-         fprintf(stderr, "SARG: %35s (-g) = %s (mm/dd/yyyy)\n",text[25],text[27]);
+         debuga(_("                     Date format (-g) = USA (mm/dd/yyyy)\n"));
       if(strcmp(df,"w") == 0)
-         fprintf(stderr, "SARG: %35s (-g) = %s (yyyy/ww)\n",text[25],text[85]);
-      if(iprel)
-         fprintf(stderr, "SARG: %35s (-i) = %s\n",text[28],text[1]);
-      else
-         fprintf(stderr, "SARG: %35s (-i) = %s\n",text[28],text[2]);
+         debuga(_("                     Date format (-g) = Sites & Users (yyyy/ww)\n"));
+      debuga(_("                       IP report (-i) = %s\n"),(iprel) ? _("Yes") : _("No"));
       for (iarq=0 ; iarq<NAccessLog ; iarq++)
-         fprintf(stderr, "SARG: %35s (-l) = %s\n",text[37],AccessLog[iarq]);
-      if(strcmp(Ip2Name,"yes") == 0)
-         fprintf(stderr, "SARG: %35s (-n) = %s\n",text[65],text[1]);
-       else
-         fprintf(stderr, "SARG: %35s (-n) = %s\n",text[65],text[2]);
-      fprintf(stderr, "SARG: %35s (-o) = %s\n",text[38],outdir);
-      if(strcmp(UserIp,"yes") == 0)
-         fprintf(stderr, "SARG: %35s (-p) = %s\n",text[29],text[1]);
-       else
-         fprintf(stderr, "SARG: %35s (-p) = %s\n",text[29],text[2]);
-      fprintf(stderr, "SARG: %35s (-s) = %s\n",text[30],site);
-      fprintf(stderr, "SARG: %35s (-t) = %s\n",text[31],hm);
-      fprintf(stderr, "SARG: %35s (-u) = %s\n",text[32],us);
-      fprintf(stderr, "SARG: %35s (-w) = %s\n",text[34],tmp);
-      if(debug)
-         fprintf(stderr, "SARG: %35s (-x) = %s\n",text[35],text[1]);
-       else
-         fprintf(stderr, "SARG: %35s (-x) = %s\n",text[35],text[2]);
-      if(debugz)
-         fprintf(stderr, "SARG: %35s (-z) = %s\n",text[36],text[1]);
-       else
-         fprintf(stderr, "SARG: %35s (-z) = %s\n",text[36],text[2]);
-      fprintf(stderr, "SARG:\n");
+         debuga(_("                       Input log (-l) = %s\n"),AccessLog[iarq]);
+      debuga(_("              Resolve IP Address (-n) = %s\n"),(Ip2Name) ? _("Yes") : _("No"));
+      debuga(_("                      Output dir (-o) = %s\n"),outdir);
+      debuga(_("Use Ip Address instead of userid (-p) = %s\n"),(UserIp) ? _("Yes") : _("No"));
+      debuga(_("                   Accessed site (-s) = %s\n"),site);
+      debuga(_("                            Time (-t) = %s\n"),hm);
+      debuga(_("                            User (-u) = %s\n"),us);
+      debuga(_("                   Temporary dir (-w) = %s\n"),tmp);
+      debuga(_("                  Debug messages (-x) = %s\n"),(debug) ? _("Yes") : _("No"));
+      debuga(_("                Process messages (-z) = %s\n"),(debugz) ? _("Yes") : _("No"));
+      debuga("\n");
    }
 
    if(debugm) {
-      printf("%s:\nSARG:\n",text[22]);
-      printf("%35s (-a) = %s\n",text[23],addr);
-      printf("%35s (-b) = %s\n",text[71],uagent);
-      printf("%35s (-c) = %s\n",text[69],hexclude);
-      printf("%35s (-d) = %s\n",text[24],date);
-      printf("%35s (-e) = %s\n",text[41],email);
-      printf("%35s (-f) = %s\n",text[70],ConfigFile);
+      printf(_("Parameters:\n"));
+      printf(_("          Hostname or IP address (-a) = %s\n"),addr);
+      printf(_("                   Useragent log (-b) = %s\n"),uagent);
+      printf(_("                    Exclude file (-c) = %s\n"),hexclude);
+      printf(_("                 Date from-until (-d) = %s\n"),date);
+      printf(_("   Email address to send reports (-e) = %s\n"),email);
+      printf(_("                     Config file (-f) = %s\n"),ConfigFile);
       if(strcmp(df,"e") == 0)
-         printf("%35s (-g) = %s (dd/mm/yyyy)\n",text[25],text[26]);
+         printf(_("                     Date format (-g) = Europe (dd/mm/yyyy)\n"));
       if(strcmp(df,"u") == 0)
-         printf("%35s (-g) = %s (mm/dd/yyyy)\n",text[25],text[27]);
+         printf(_("                     Date format (-g) = USA (mm/dd/yyyy)\n"));
       if(strcmp(df,"w") == 0)
-         printf("%35s (-g) = %s (yyyy/ww)\n",text[25],text[85]);
-      if(iprel)
-         printf("%35s (-i) = %s\n",text[28],text[1]);
-      else
-         printf("%35s (-i) = %s\n",text[28],text[2]);
+         printf(_("                     Date format (-g) = Sites & Users (yyyy/ww)\n"));
+      printf(_("                       IP report (-i) = %s\n"),(iprel) ? _("Yes") : _("No"));
       for (iarq=0 ; iarq<NAccessLog ; iarq++)
-         printf("%35s (-l) = %s\n",text[37],AccessLog[iarq]);
-      if(strcmp(Ip2Name,"yes") == 0)
-         printf("%35s (-n) = %s\n",text[65],text[1]);
-       else
-         printf("%35s (-n) = %s\n",text[65],text[2]);
-      printf("%35s (-o) = %s\n",text[38],outdir);
-      if(strcmp(UserIp,"yes") == 0)
-         printf("%35s (-p) = %s\n",text[29],text[1]);
-       else
-         printf("%35s (-p) = %s\n",text[29],text[2]);
-      printf("%35s (-s) = %s\n",text[30],site);
-      printf("%35s (-t) = %s\n",text[31],hm);
-      printf("%35s (-u) = %s\n",text[32],us);
-      printf("%35s (-w) = %s\n",text[34],tmp);
-      if(debug)
-         printf("%35s (-x) = %s\n",text[35],text[1]);
-       else
-         printf("%35s (-x) = %s\n",text[35],text[2]);
-      if(debugz)
-         printf("%35s (-z) = %s\n",text[36],text[1]);
-       else
-         printf("%35s (-z) = %s\n",text[36],text[2]);
-      printf("sarg %s: %s\n",text[73],VERSION);
-      printf("Language=%s\n\n",text[3]);
+         printf(_("                       Input log (-l) = %s\n"),AccessLog[iarq]);
+      printf(_("              Resolve IP Address (-n) = %s\n"),(Ip2Name) ? _("Yes") : _("No"));
+      printf(_("                      Output dir (-o) = %s\n"),outdir);
+      printf(_("Use Ip Address instead of userid (-p) = %s\n"),(UserIp) ? _("Yes") : _("No"));
+      printf(_("                   Accessed site (-s) = %s\n"),site);
+      printf(_("                            Time (-t) = %s\n"),hm);
+      printf(_("                            User (-u) = %s\n"),us);
+      printf(_("                   Temporary dir (-w) = %s\n"),tmp);
+      printf(_("                  Debug messages (-x) = %s\n"),(debug) ? _("Yes") : _("No"));
+      printf(_("                Process messages (-z) = %s\n"),(debugz) ? _("Yes") : _("No"));
+      printf(_("sarg version: %s\n"),VERSION);
    }
 
    if(debug)
-      debuga("sarg %s: %s",text[73],VERSION);
+      debuga(_("sarg version: %s\n"),VERSION);
 
+   maxopenfiles=MAX_OPEN_USER_FILES;
 #ifdef HAVE_RLIM_T
    if (Ulimit[0] != '\0') {
       struct rlimit rl;
@@ -684,7 +676,7 @@ int main(int argc,char *argv[])
 #warning "No rlimit resource for the number of open files"
 #endif
       if(rc == -1) {
-            debuga("setrlimit error - %s\n",strerror(errno));
+            debuga(_("setrlimit error - %s\n"),strerror(errno));
       }
 
       if(debug)
@@ -692,22 +684,26 @@ int main(int argc,char *argv[])
    }
 #endif
 
-   read_usertab(UserTabFile);
+   init_usertab(UserTabFile);
+
+   if (longline_prepare(&line)<0) {
+      debuga(_("Not enough memory to read a log file\n"));
+      exit(1);
+   }
 
    sprintf ( sz_Download_Unsort , "%s/sarg/download.unsort", tmp);
-   bool_ShowReadStatistics = ( strcmp(ShowReadStatistics,"yes") == 0 ) ;
 
-   if(strstr(ReportType,"denied") != 0) {
-      if((fp_denied=MY_FOPEN(tmp4,"w"))==NULL) {
-         fprintf(stderr, "%s: (log) %s: %s - %s\n",argv[0],text[45],tmp4,strerror(errno));
-         exit(1);
+   if(DataFile[0]=='\0') {
+      if((ReportType & REPORT_TYPE_DENIED) != 0) {
+         if((fp_denied=MY_FOPEN(denied_unsort,"w"))==NULL) {
+            debuga(_("SARG: (log) Cannot open file: %s - %s\n"),denied_unsort,strerror(errno));
+            exit(1);
+         }
       }
-   }
 
-   if(DataFile[0]=='\0') {
-      if(strstr(ReportType,"denied") != 0 || strstr(ReportType,"auth_failures") != 0) {
-         if((fp_authfail=MY_FOPEN(tmp6,"w"))==NULL) {
-            fprintf(stderr, "%s: (log) %s: %s - %s\n",argv[0],text[45],tmp6,strerror(errno));
+      if((ReportType & REPORT_TYPE_DENIED) != 0 || (ReportType & REPORT_TYPE_AUTH_FAILURES) != 0) {
+         if((fp_authfail=MY_FOPEN(authfail_unsort,"w"))==NULL) {
+            debuga(_("SARG: (log) Cannot open file: %s - %s\n"),authfail_unsort,strerror(errno));
             exit(1);
          }
       }
@@ -720,48 +716,69 @@ int main(int argc,char *argv[])
 
       if(strcmp(arq,"-")==0) {
          if(debug)
-            debuga("%s: %s",text[7],"stdin");
+            debuga(_("Reading access log file: from stdin\n"));
          fp_in=stdin;
          from_stdin=1;
       } else {
          decomp(arq,zip,tmp);
          if(debug)
-            debuga("%s: %s",text[7],arq);
+            debuga(_("Reading access log file: %s\n"),arq);
          if((fp_in=MY_FOPEN(arq,"r"))==NULL) {
-            fprintf(stderr, "%s: (log) %s: %s - %s\n",argv[0],text[8],arq,strerror(errno));
+            debuga(_("SARG: (log) Cannot open log file: %s - %s\n"),arq,strerror(errno));
             exit(1);
          }
          from_stdin=0;
       }
       ilf=ILF_Unknown;
-      // pre-Read the file only if I have to show stats
-      if(bool_ShowReadStatistics && !from_stdin) {
-         rewind(fp_in);
+      download_flag=0;
+      // pre-read the file only if we have to show stats
+      if(ShowReadStatistics && !from_stdin) {
+         size_t nread,i;
+         int skipcr=0;
+
          recs1=0UL;
          recs2=0UL;
 
-         while( fgets(bufz,sizeof(bufz),fp_in) != NULL ) recs1++;
+         while ((nread=fread(line.buffer,1,line.size,fp_in))>0) {
+            for (i=0 ; i<nread ; i++)
+               if (skipcr) {
+                  if (line.buffer[i]!='\n' && line.buffer[i]!='\r') {
+                     skipcr=0;
+                  }
+               } else {
+                  if (line.buffer[i]=='\n' || line.buffer[i]=='\r') {
+                     skipcr=1;
+                     recs1++;
+                  }
+               }
+         }
          rewind(fp_in);
-         printf("SARG: Records in file: %lu, reading: %3.2f%%\r",recs1,(float) 0);
+         printf(_("SARG: Records in file: %lu, reading: %3.2f%%\r"),recs1,(float) 0);
          fflush( stdout ) ;
       }
 
-      while(fgets(bufz,sizeof(bufz),fp_in)!=NULL) {
+      line.start=0;
+      line.end=0;
+      line.length=0;
+
+      while ((linebuf=longline_read(fp_in,&line))!=NULL) {
+         blen=strlen(linebuf);
 
          if (ilf==ILF_Unknown) {
-            if(strncmp(bufz,"#Software: Mic",14) == 0) {
-               fixendofline(bufz);
-               debuga("%s: %s",text[143],bufz);
+            if(strncmp(linebuf,"#Software: Mic",14) == 0) {
+               fixendofline(linebuf);
+               if (debug)
+                  debuga(_("Log is from Microsoft ISA: %s\n"),linebuf);
                ilf=ILF_Isa;
                ilf_count[ilf]++;
                continue;
             }
 
-            if(strncmp(bufz,"*** SARG Log ***",16) == 0) {
+            if(strncmp(linebuf,"*** SARG Log ***",16) == 0) {
                getword_start(&gwarea,arqtt);
-               if (getword(val2,sizeof(val2),&gwarea,'-')<0 || getword(val2,sizeof(val2),&gwarea,'_')<0 ||
-                   getword(val3,sizeof(val3),&gwarea,'-')<0 || getword(val3,sizeof(val3),&gwarea,'_')<0) {
-                  printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+               if (getword_skip(2000,&gwarea,'-')<0 || getword(val2,sizeof(val2),&gwarea,'_')<0 ||
+                   getword_skip(10,&gwarea,'-')<0 || getword(val3,sizeof(val3),&gwarea,'_')<0) {
+                  debuga(_("The name of the file is invalid: %s\n"),arq);
                   exit(1);
                }
                sprintf(period,"%s-%s",val2,val3);
@@ -771,76 +788,56 @@ int main(int argc,char *argv[])
             }
          }
 
-         if(strcmp(ParsedOutputLog, "no") != 0 && ilf!=ILF_Sarg) {
+         if(!fp_log && strcmp(ParsedOutputLog, "no") != 0 && ilf!=ILF_Sarg) {
             if(access(ParsedOutputLog,R_OK) != 0) {
-               sprintf(csort,"%s",ParsedOutputLog);
-               my_mkdir(csort);
+               my_mkdir(ParsedOutputLog);
             }
             sprintf(arq_log,"%s/sarg_temp.log",ParsedOutputLog);
             if((fp_log=MY_FOPEN(arq_log,"w"))==NULL) {
-               fprintf(stderr, "%s: (log) %s: %s - %s\n",argv[0],text[8],arq_log,strerror(errno));
+               debuga(_("SARG: (log) Cannot open log file: %s - %s\n"),arq_log,strerror(errno));
                exit(1);
             }
             fputs("*** SARG Log ***\n",fp_log);
          }
 
          recs2++;
-         if( bool_ShowReadStatistics && !from_stdin && ! --OutputNonZero) {
+         if( ShowReadStatistics && !from_stdin && ! --OutputNonZero) {
            perc = recs2 * 100 ;
            perc = perc / recs1 ;
            printf("SARG: Records in file: %lu, reading: %3.2f%%\r",recs1,perc);
            fflush (stdout);
            OutputNonZero = REPORT_EVERY_X_LINES ;
          }
-         if(strlen(bufz) > MAXLEN-1) continue;
-         if(!bufz[0]) continue;
-         if(strstr(bufz,"HTTP/0.0") != 0) continue;
-         if(strstr(bufz,"logfile turned over") != 0) continue;
-         if(bufz[0] == ' ') continue;
-         if(strlen(bufz) < 58) continue;
-
-         // Record only hours usage which is required
-         tt = (time_t) strtoul( bufz, NULL, 10 );
-         t = localtime( &tt );
-
-         if( bsearch( &( t -> tm_wday ), weekdays.list, weekdays.len,
-                                          sizeof( int ), compar ) == NULL )
-            continue;
-
-         if( bsearch( &( t -> tm_hour ), hours.list, hours.len,
-                                          sizeof( int ), compar ) == NULL )
-            continue;
+         if(blen < 58) continue;
+         if(strstr(linebuf,"HTTP/0.0") != 0) continue;
+         if(strstr(linebuf,"logfile turned over") != 0) continue;
+         if(linebuf[0] == ' ') continue;
 
          // exclude_string
-         exstring=0;
          if(ExcludeString[0] != '\0') {
-            strcpy(warea,bufz);
+            exstring=0;
             getword_start(&gwarea,ExcludeString);
             while(strchr(gwarea.current,':') != 0) {
                if (getword_multisep(val1,sizeof(val1),&gwarea,':')<0) {
-                  printf("SARG: Maybe you have a broken record or garbage in your exclusion string.\n");
+                  debuga(_("Maybe you have a broken record or garbage in your exclusion string\n"));
                   exit(1);
                }
-               if((str=(char *) strstr(warea,val1)) != (char *) NULL )
+               if((str=(char *) strstr(linebuf,val1)) != (char *) NULL )
                   exstring++;
             }
-            if((str=(char *) strstr(warea,gwarea.current)) != (char *) NULL )
+            if((str=(char *) strstr(linebuf,gwarea.current)) != (char *) NULL )
                   exstring++;
+            if(exstring) continue;
          }
-         if(exstring) continue;
-
-         strcpy(bufy,bufz);
-         if ((str = strchr(bufz, '\n')) != NULL)
-            *str = '\0';          /* strip \n */
 
          totregsl++;
          if(debugm)
-            printf("BUF=%s\n",bufz);
+            printf("BUF=%s\n",linebuf);
 
          if (ilf==ILF_Squid || ilf==ILF_Common || ilf==ILF_Unknown) {
-            getword_start(&gwarea,bufz);
+            getword_start(&gwarea,linebuf);
             if (getword(data,sizeof(data),&gwarea,' ')<0) {
-               printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
+               debuga(_("Maybe you have a broken time in your access.log file.\n"));
                exit(1);
             }
             if((str=(char *) strchr(data, '.')) != (char *) NULL ) {
@@ -849,30 +846,37 @@ int main(int argc,char *argv[])
                   strcpy(elap,"0");
                   if(squid24) {
                      if (getword(user,sizeof(user),&gwarea,' ')<0 || getword_skip(255,&gwarea,' ')<0) {
-                        printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+                        debuga(_("Maybe you have a broken record or garbage in your %s file.\n"),arq);
                         exit(1);
                      }
                   } else {
                      if (getword_skip(255,&gwarea,' ')<0 || getword(user,sizeof(user),&gwarea,' ')<0) {
-                        printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+                        debuga(_("Maybe you have a broken record or garbage in your %s file.\n"),arq);
                         exit(1);
                      }
                   }
                   if (getword(data,sizeof(data),&gwarea,']')<0 || getword_skip(MAXLEN,&gwarea,'"')<0 ||
-                      getword(fun,sizeof(fun),&gwarea,' ')<0 || getword(url,sizeof(url),&gwarea,' ')<0 ||
-                      getword_skip(MAXLEN,&gwarea,' ')<0 || getword(code2,sizeof(code2),&gwarea,' ')<0 ||
+                      getword(fun,sizeof(fun),&gwarea,' ')<0) {
+                     debuga(_("Maybe you have a broken record or garbage in your %s file.\n"),arq);
+                     exit(1);
+                  }
+                  if (getword_ptr(linebuf,&url,&gwarea,' ')<0) {
+                     debuga(_("Maybe you have a broken url in your %s file\n"),arq);
+                     exit(1);
+                  }
+                  if (getword_skip(MAXLEN,&gwarea,' ')<0 || getword(code2,sizeof(code2),&gwarea,' ')<0 ||
                       getword(tam,sizeof(tam),&gwarea,' ')<0) {
-                     printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+                     debuga(_("Maybe you have a broken record or garbage in your %s file.\n"),arq);
                      exit(1);
                   }
                   if((str=(char *) strchr(gwarea.current, ' ')) != (char *) NULL ) {
                      if (getword(code,sizeof(code),&gwarea,' ')<0) {
-                        printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+                        debuga(_("Maybe you have a broken record or garbage in your %s file.\n"),arq);
                         exit(1);
                      }
                   } else {
                      if (getword(code,sizeof(code),&gwarea,'\0')<0) {
-                        printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+                        debuga(_("Maybe you have a broken record or garbage in your %s file.\n"),arq);
                         exit(1);
                      }
                   }
@@ -890,41 +894,37 @@ int main(int argc,char *argv[])
 
             if(ilf==ILF_Unknown || ilf==ILF_Squid) {
                if (getword(elap,sizeof(elap),&gwarea,' ')<0) {
-                  printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+                  debuga(_("Maybe you have a broken elapsed time in your %s file.\n"),arq);
                   exit(1);
                }
                while(strcmp(elap,"") == 0 && gwarea.current[0] != '\0')
                   if (getword(elap,sizeof(elap),&gwarea,' ')<0) {
-                     printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+                     debuga(_("Maybe you have a broken elapsed time in your %s file.\n"),arq);
                      exit(1);
                   }
                if(strlen(elap) < 1) continue;
                if (getword(ip,sizeof(ip),&gwarea,' ')<0){
-                  printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+                  debuga(_("Maybe you have a broken client IP address in your %s file.\n"),arq);
                   exit(1);
                }
                if (getword(code,sizeof(code),&gwarea,' ')<0){
-                  printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+                  debuga(_("Maybe you have a broken result code in your %s file.\n"),arq);
                   exit(1);
                }
                if (getword(tam,sizeof(tam),&gwarea,' ')<0){
-                  printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+                  debuga(_("Maybe you have a broken amount of data in your %s file.\n"),arq);
                   exit(1);
                }
                if (getword(fun,sizeof(fun),&gwarea,' ')<0){
-                  printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+                  debuga(_("Maybe you have a broken request method in your %s file.\n"),arq);
                   exit(1);
                }
-               if (getword(url,sizeof(url),&gwarea,' ')<0){
-                  printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+               if (getword_ptr(linebuf,&url,&gwarea,' ')<0){
+                  debuga(_("Maybe you have a broken url in your %s file\n"),arq);
                   exit(1);
                }
-//              while (strstr(bufz,"%20") != 0) {
-//                 getword(warea,bufz,' ');
-//                 strcat(url,warea);
-//              }
                if (getword(user,sizeof(user),&gwarea,' ')<0){
-                  printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+                  debuga(_("Maybe you have a broken user ID in your %s file.\n"),arq);
                   exit(1);
                }
                ilf=ILF_Squid;
@@ -932,60 +932,60 @@ int main(int argc,char *argv[])
             }
          }
          if (ilf==ILF_Sarg) {
-            getword_start(&gwarea,bufz);
-            if (getword(data,sizeof(data),&gwarea,' ')<0){
-               printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+            getword_start(&gwarea,linebuf);
+            if (getword(data,sizeof(data),&gwarea,'\t')<0){
+               debuga(_("Maybe you have a broken record or garbage in your %s file.\n"),arq);
                exit(1);
             }
-            if (getword(hora,sizeof(hora),&gwarea,' ')<0) {
-               printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+            if (getword(hora,sizeof(hora),&gwarea,'\t')<0) {
+               debuga(_("Maybe you have a broken record or garbage in your %s file.\n"),arq);
                exit(1);
             }
-            if (getword(user,sizeof(user),&gwarea,' ')<0) {
-               printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+            if (getword(user,sizeof(user),&gwarea,'\t')<0) {
+               debuga(_("Maybe you have a broken record or garbage in your %s file.\n"),arq);
                exit(1);
             }
-            if (getword(ip,sizeof(ip),&gwarea,' ')<0) {
-               printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+            if (getword(ip,sizeof(ip),&gwarea,'\t')<0) {
+               debuga(_("Maybe you have a broken record or garbage in your %s file.\n"),arq);
                exit(1);
             }
-            if (getword(url,sizeof(url),&gwarea,' ')<0){
-               printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+            if (getword_ptr(linebuf,&url,&gwarea,'\t')<0){
+               debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
                exit(1);
             }
-            if (getword(tam,sizeof(tam),&gwarea,' ')<0){
-               printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+            if (getword(tam,sizeof(tam),&gwarea,'\t')<0){
+               debuga(_("Maybe you have a broken record or garbage in your %s file.\n"),arq);
                exit(1);
             }
-            if (getword(code,sizeof(code),&gwarea,' ')<0){
-               printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+            if (getword(code,sizeof(code),&gwarea,'\t')<0){
+               debuga(_("Maybe you have a broken record or garbage in your %s file.\n"),arq);
                exit(1);
             }
-            if (getword(elap,sizeof(elap),&gwarea,' ')<0){
-               printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+            if (getword(elap,sizeof(elap),&gwarea,'\t')<0){
+               debuga(_("Maybe you have a broken record or garbage in your %s file.\n"),arq);
                exit(1);
             }
-            if (getword(smartfilter,sizeof(smartfilter),&gwarea,' ')<0){
-               printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+            if (getword(smartfilter,sizeof(smartfilter),&gwarea,'\0')<0){
+               debuga(_("Maybe you have a broken record or garbage in your %s file.\n"),arq);
                exit(1);
             }
          }
          if (ilf==ILF_Isa) {
-            if (bufz[0] == '#') {
+            if (linebuf[0] == '#') {
                int ncols,cols[ISACOL_Last];
 
-               fixendofline(bufz);
-               getword_start(&gwarea,bufz);
+               fixendofline(linebuf);
+               getword_start(&gwarea,linebuf);
                // remove the #Fields: column at the beginning of the line
                if (getword_skip(1000,&gwarea,' ')<0){
-                  printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+                  debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
                   exit(1);
                }
                for (ncols=0 ; ncols<ISACOL_Last ; ncols++) cols[ncols]=-1;
                ncols=0;
                while(gwarea.current[0] != '\0') {
                   if (getword(val1,sizeof(val1),&gwarea,'\t')<0){
-                     printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+                     debuga(_("Maybe you have a broken record or garbage in your %s file.\n"),arq);
                      exit(1);
                   }
                   if(strcmp(val1,"c-ip") == 0) cols[ISACOL_Ip]=ncols;
@@ -1000,66 +1000,62 @@ int main(int argc,char *argv[])
                }
                if (cols[ISACOL_Ip]>=0) {
                   isa_ncols=ncols;
-                  for (isa_ncols=0 ; isa_ncols<ncols ; isa_ncols++)
-                     isa_cols[isa_ncols]=cols[isa_ncols];
+                  for (ncols=0 ; ncols<ISACOL_Last ; ncols++)
+                     isa_cols[ncols]=cols[ncols];
                }
                continue;
             }
             if (!isa_ncols) continue;
-            getword_start(&gwarea,bufz);
+            getword_start(&gwarea,linebuf);
             for (x=0 ; x<isa_ncols ; x++) {
-               if (getword(val1,sizeof(val1),&gwarea,'\t')<0) {
-                  printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+               if (getword_ptr(linebuf,&str,&gwarea,'\t')<0) {
+                  debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
                   exit(1);
                }
                if (x==isa_cols[ISACOL_Ip]) {
-                  if (strlen(val1)>=sizeof(ip)) {
-                     printf("SARG: Maybe you have a broken IP in your %s file.\n",arq);
+                  if (strlen(str)>=sizeof(ip)) {
+                     debuga(_("Maybe you have a broken IP in your %s file\n"),arq);
                      exit(1);
                   }
-                  strcpy(ip,val1);
+                  strcpy(ip,str);
                } else if (x==isa_cols[ISACOL_UserName]) {
-                  if (strlen(val1)>=sizeof(user)) {
-                     printf("SARG: Maybe you have a broken user in your %s file.\n",arq);
+                  if (strlen(str)>=sizeof(user)) {
+                     debuga(_("Maybe you have a broken user in your %s file\n"),arq);
                      exit(1);
                   }
-                  strcpy(user,val1);
+                  strcpy(user,str);
                } else if (x==isa_cols[ISACOL_Date]) {
-                  if (strlen(val1)>=sizeof(data)) {
-                     printf("SARG: Maybe you have a broken date in your %s file.\n",arq);
+                  if (strlen(str)>=sizeof(data)) {
+                     debuga(_("Maybe you have a broken date in your %s file\n"),arq);
                      exit(1);
                   }
-                  strcpy(data,val1);
+                  strcpy(data,str);
                } else if (x==isa_cols[ISACOL_Time]) {
-                  if (strlen(val1)>=sizeof(hora)) {
-                     printf("SARG: Maybe you have a broken time in your %s file.\n",arq);
+                  if (strlen(str)>=sizeof(hora)) {
+                     debuga(_("Maybe you have a broken time in your %s file\n"),arq);
                      exit(1);
                   }
-                  strcpy(hora,val1);
+                  strcpy(hora,str);
                } else if (x==isa_cols[ISACOL_TimeTaken]) {
-                  if (strlen(val1)>=sizeof(elap)) {
-                     printf("SARG: Maybe you have a broken download duration in your %s file.\n",arq);
+                  if (strlen(str)>=sizeof(elap)) {
+                     debuga(_("Maybe you have a broken download duration in your %s file\n"),arq);
                      exit(1);
                   }
-                  strcpy(elap,val1);
+                  strcpy(elap,str);
                } else if (x==isa_cols[ISACOL_Bytes]) {
-                  if (strlen(val1)>=sizeof(tam)) {
-                     printf("SARG: Maybe you have a broken download size in your %s file.\n",arq);
+                  if (strlen(str)>=sizeof(tam)) {
+                     debuga(_("Maybe you have a broken download size in your %s file\n"),arq);
                      exit(1);
                   }
-                  strcpy(tam,val1);
+                  strcpy(tam,str);
                } else if (x==isa_cols[ISACOL_Uri]) {
-                  if (strlen(val1)>=sizeof(url)) {
-                     printf("SARG: Maybe you have a broken URL in your %s file.\n",arq);
-                     exit(1);
-                  }
-                  strcpy(url,val1);
+                  url=str;
                } else if (x==isa_cols[ISACOL_Status]) {
-                  if (strlen(val1)>=sizeof(code)) {
-                     printf("SARG: Maybe you have a broken access code in your %s file.\n",arq);
+                  if (strlen(str)>=sizeof(code)) {
+                     debuga(_("Maybe you have a broken access code in your %s file\n"),arq);
                      exit(1);
                   }
-                  strcpy(code,val1);
+                  strcpy(code,str);
                }
             }
 
@@ -1069,23 +1065,127 @@ int main(int argc,char *argv[])
             }
             getword_start(&gwarea,data);
             if (getword(ano,sizeof(ano),&gwarea,'-')<0){
-               printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+               debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
                exit(1);
             }
             if (getword(mes,sizeof(mes),&gwarea,'-')<0){
-               printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+               debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
                exit(1);
             }
             if (getword(dia,sizeof(dia),&gwarea,'\0')<0){
-               printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq);
+               debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
                exit(1);
             }
             conv_month_name(mes);
             sprintf(data," %s/%s/%s:%s",dia,mes,ano,hora);
          }
 
-         if(strlen(user) > 150) {
-            if (debugm) printf("User too long: %s\n",user);
+         if(ilf==ILF_Squid) {
+            tt=atoi(data);
+            t=localtime(&tt);
+
+            strftime(tbuf2, sizeof(tbuf2), "%H%M", t);
+            sprintf(mes,"%d",t->tm_mon+1);
+            conv_month_name(mes);
+            if(strncmp(df,"u",1) == 0)
+               sprintf(tbuf, "%04d%s%02d", t->tm_year+1900, mes, t->tm_mday);
+            if(strncmp(df,"e",1) == 0)
+               sprintf(tbuf, "%02d%s%04d", t->tm_mday, mes, t->tm_year+1900);
+            if(strncmp(df,"w",1) == 0) {
+               IndexTree=INDEX_TREE_FILE;
+               strftime(tbuf, sizeof(tbuf), "%Y.%U", t);
+            }
+
+            strftime(wdata, sizeof(wdata), "%Y%m%d", t);
+            idata=atoi(wdata);
+
+            if(strncmp(df,"u",1)==0)
+               strftime(dia, sizeof(dia), "%m/%d/%Y", t);
+            else
+               strftime(dia, sizeof(dia), "%d/%m/%Y", t);
+            sprintf(hora,"%02d:%02d:%02d",t->tm_hour,t->tm_min,t->tm_sec);
+         } else if(ilf==ILF_Common || ilf==ILF_Isa) {
+            getword_start(&gwarea,data+1);
+            if (getword_multisep(data,sizeof(data),&gwarea,':')<0){
+               debuga(_("Maybe you have a broken date in your %s file\n"),arq);
+               exit(1);
+            }
+            if (getword_multisep(hora,sizeof(hora),&gwarea,' ')<0){
+               debuga(_("Maybe you have a broken date in your %s file\n"),arq);
+               exit(1);
+            }
+            getword_start(&gwarea,data);
+            if (getword(dia,sizeof(dia),&gwarea,'/')<0){
+               debuga(_("Maybe you have a broken date in your %s file\n"),arq);
+               exit(1);
+            }
+            if (getword(mes,sizeof(mes),&gwarea,'/')<0){
+               debuga(_("Maybe you have a broken date in your %s file\n"),arq);
+               exit(1);
+            }
+            if (getword(ano,sizeof(ano),&gwarea,'/')<0){
+               debuga(_("Maybe you have a broken date in your %s file\n"),arq);
+               exit(1);
+            }
+
+            if(strcmp(df,"u") == 0)
+               snprintf(tbuf,sizeof(tbuf),"%s%s%s",ano,mes,dia);
+            if(strcmp(df,"e") == 0)
+               snprintf(tbuf,sizeof(tbuf),"%s%s%s",dia,mes,ano);
+            builddia(dia,mes,ano,df,wdata);
+            idata=atoi(wdata);
+            tt=computedate(ano,mes,dia);
+            t=localtime(&tt);
+         } else if (ilf==ILF_Sarg) {
+            getword_start(&gwarea,data);
+            if(strcmp(df,"u") == 0) {
+               if (getword(mes,sizeof(mes),&gwarea,'/')<0){
+                  debuga(_("Maybe you have a broken date in your %s file\n"),arq);
+                  exit(1);
+               }
+               if (getword(dia,sizeof(dia),&gwarea,'/')<0){
+                  debuga(_("Maybe you have a broken date in your %s file\n"),arq);
+                  exit(1);
+               }
+            } else {
+               if (getword(dia,sizeof(dia),&gwarea,'/')<0){
+                  debuga(_("Maybe you have a broken date in your %s file\n"),arq);
+                  exit(1);
+               }
+               if (getword(mes,sizeof(mes),&gwarea,'/')<0){
+                  debuga(_("Maybe you have a broken date in your %s file\n"),arq);
+                  exit(1);
+               }
+            }
+            if (getword(ano,sizeof(ano),&gwarea,0)<0){
+               debuga(_("Maybe you have a broken date in your %s file\n"),arq);
+               exit(1);
+            }
+            snprintf(wdata,9,"%s%s%s",ano,mes,dia);
+            idata=atoi(wdata);
+            tt=computedate(ano,mes,dia);
+            t=localtime(&tt);
+         }
+
+         if(debugm)
+            printf("DATE=%s IDATA=%d DFROM=%d DUNTIL=%d\n",date,idata,dfrom,duntil);
+
+         if(date[0] != '\0'){
+            if(idata < dfrom || idata > duntil) continue;
+         }
+
+         // Record only hours usage which is required
+         if( bsearch( &( t -> tm_wday ), weekdays.list, weekdays.len,
+                                          sizeof( int ), compar ) == NULL )
+            continue;
+
+         if( bsearch( &( t -> tm_hour ), hours.list, hours.len,
+                                          sizeof( int ), compar ) == NULL )
+            continue;
+
+
+         if(strlen(user) > MAX_USER_LEN) {
+            if (debugm) printf(_("User ID too long: %s\n"),user);
             totregsx++;
             continue;
          }
@@ -1098,7 +1198,7 @@ int main(int argc,char *argv[])
          }
 
          if(vercode(code)) {
-            if (debugm) printf("Excluded code: %s\n",code);
+            if (debugm) printf(_("Excluded code: %s\n"),code);
             totregsx++;
             continue;
          }
@@ -1106,9 +1206,12 @@ int main(int argc,char *argv[])
          if(testvaliduserchar(user))
             continue;
 
+#if 0
          if((str = strstr(user,"%20")) != NULL) {
             /*
-            Why is it necessary to truncate the user name at the first space ?
+            This is a patch introduced to solve bug #1624251 reported at sourceforge but
+            the side effect is to truncate the name at the first space and merge the reports
+            of people whose name is identical up to the first space.
 
             The old code used to truncate the user name at the first % if a %20 was
             found anywhere in the string. That means the string could be truncated
@@ -1127,33 +1230,22 @@ int main(int argc,char *argv[])
             *str='.';
             for (x=3 ; str[x] ; x++) str[x-2]=str[x];
          }
+#endif
 
-         for(str=user; *str; str++) {
-            if(*str=='.') dotinuser++;
-            if(*str=='?' || *str=='.' || *str==':' || *str=='/' || *str=='\\')
-               *str='_';
-         }
+         urly=url;
 
-         strlow(user);
-         if(strncmp(NtlmUserFormat,"user",4) == 0) {
-            if((str = strchr(user,'_')) != 0) {
-               strcpy(warea,str+1);
-               strcpy(user,warea);
-            }
-            if((str = strchr(user,'+')) != 0) {
-               strcpy(warea,str+1);
-               strcpy(user,warea);
+         if(ilf!=ILF_Sarg) {
+            /*
+            The full URL is not saved in sarg log. There is no point in testing the URL to detect
+            a downloaded file.
+            */
+            download_flag=is_download_suffix(url);
+            if (download_flag) {
+               download_url=url;
+               download_count++;
             }
-         }
-
-         if(strstr(ReportType,"denied") != 0)
-            strcpy(urly,url);
-
-         download_flag=is_download_suffix(url);
-         if (download_flag) {
-            strcpy(download_url,url);
-            download_count++;
-         }
+         } else
+            download_flag=0;
 
          // remove any protocol:// at the beginning of the URL
          if ((str = strchr(url,'/')) != NULL && str[1] == '/') {
@@ -1165,155 +1257,76 @@ int main(int argc,char *argv[])
             url[i]='\0';
          }
 
-         if(strcmp(LongUrl,"no") == 0) {
-            char *endofhost=strchr(url,'/');
-            if (endofhost)
-               *endofhost='\0';
-            if(strlen(url) > 512 && (endofhost=strchr(url,'%')) != NULL) {
-               *endofhost='\0';
-            }
+         if(!LongUrl) {
+            url_hostname(url,hostname,sizeof(hostname));
+            url=hostname;
          }
 
-         if(ilf==ILF_Squid) {
-            tt=atoi(data);
-            t=localtime(&tt);
-
-            strftime(tbuf2, sizeof(tbuf2), "%H%M", t);
-            if(strncmp(df,"u",1) == 0)
-               strftime(tbuf, sizeof(tbuf), "%Y%b%d", t);
-            if(strncmp(df,"e",1) == 0)
-               strftime(tbuf, sizeof(tbuf), "%d%b%Y", t);
-            if(strncmp(df,"w",1) == 0) {
-               strcpy(IndexTree,"file");
-               strftime(tbuf, sizeof(tbuf), "%Y.%U", t);
-            }
+         if(url[0] == '\0') continue;
 
-            strftime(wdata, sizeof(wdata), "%Y%m%d", t);
-            idata=atoi(wdata);
-
-            if(strncmp(df,"u",1)==0)
-               strftime(dia, sizeof(dia), "%m/%d/%Y", t);
-            else
-               strftime(dia, sizeof(dia), "%d/%m/%Y", t);
-            sprintf(hora,"%02d:%02d:%02d",t->tm_hour,t->tm_min,t->tm_sec);
-         } else if(ilf==ILF_Common || ilf==ILF_Isa) {
-            getword_start(&gwarea,data+1);
-            if (getword_multisep(data,sizeof(data),&gwarea,':')<0){
-               printf("SARG: Maybe you have a broken date in your %s file.\n",arq);
-               exit(1);
-            }
-            if (getword_multisep(hora,sizeof(hora),&gwarea,' ')<0){
-               printf("SARG: Maybe you have a broken date in your %s file.\n",arq);
-               exit(1);
-            }
-            getword_start(&gwarea,data);
-            if (getword_multisep(dia,sizeof(dia),&gwarea,'/')<0){
-               printf("SARG: Maybe you have a broken date in your %s file.\n",arq);
-               exit(1);
-            }
-            if (getword_multisep(mes,sizeof(mes),&gwarea,'/')<0){
-               printf("SARG: Maybe you have a broken date in your %s file.\n",arq);
-               exit(1);
-            }
-            if (getword_multisep(ano,sizeof(ano),&gwarea,'/')<0){
-               printf("SARG: Maybe you have a broken date in your %s file.\n",arq);
-               exit(1);
-            }
-
-            if(strcmp(df,"u") == 0)
-               snprintf(tbuf,sizeof(tbuf),"%s%s%s",ano,mes,dia);
-            if(strcmp(df,"e") == 0)
-               snprintf(tbuf,sizeof(tbuf),"%s%s%s",dia,mes,ano);
-            builddia(dia,mes,ano,df,wdata);
-            idata=atoi(wdata);
-         } else if (ilf==ILF_Sarg) {
-            getword_start(&gwarea,data);
-            if (getword_multisep(mes,sizeof(mes),&gwarea,'/')<0){
-               printf("SARG: Maybe you have a broken date in your %s file.\n",arq);
-               exit(1);
-            }
-            if (getword_multisep(dia,sizeof(dia),&gwarea,'/')<0){
-               printf("SARG: Maybe you have a broken date in your %s file.\n",arq);
-               exit(1);
-            }
-            if (getword_multisep(ano,sizeof(ano),&gwarea,0)<0){
-               printf("SARG: Maybe you have a broken date in your %s file.\n",arq);
-               exit(1);
+         if(addr[0] != '\0'){
+            if(strcmp(addr,ip)!=0) continue;
+         }
+         if(fhost) {
+            if(!vhexclude(url)) {
+               if (debugm) printf(_("Excluded site: %s\n"),url);
+               totregsx++;
+               continue;
             }
          }
 
-         if(debugm)
-            printf("DATE=%s IDATA=%d DFROM=%d DUNTIL=%d\n",date,idata,dfrom,duntil);
-
-         l=1;
-         if(l){
-            if(addr[0] != '\0'){
-               if(strcmp(addr,ip)==0)
-                  l=1;else l=0;
-            }
-            if(fhost) {
-//              l=vhexclude(excludefile,ip);
-               l=vhexclude(excludefile,url);
-               if(!l) {
-                  if (debugm) printf("Excluded site: %s\n",url);
-                  totregsx++;
+         if(hm[0] != '\0') {
+            hmr[0]='\0';
+            chm++;
+            getword_start(&gwarea,hora);
+            while(chm) {
+               if (getword_multisep(warea,sizeof(warea),&gwarea,':')<0){
+                  debuga(_("Maybe you have a broken time in your %s file\n"),arq);
+                  exit(1);
                }
+               strncat(hmr,warea,2);
+               chm--;
             }
+            strncat(hmr,gwarea.current,2);
+
+            if(atoi(hmr) < atoi(hm) || atoi(hmr) > atoi(hmf)) continue;
          }
 
-         if(l){
-            if(date[0] != '\0'){
-               if(idata >= dfrom && idata <= duntil)
-                  l=1;else l=0;
-            }
+         if(site[0] != '\0'){
+            if(strstr(url,site)==0) continue;
          }
-         if(l){
-            if(hm[0] != '\0') {
-               bzero(hmr,sizeof(hmr));
-               chm++;
-               getword_start(&gwarea,hora);
-               while(chm) {
-                  if (getword_multisep(warea,sizeof(warea),&gwarea,':')<0){
-                     printf("SARG: Maybe you have a broken time in your %s file.\n",arq);
-                     exit(1);
+
+         if(userip) {
+            strcpy(user,ip);
+            id_is_ip=1;
+         } else {
+            id_is_ip=0;
+            if(strcmp(user,"-") == 0 || strcmp(user," ") == 0 || strcmp(user,"") == 0) {
+               if(RecordsWithoutUser == RECORDWITHOUTUSER_IP) {
+                  strcpy(user,ip);
+                  id_is_ip=1;
+               }
+               if(RecordsWithoutUser == RECORDWITHOUTUSER_IGNORE)
+                  continue;
+               if(RecordsWithoutUser == RECORDWITHOUTUSER_EVERYBODY)
+                  strcpy(user,"everybody");
+            } else {
+               strlow(user);
+               if(NtlmUserFormat == NTLMUSERFORMAT_USER) {
+                  if((str = strchr(user,'_')) != 0) {
+                     strcpy(warea,str+1);
+                     strcpy(user,warea);
+                  }
+                  if((str = strchr(user,'+')) != 0) {
+                     strcpy(warea,str+1);
+                     strcpy(user,warea);
                   }
-                  strncat(hmr,warea,2);
-                  chm--;
                }
-               strncat(hmr,gwarea.current,2);
-
-               if(atoi(hmr) >= atoi(hm) && atoi(hmr) <= atoi(hmf))
-                  l=1;else l=0;
-            }
-         }
-         if(l){
-            if(site[0] != '\0'){
-               if(strstr(url,site)!=0)
-                  l=1;else l=0;
             }
          }
 
-         if(userip)
-            strcpy(user,ip);
-
-         if(strcmp(user,"-") == 0 || strcmp(user," ") == 0 || strcmp(user,"") == 0) {
-            if(strcmp(RecordsWithoutUser,"ip") == 0)
-               strcpy(user,ip);
-            if(strcmp(RecordsWithoutUser,"ignore") == 0)
-               continue;
-            if(strcmp(RecordsWithoutUser,"everybody") == 0)
-               strcpy(user,"everybody");
-         }
          if(us[0] != '\0'){
-            if(strcmp(user,us)==0)
-               l=1;
-            else
-               l=0;
-         }
-
-         if(dotinuser) {
-            subs(user,sizeof(user),"_",".");
-            dotinuser=0;
+            if(strcmp(user,us)!=0) continue;
          }
 
          if(puser) {
@@ -1322,183 +1335,221 @@ int main(int argc,char *argv[])
                continue;
          }
 
-         if(l) {
-            if(fuser) {
-               l=vuexclude(excludeuser,user);
-               if(!l) {
-                  if (debugm) printf("Excluded user: %s\n",user);
-                  totregsx++;
-               }
+         if(fuser) {
+            if(!vuexclude(user)) {
+               if (debugm) printf(_("Excluded user: %s\n"),user);
+               totregsx++;
+               continue;
             }
          }
 
-         if(l) {
-            if(userip)
-               fixip(user);
-         }
+         if(strcmp(user,"-") ==0 || strcmp(user," ") ==0 || strcmp(user,"") ==0 || strcmp(user,":") ==0)
+            continue;
 
-         if(l && max_elapsed) {
+         if(max_elapsed) {
             if(atol(elap)>max_elapsed) {
                elap[0]='0';
                elap[1]='\0';
             }
          }
 
-         if(l) {
-            if(strcmp(user,"-") !=0 && url[0] != '\0' && strcmp(user," ") !=0 && strcmp(user,"") !=0 && strcmp(user,":") !=0){
-               if((str=(char *) strstr(bufz, "[SmartFilter:")) != (char *) NULL ) {
-                  fixendofline(str);
-                  sprintf(smartfilter,"\"%s\"",str+1);
-               } else sprintf(smartfilter,"\"\"");
+         if((str=(char *) strstr(linebuf, "[SmartFilter:")) != (char *) NULL ) {
+            fixendofline(str);
+            sprintf(smartfilter,"\"%s\"",str+1);
+         } else sprintf(smartfilter,"\"\"");
 
-               sprintf(bufz, "%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);
-
-               if ( strcmp ( user , sz_Last_User ) != 0 ) {
-                  if ( fp_Write_User )
-                     fclose( fp_Write_User ) ;
-                  sprintf (tmp3, "%s/sarg/%s.unsort", tmp, user);
+         nopen=0;
+         prev_ufile=NULL;
+         for (ufile=first_user_file ; ufile && strcmp(user,ufile->user->id)!=0 ; ufile=ufile->next) {
+            prev_ufile=ufile;
+            if (ufile->file) nopen++;
+         }
+         if (!ufile) {
+            ufile=malloc(sizeof(*ufile));
+            if (!ufile) {
+               debuga(_("Not enough memory to store the user %s\n"),user);
+               exit(1);
+            }
+            memset(ufile,0,sizeof(*ufile));
+            ufile->next=first_user_file;
+            first_user_file=ufile;
+            uinfo=userinfo_create(user);
+            ufile->user=uinfo;
+            uinfo->id_is_ip=id_is_ip;
+         } else {
+            if (prev_ufile) {
+               prev_ufile->next=ufile->next;
+               ufile->next=first_user_file;
+               first_user_file=ufile;
+            }
+         }
 
-                  if ((fp_Write_User = MY_FOPEN (tmp3, "a")) == NULL) {
-                     fprintf (stderr, "%s: (log) %s: %s - %s\n", argv[0], text[9], tmp3, strerror(errno));
-                     exit (1);
+         if (ufile->file==NULL) {
+            if (nopen>=maxopenfiles) {
+               x=0;
+               for (ufile1=first_user_file ; ufile1 ; ufile1=ufile1->next) {
+                  if (ufile1->file!=NULL) {
+                     if (x>=maxopenfiles) {
+                        fclose(ufile1->file);
+                        ufile1->file=NULL;
+                     }
+                     x++;
                   }
-                  strcpy( sz_Last_User , user ) ;
                }
-               fputs (bufz, fp_Write_User);
+            }
+            if (snprintf (tmp3, sizeof(tmp3), "%s/sarg/%s.unsort", tmp, ufile->user->filename)>=sizeof(tmp3)) {
+               debuga(_("Temporary user file name too long: %s/sarg/%s.unsort\n"), tmp, ufile->user->filename);
+               exit(1);
+            }
+            if ((ufile->file = MY_FOPEN (tmp3, "a")) == NULL) {
+               debuga(_("(log) Cannot open temporary file: %s - %s\n"), tmp3, strerror(errno));
+               exit (1);
+            }
+         }
 
-               if(strcmp(ParsedOutputLog, "no") != 0 && ilf!=ILF_Sarg)
-                  fputs(bufz,fp_log);
+         /*if ( strcmp ( user , sz_Last_User ) != 0 ) {
+            if ( fp_Write_User )
+               fclose( fp_Write_User ) ;
+            sprintf (tmp3, "%s/sarg/%s.unsort", tmp, user);
 
-               totregsg++;
+            if ((fp_Write_User = MY_FOPEN (tmp3, "a")) == NULL) {
+               fprintf (stderr, "%s: (log) %s: %s - %s\n", argv[0], _("Cannot open temporary file"), tmp3, strerror(errno));
+               exit (1);
+            }
+            strcpy( sz_Last_User , user ) ;
+         }*/
+         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);
 
-               if(download_flag && strstr(code,"DENIED") == 0) {
-                  ndownload = 1;
+         if(fp_log && ilf!=ILF_Sarg)
+            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);
 
-                  if ( ! fp_Download_Unsort ) {
-                     if ((fp_Download_Unsort = MY_FOPEN ( sz_Download_Unsort, "a")) == NULL) {
-                        fprintf (stderr, "%s: (log) %s: %s - %s\n", argv[0], text[9], tmp3, strerror(errno));
-                        exit (1);
-                     }
-                  }
-                  fprintf(fp_Download_Unsort,"%s\t%s\t%s\t%s\t%s\n",dia,hora,user,ip,download_url);
-               }
+         totregsg++;
 
-               if(strstr(ReportType,"denied") != 0 || strstr(ReportType,"auth_failures") != 0) {
-                  if(strstr(code,"DENIED/403") != 0) {
-                     fprintf(fp_denied, "%s\t%s\t%s\t%s\t%s\n",dia,hora,user,ip,urly);
-                     denied_count++;
-                  }
-                  if(strstr(code,"DENIED/401") != 0 || strstr(code,"DENIED/407") != 0) {
-                     if(fp_authfail)
-                        fprintf(fp_authfail, "%s\t%s\t%s\t%s\t%s\n",dia,hora,user,ip,urly);
-                     authfail_count++;
-                  }
-               }
+         if(!dataonly && download_flag && download_url && strstr(code,"DENIED") == 0) {
+            ndownload = 1;
 
-               if((!totper || idata<mindate) && ilf!=ILF_Sarg){
-                  totper++;
-                  mindate=idata;
-                  sprintf(period,"%s-",tbuf);
-                  sprintf(per_hour,"%s-",tbuf2);
-                  if(date[0] != '\0')
-                     fixper(tbuf, period, cduntil);
-                  if(debugz){
-                     debugaz("tbuf",tbuf);
-                     debugaz("period",period);
-                  }
+            if ( ! fp_Download_Unsort ) {
+               if ((fp_Download_Unsort = MY_FOPEN ( sz_Download_Unsort, "a")) == NULL) {
+                  debuga(_("(log) Cannot open temporary file: %s - %s\n"),tmp3, strerror(errno));
+                  exit (1);
                }
             }
+            fprintf(fp_Download_Unsort,"%s\t%s\t%s\t%s\t%s\n",dia,hora,user,ip,download_url);
+         }
 
-            if(debugm){
-               printf("IP=\t%s\n",ip);
-               printf("USER=\t%s\n",user);
-               printf("ELAP=\t%s\n",elap);
-               printf("DATE=\t%s\n",dia);
-               printf("TIME=\t%s\n",hora);
-               printf("FUNC=\t%s\n",fun);
-               printf("URL=\t%s\n",url);
-               printf("CODE=\t%s\n",code);
-               printf("LEN=\t%s\n",tam);
+         if((ReportType & REPORT_TYPE_DENIED) != 0 || (ReportType & REPORT_TYPE_AUTH_FAILURES) != 0) {
+            if(fp_denied && strstr(code,"DENIED/403") != 0) {
+               fprintf(fp_denied, "%s\t%s\t%s\t%s\t%s\n",dia,hora,user,ip,urly);
+               denied_count++;
+            }
+            if(fp_authfail && (strstr(code,"DENIED/401") != 0 || strstr(code,"DENIED/407") != 0)) {
+               fprintf(fp_authfail, "%s\t%s\t%s\t%s\t%s\n",dia,hora,user,ip,urly);
+               authfail_count++;
             }
          }
+
+         if((!totper || idata<mindate) && ilf!=ILF_Sarg){
+            totper++;
+            mindate=idata;
+            sprintf(period,"%s-",tbuf);
+            strcpy(start_hour,tbuf2);
+            if(date[0] != '\0')
+               fixper(tbuf, period, cduntil);
+            if(debugz){
+               debugaz("tbuf",tbuf);
+               debugaz("period",period);
+            }
+         }
+
+         if(debugm){
+            printf("IP=\t%s\n",ip);
+            printf("USER=\t%s\n",user);
+            printf("ELAP=\t%s\n",elap);
+            printf("DATE=\t%s\n",dia);
+            printf("TIME=\t%s\n",hora);
+            printf("FUNC=\t%s\n",fun);
+            printf("URL=\t%s\n",url);
+            printf("CODE=\t%s\n",code);
+            printf("LEN=\t%s\n",tam);
+         }
       }
       if (!from_stdin) {
          fclose(fp_in);
-         if( bool_ShowReadStatistics )
-            printf("SARG: Records in file: %lu, reading: %3.2f%%\n",recs1, (float) 100 );
+         if( ShowReadStatistics )
+            printf(_("SARG: Records in file: %lu, reading: %3.2f%%\n"),recs1, (float) 100 );
       }
    }
 
+   longline_free(&line);
    if ( fp_Download_Unsort )
      fclose (fp_Download_Unsort);
 
-   if (fp_Write_User)
-     fclose (fp_Write_User);
+   for (ufile=first_user_file ; ufile ; ufile=ufile1) {
+      ufile1=ufile->next;
+      if (ufile->file!=NULL) fclose(ufile->file);
+      free(ufile);
+   }
+
+   free_download();
+   free_excludecodes();
+   free_exclude();
 
    if(debug) {
       int totalcount=0;
 
       for (ilf=0 ; ilf<ILF_Last ; ilf++) totalcount+=ilf_count[ilf];
 
-      debuga("   %s: %ld, %s: %ld, %s: %ld",text[10],totregsl,text[11],totregsg,text[68],totregsx);
+      debuga(_("   Records read: %ld, written: %ld, excluded: %ld\n"),totregsl,totregsg,totregsx);
 
       if(ilf_count[ILF_Common]>0 && ilf_count[ILF_Squid]>0)
-         debuga("%s",text[12]);
+         debuga(_("Log with mixed records format (squid and common log)\n"));
 
       if(ilf_count[ILF_Common]>0 && ilf_count[ILF_Squid]==0)
-         debuga("%s",text[13]);
+         debuga(_("Common log format\n"));
 
       if(ilf_count[ILF_Common]==0 && ilf_count[ILF_Squid]>0)
-         debuga("%s",text[14]);
+         debuga(_("Squid log format\n"));
 
       if(ilf_count[ILF_Sarg]>0)
-         debuga("%s",text[124]);
+         debuga(_("Sarg log format\n"));
 
       if(totalcount==0) {
          if(!totregsg) {
-            fprintf(stderr, "SARG: %s\n",text[16]);
-            fprintf(stderr, "SARG: %s\n",text[21]);
-         } else fprintf(stderr, "SARG: %s\n",text[15]);
-         bzero(msg,sizeof(msg));
+            debuga(_("No records found\n"));
+            debuga(_("End\n"));
+         } else debuga(_("Log with invalid format\n"));
          if(fp_denied)
             fclose(fp_denied);
          if(fp_authfail)
             fclose(fp_authfail);
-         free_excludecodes();
+         userinfo_free();
          if(userfile)
             free(userfile);
-         if(excludefile)
-            free(excludefile);
-         if(excludeuser)
-            free(excludeuser);
-         unlink(tmp4);
-         unlink(tmp6);
+         close_usertab();
+         unlink(denied_unsort);
+         unlink(authfail_unsort);
          unlink(tmp3);
          exit(0);
       }
    }
 
    if(!totregsg){
-      fprintf(stderr, "SARG: %s\n",text[16]);
-      fprintf(stderr, "SARG: %s\n",text[21]);
+      debuga(_("No records found\n"));
+      debuga(_("End\n"));
 //      fclose(fp_ou);
       if(fp_denied)
          fclose(fp_denied);
       if(fp_authfail)
          fclose(fp_authfail);
-      free_excludecodes();
+      userinfo_free();
       if(userfile)
          free(userfile);
-      if(excludefile)
-         free(excludefile);
-      if(excludeuser)
-         free(excludeuser);
+      close_usertab();
       exit(0);
    }
 
    if(date[0] == '\0' && ilf_count[ILF_Sarg]==0) {
       strcat(period,tbuf);
-      strcat(per_hour,tbuf2);
    }
 
    if(debugz){
@@ -1508,7 +1559,7 @@ int main(int argc,char *argv[])
    }
 
    if(debug)
-      debuga("%s: %s",text[17],period);
+      debuga(_("Period: %s\n"),period);
 
 //   fclose(fp_ou);
    if(fp_denied)
@@ -1518,47 +1569,49 @@ int main(int argc,char *argv[])
 
    if(fp_log != NULL) {
       fclose(fp_log);
+      strcpy(end_hour,tbuf2);
       getword_start(&gwarea,period);
-      if (getword_multisep(val2,sizeof(val2),&gwarea,'-')<0){
-         printf("SARG: Maybe you have a broken date range definition.\n");
+      if (getword(val2,sizeof(val2),&gwarea,'-')<0){
+         debuga(_("Maybe you have a broken date range definition.\n"));
          exit(1);
       }
-      if (getword_multisep(val1,sizeof(val1),&gwarea,'\0')<0){
-         printf("SARG: Maybe you have a broken date range definition.\n");
+      if (getword(val1,sizeof(val1),&gwarea,'\0')<0){
+         debuga(_("Maybe you have a broken date range definition.\n"));
          exit(1);
       }
-      getword_start(&gwarea,per_hour);
-      if (getword_multisep(val3,sizeof(val3),&gwarea,'-')<0){
-         printf("SARG: Maybe you have a broken date range definition.\n");
-         exit(1);
-      }
-      sprintf(val4,"%s/sarg-%s_%s-%s_%s.log",ParsedOutputLog,val2,val3,val1,gwarea.current);
-      rename(arq_log,val4);
-      strcpy(arq_log,val4);
-
-      if(strcmp(ParsedOutputLogCompress,"nocompress") != 0) {
-         sprintf(val1,"\"%s\" \"%s\"",ParsedOutputLogCompress,arq_log);
-         cstatus=system(val1);
-         if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
-            fprintf(stderr, "SARG: command return status %d\n",WEXITSTATUS(cstatus));
-            fprintf(stderr, "SARG: command: %s\n",val1);
-            exit(1);
+      sprintf(val4,"%s/sarg-%s_%s-%s_%s.log",ParsedOutputLog,val2,start_hour,val1,end_hour);
+      if (rename(arq_log,val4)) {
+         debuga(_("failed to rename %s to %s - %s\n"),arq_log,val4,strerror(errno));
+      } else {
+         strcpy(arq_log,val4);
+
+         if(strcmp(ParsedOutputLogCompress,"nocompress") != 0 && ParsedOutputLogCompress[0] != '\0') {
+            /*
+            No double quotes around ParsedOutputLogCompress because it may contain command line options. If double quotes are
+            necessary around the command name, put them in the configuration file.
+            */
+            sprintf(val1,"%s \"%s\"",ParsedOutputLogCompress,arq_log);
+            cstatus=system(val1);
+            if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
+               debuga(_("command return status %d\n"),WEXITSTATUS(cstatus));
+               debuga(_("command: %s\n"),val1);
+               exit(1);
+            }
          }
       }
-
       if(debug)
-         debuga("%s %s",text[123],arq_log);
+         debuga(_("Sarg parsed log saved as %s\n"),arq_log);
    }
 
-   if(strstr(ReportType,"denied") != 0) {
-      sprintf(csort,"sort -T \"%s\" -k 3,3 -k 5,5 -o \"%s\" \"%s\"",tmp,tmp5,tmp4);
+   if(DataFile[0] == '\0' && (ReportType & REPORT_TYPE_DENIED) != 0) {
+      sprintf(csort,"sort -T \"%s\" -k 3,3 -k 5,5 -o \"%s\" \"%s\"",tmp,denied_sort,denied_unsort);
       cstatus=system(csort);
       if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
-         fprintf(stderr, "SARG: sort command return status %d\n",WEXITSTATUS(cstatus));
-         fprintf(stderr, "SARG: sort command: %s\n",csort);
+         debuga(_("sort command return status %d\n"),WEXITSTATUS(cstatus));
+         debuga(_("sort command: %s\n"),csort);
          exit(1);
       }
-      unlink(tmp4);
+      unlink(denied_unsort);
    }
 
    sort_users_log(tmp, debug);
@@ -1569,8 +1622,8 @@ int main(int argc,char *argv[])
       gerarel();
 
    unlink(tmp2);
-   if(strstr(ReportType,"denied") != 0)
-      unlink(tmp5);
+   if((ReportType & REPORT_TYPE_DENIED) != 0)
+      unlink(denied_sort);
 
    if(zip[0] != '\0' && strcmp(zip,"zcat") !=0) {
       recomp(arq, zip);
@@ -1578,28 +1631,16 @@ int main(int argc,char *argv[])
 //   else  unlink(arq);
 
    if(strcmp(tmp,"/tmp") != 0) {
-      if (snprintf(tmp4,sizeof(tmp4),"rm -rf \"%s\"",tmp)>=sizeof(tmp4)) {
-         fprintf(stderr,"SARG: Directory name too long: %s\n",tmp);
-         exit(1);
-      }
-      cstatus=system(tmp4);
-      if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
-         fprintf(stderr, "SARG: command return status %d\n",WEXITSTATUS(cstatus));
-         fprintf(stderr, "SARG: command: %s\n",tmp4);
-         exit(1);
-      }
+      unlinkdir(tmp,0);
    }
 
-   free_excludecodes();
+   userinfo_free();
    if(userfile)
       free(userfile);
-   if(excludefile)
-      free(excludefile);
-   if(excludeuser)
-      free(excludeuser);
+   close_usertab();
 
    if(debug)
-      debuga("%s",text[21]);
+      debuga(_("End\n"));
 
    exit(0);
 
@@ -1615,24 +1656,24 @@ static void getusers(const char *pwdfile, int debug)
    long int nreg=0;
 
    if(debug)
-      debuga("%s: %s",text[60],pwdfile);
+      debuga(_("Loading password file from: %s\n"),pwdfile);
 
    if ((fp_usr = fopen(pwdfile, "r")) == NULL) {
-      fprintf(stderr, "SARG: (getusers) %s: %s - %s\n",text[45],pwdfile,strerror(errno));
+      debuga(_("(getusers) Cannot open file: %s - %s\n"),pwdfile,strerror(errno));
       exit(1);
    }
 
    fseek(fp_usr, 0, SEEK_END);
    nreg = ftell(fp_usr);
    if (nreg<0) {
-      printf("SARG: Cannot get the size of file %s",pwdfile);
+      debuga(_("Cannot get the size of file %s\n"),pwdfile);
       exit(1);
    }
    nreg = nreg+5000;
    fseek(fp_usr, 0, SEEK_SET);
 
    if((userfile=(char *) malloc(nreg))==NULL){
-      fprintf(stderr, "SARG: %s (%ld):\n",text[59],nreg);
+      debuga(_("malloc error (%ld):\n"),nreg);
       exit(1);
    }
 
@@ -1642,7 +1683,7 @@ static void getusers(const char *pwdfile, int debug)
    while(fgets(buf,sizeof(buf),fp_usr)!=NULL) {
       str=strchr(buf,':');
       if (!str) {
-         printf("SARG: You have an invalid user in your %s file.\n",pwdfile);
+         debuga(_("You have an invalid user in your %s file.\n"),pwdfile);
          exit(1);
       }
       str[1]=0;
@@ -1653,97 +1694,3 @@ static void getusers(const char *pwdfile, int debug)
 
    return;
 }
-
-
-static void gethexclude(const char *hexfile, int debug)
-{
-
-   FILE *fp_ex;
-   char buf[255];
-   long int nreg=0;
-
-   if(debug)
-      debuga("%s: %s",text[67],hexfile);
-
-   if ((fp_ex = fopen(hexfile, "r")) == NULL) {
-      fprintf(stderr, "SARG: (gethexclude) %s: %s - %s\n",text[45],hexfile,strerror(errno));
-      exit(1);
-   }
-
-   fseek(fp_ex, 0, SEEK_END);
-   nreg = ftell(fp_ex);
-   if (nreg<0) {
-      printf("SARG: Cannot get the size of file %s",hexfile);
-      exit(1);
-   }
-   nreg += 11;
-   fseek(fp_ex, 0, SEEK_SET);
-
-   if((excludefile=(char *) malloc(nreg))==NULL){
-      fprintf(stderr, "SARG: %s (%ld):\n",text[59],nreg);
-      exit(1);
-   }
-
-   bzero(excludefile,nreg);
-
-   while(fgets(buf,sizeof(buf),fp_ex)!=NULL){
-     if(strchr(buf,'#') != NULL)
-        continue;
-     fixendofline(buf);
-     strcat(excludefile,buf);
-     strcat(excludefile," ");
-   }
-
-   strcat(excludefile,"*END* ");
-
-   fclose(fp_ex);
-
-   return;
-}
-
-
-static void getuexclude(const char *uexfile, int debug)
-{
-
-   FILE *fp_ex;
-   char buf[255];
-   long int nreg=0;
-
-   if(debug)
-      debuga("%s: %s",text[67],uexfile);
-
-   if ((fp_ex = fopen(uexfile, "r")) == NULL) {
-      fprintf(stderr, "SARG: (gethexclude) %s: %s - %s\n",text[45],uexfile,strerror(errno));
-      exit(1);
-   }
-
-   fseek(fp_ex, 0, SEEK_END);
-   nreg = ftell(fp_ex);
-   if (nreg<0) {
-      printf("SARG: Cannot get the size of file %s",uexfile);
-      exit(1);
-   }
-   nreg += 11;
-   fseek(fp_ex, 0, SEEK_SET);
-
-   if((excludeuser=(char *) malloc(nreg))==NULL){
-      fprintf(stderr, "SARG: %s (%ld):\n",text[59],nreg);
-      exit(1);
-   }
-
-   bzero(excludeuser,nreg);
-
-   while(fgets(buf,sizeof(buf),fp_ex)!=NULL){
-     if(strchr(buf,'#') != NULL)
-        continue;
-     fixendofline(buf);
-     strcat(excludeuser,buf);
-     strcat(excludeuser," ");
-   }
-
-   strcat(excludeuser,"*END* ");
-
-   fclose(fp_ex);
-
-   return;
-}