/*
- * AUTHOR: Pedro Lineu Orso pedro.orso@gmail.com
- * 1998, 2008
* 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/conf.h"
+#include "include/defs.h"
static char **files_done = NULL;
static int nfiles_done = 0;
-void read_log(char *wentp, FILE *fp_ou)
+static void read_log(const char *wentp, FILE *fp_ou)
{
FILE *fp_in = NULL;
- char bufbsf[255];
+ char buf[MAXLEN];
char leks[5], sep[2], res[MAXLEN];
- char mon[10], hour[15];
+ char mon[20], day[3], year[5], hour[15];
char list[MAXLEN];
char wdata[127];
+ char url[MAX_URL_LEN];
+ char user[MAX_USER_LEN];
+ char ip[25];
int idata=0;
int i;
+ char *str;
+ struct getwordstruct gwarea;
+ struct getwordstruct gwarea1;
if(debug) {
- strcpy(buf,text[7]);
- if (getword(urly,sizeof(urly),buf,' ')<0 || getword(href,sizeof(href),buf,' ')<0) {
- printf("SARG: Maybe you have a broken record or garbage in your %s string.\n",text[7]);
- exit(1);
- }
- sprintf(msg,"%s squidGuard %s: %s",urly,buf,wentp);
- debuga(msg);
+ debuga(_("Reading squidGuard log file %s\n"),wentp);
}
/* With squidGuard, you can log groups in only one log file.
*/
for (i=0; i<nfiles_done; i++)
if (!strcmp(wentp, files_done[i])) return;
-
+
nfiles_done++;
files_done = realloc(files_done, nfiles_done*sizeof(char *));
if (!files_done) {
- perror("parse squidGuard - realloc");
- exit(EXIT_FAILURE);
+ debuga(_("Not enough memory to store the name of the new squidGuard log to be read - %s\n"),strerror(errno));
+ exit(EXIT_FAILURE);
}
files_done[nfiles_done-1] = strdup(wentp);
if (!files_done[nfiles_done-1]) {
- perror("parse squidGuard - strdup");
- exit(EXIT_FAILURE);
+ debuga(_("Not enough memory to store the name of the new squidGuard log to be read - %s\n"),strerror(errno));
+ exit(EXIT_FAILURE);
}
if ((fp_in=fopen(wentp,"r"))==NULL) {
- fprintf(stderr, "SARG: (squidguard) %s: %s\n",text[8],wentp);
- exit(1);
+ debuga(_("(squidguard) Cannot open log file %s\n"),wentp);
+ exit(EXIT_FAILURE);
}
-
- if ((fp_in=fopen(wentp,"r"))==NULL) {
- fprintf(stderr, "SARG: (squidguard) %s: %s\n",text[8],wentp);
- exit(1);
- }
-
+
while (fgets(buf,sizeof(buf),fp_in) != NULL) {
- if(strlen(SquidGuardLogFormat) > 0) {
- strcpy(bufbsf,SquidGuardLogFormat);
+ getword_start(&gwarea,buf);
+ if(SquidGuardLogFormat[0] != '\0') {
+ getword_start(&gwarea1,SquidGuardLogFormat);
leks[0]='\0';
- if (getword(leks,sizeof(leks),bufbsf,'#')<0) {
- printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",wentp);
- exit(1);
+ if (getword(leks,sizeof(leks),&gwarea1,'#')<0) {
+ debuga(_("There is a broken record or garbage in your %s file\n"),wentp);
+ exit(EXIT_FAILURE);
}
while(strcmp(leks,"end") != 0) {
- if (getword(leks,sizeof(leks),bufbsf,'#')<0 || getword(sep,sizeof(sep),bufbsf,'#')<0) {
- printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",wentp);
- exit(1);
+ if (getword(leks,sizeof(leks),&gwarea1,'#')<0 || getword(sep,sizeof(sep),&gwarea1,'#')<0) {
+ debuga(_("Maybe you have a broken record or garbage in your %s file\n"),wentp);
+ exit(EXIT_FAILURE);
}
if(strcmp(leks,"end") != 0) {
- if (getword(res,sizeof(res),buf,sep[0])<0) {
- printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",wentp);
- exit(1);
+ if (getword(res,sizeof(res),&gwarea,sep[0])<0) {
+ debuga(_("Maybe you have a broken record or garbage in your %s file\n"),wentp);
+ exit(EXIT_FAILURE);
}
- if(strcmp(leks,"year") == 0)
+ if(strcmp(leks,"year") == 0) {
+ if (strlen(res)>=sizeof(year)) {
+ debuga(_("Year string too long in squidGuard log file %s\n"),wentp);
+ exit(EXIT_FAILURE);
+ }
strcpy(year,res);
- else if(strcmp(leks,"year") == 0)
- strcpy(year,res);
- else if(strcmp(leks,"mon") == 0)
+ } else if(strcmp(leks,"mon") == 0) {
+ if (strlen(res)>=sizeof(mon)) {
+ debuga(_("Month string too long in squidGuard log file %s\n"),wentp);
+ exit(EXIT_FAILURE);
+ }
strcpy(mon,res);
- else if(strcmp(leks,"day") == 0)
+ } else if(strcmp(leks,"day") == 0) {
+ if (strlen(res)>=sizeof(day)) {
+ debuga(_("Day string too long in squidGuard log file %s\n"),wentp);
+ exit(EXIT_FAILURE);
+ }
strcpy(day,res);
- else if(strcmp(leks,"hour") == 0)
+ } else if(strcmp(leks,"hour") == 0) {
+ if (strlen(res)>=sizeof(hour)) {
+ debuga(_("Hour string too long in squidGuard log file %s\n"),wentp);
+ exit(EXIT_FAILURE);
+ }
strcpy(hour,res);
- else if(strcmp(leks,"list") == 0)
+ } else if(strcmp(leks,"list") == 0) {
+ if (strlen(res)>=sizeof(list)) {
+ debuga(_("Banning list name too long in squidGuard log file %s\n"),wentp);
+ exit(EXIT_FAILURE);
+ }
strcpy(list,res);
- else if(strcmp(leks,"ip") == 0)
+ } else if(strcmp(leks,"ip") == 0) {
+ if (strlen(res)>=sizeof(ip)) {
+ debuga(_("IP address too long in squidGuard log file %s\n"),wentp);
+ exit(EXIT_FAILURE);
+ }
strcpy(ip,res);
- else if(strcmp(leks,"user") == 0)
+ } else if(strcmp(leks,"user") == 0) {
+ if (strlen(res)>=sizeof(user)) {
+ debuga(_("User ID too long in squidGuard log file %s\n"),wentp);
+ exit(EXIT_FAILURE);
+ }
strcpy(user,res);
- else if(strcmp(leks,"url") == 0)
+ } else if(strcmp(leks,"url") == 0) {
+ if (strlen(res)>=sizeof(url)) {
+ debuga(_("URL too long in squidGuard log file %s\n"),wentp);
+ exit(EXIT_FAILURE);
+ }
strcpy(url,res);
+ }
}
}
} else {
- if (getword(year,sizeof(year),buf,'-')<0 || getword(mon,sizeof(mon),buf,'-')<0 ||
- getword(day,sizeof(day),buf,' ')<0 || getword(hour,sizeof(hour),buf,' ')<0 ||
- getword(list,sizeof(list),buf,'/')<0 || getword(list,sizeof(list),buf,'/')<0 ||
- getword(tmp5,sizeof(tmp5),buf,'/')<0 || getword(tmp5,sizeof(tmp5),buf,'/')<0 ||
- getword(url,sizeof(url),buf,'/')<0 || getword(tmp5,sizeof(tmp5),buf,' ')<0 ||
- getword(ip,sizeof(ip),buf,'/')<0 || getword(user,sizeof(user),buf,' ')<0 ||
- getword(user,sizeof(user),buf,' ')<0) {
- printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",wentp);
- exit(1);
+ if (getword(year,sizeof(year),&gwarea,'-')<0 || getword(mon,sizeof(mon),&gwarea,'-')<0 ||
+ getword(day,sizeof(day),&gwarea,' ')<0 || getword(hour,sizeof(hour),&gwarea,' ')<0 ||
+ getword_skip(MAXLEN,&gwarea,'/')<0 || getword(list,sizeof(list),&gwarea,'/')<0 ||
+ getword_skip(MAXLEN,&gwarea,' ')<0 || getword(url,sizeof(url),&gwarea,' ')<0 ||
+ getword(ip,sizeof(ip),&gwarea,'/')<0 || getword_skip(MAXLEN,&gwarea,' ')<0 ||
+ getword(user,sizeof(user),&gwarea,' ')<0) {
+ debuga(_("There is a broken record or garbage in your %s file\n"),wentp);
+ exit(EXIT_FAILURE);
+ }
+ /*
+ The URL may be "http://url:port/data" if the method is GET or simply "url:port/" if the method is CONNECT.
+ The following code removes the protocol:// if it is detected and always truncates the URL after the domain name.
+ It will fail if the URL doesn't start with the protocol and contains two consecutive / in the path (i.e.
+ the URL is not normalized).
+ */
+ str=strchr(url,'/');
+ if (str) {
+ if (str[1]=='/') {
+ str+=2;
+ for (i=0 ; *str && *str!='/' ; i++) url[i]=*str++;
+ url[i]='\0';
+ } else {
+ *str='\0';
+ }
}
}
sprintf(wdata,"%s%s%s",year,mon,day);
idata = atoi(wdata);
- if(strcmp(SquidguardIgnoreDate,"on") == 0) {
- if(idata < dfrom && idata > duntil)
+ if(SquidguardIgnoreDate) {
+ if(idata < dfrom || idata > duntil)
continue;
}
if (strcmp(user,"-") == 0) {
strcpy(user,ip);
- bzero(ip, 30);
+ ip[0]='\0';
}
- sprintf(tmp6,"%s %s%s%s %s %s %s %s\n",user,year,mon,day,hour,ip,url,list);
- fputs(tmp6, fp_ou);
+ fprintf(fp_ou,"%s\t%s%s%s\t%s\t%s\t%s\t%s\n",user,year,mon,day,hour,ip,url,list);
squidguard_count++;
}
if (fp_in) fclose(fp_in);
}
-int squidguard_log()
+void squidguard_log(void)
{
-
FILE *fp_ou = NULL, *fp_guard = NULL;
+ char buf[MAXLEN];
char guard_in[MAXLEN];
char guard_ou[MAXLEN];
char logdir[MAXLEN];
char year[10], day[10], mon[10];
char user[MAXLEN];
- char ip[30];
- int x, y;
+ char tmp6[MAXLEN];
+ int y;
int cstatus;
+ char *str;
+ char *str2;
str2 = user;
if(strlen(SquidGuardConf) < 1 && strlen(SquidGuardLogAlternate) < 1)
return;
- if (strlen(SquidGuardLogAlternate) > 0)
+ if (SquidGuardLogAlternate[0] != '\0')
SquidGuardConf[0]='\0';
sprintf(guard_in,"%s/squidguard.unsort",tmp);
sprintf(guard_ou,"%s/squidguard.log",tmp);
if((fp_ou=fopen(guard_in,"a"))==NULL) {
- fprintf(stderr, "SARG: (squidguard) %s: %s\n",text[8],guard_in);
- exit(1);
+ debuga(_("(squidguard) Cannot open log file %s\n"),guard_in);
+ exit(EXIT_FAILURE);
}
bzero(day, 3);
bzero(mon, 4);
bzero(year, 5);
- if(strcmp(SquidguardIgnoreDate,"on") == 0) {
+ if(SquidguardIgnoreDate) {
if(strcmp(df,"e") == 0) {
strncpy(day,period,2);
strncpy(mon,period+2,3);
}
}
- if(strlen(SquidGuardConf) > 0) {
+ if(SquidGuardConf[0] != 0) {
if(access(SquidGuardConf, R_OK) != 0) {
- sprintf(msg,"Cannot open squidGuard config file: %s",SquidGuardConf);
- debuga(msg);
- exit(1);
+ debuga(_("Cannot open squidGuard config file: %s\n"),SquidGuardConf);
+ exit(EXIT_FAILURE);
}
if((fp_guard=fopen(SquidGuardConf,"r"))==NULL) {
- fprintf(stderr, "SARG: (squidguard) %s: %s\n",text[8],SquidGuardConf);
- exit(1);
+ debuga(_("(squidguard) Cannot open log file %s\n"),SquidGuardConf);
+ exit(EXIT_FAILURE);
}
-
+
+ logdir[0]=0;
while(fgets(buf,sizeof(buf),fp_guard)!=NULL) {
- if(strstr(buf,"\n") != 0)
- buf[strlen(buf)-1]='\0';
- if(strstr(buf,"logdir ") != 0) {
- if (getword(logdir,sizeof(logdir),buf,' ')<0 || getword(logdir,sizeof(logdir),buf,' ')<0) {
- printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",SquidGuardConf);
- exit(1);
+ fixendofline(buf);
+ if((str=get_param_value("logdir",buf))!=NULL) {
+ /*
+ We want to tolerate spaces inside the directory name but we must also
+ remove the trailing spaces left by the editor after the directory name.
+ This should not be a problem as nobody use a file name with trailing spaces.
+ */
+ for (y=strlen(str)-1 ; y>=0 && (unsigned char)str[y]<=' ' ; y--);
+ if (y>=sizeof(logdir)-1) y=sizeof(logdir)-2;
+ logdir[y+1] = '\0';
+ while (y>=0) {
+ logdir[y] = str[y];
+ y--;
}
- }
- if((str=(char *) strstr(buf, "log")) != (char *) NULL ) {
- str=str+3;
- str2[0]='\0';
- y=0;
- while(*str == ' ')
- str++;
- if (str == (char *) strstr(str, "anonymous"))
- str+=9;
+ } else if((str=get_param_value("log",buf))!=NULL) {
+ if((str2=get_param_value("anonymous",str))!=NULL)
+ str=str2;
- for (x=0; x<=strlen(str); x++) {
- if (str[x] != ' ' && str[x] != '\t') {
- str2[y] = str[x];
- y++;
- }
- }
- if(strchr(str2,' ') != 0) {
- if (getword(warea,sizeof(warea),str2,' ')<0) {
- printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",SquidGuardConf);
- exit(1);
+ /*
+ If logdir is defined, we prepend it to the log file name, otherwise, we assume
+ the log directive provides an absolute file name to the log file. Therefore,
+ we don't need to add an additionnal / at the beginning of the log file name.
+ */
+ y=(logdir[0]) ? sprintf(wentp,"%s/",logdir) : 0;
+ /*
+ Spaces are allowed in the name of the log file. The file name ends at the first #
+ because it is assumed it is an end of line comment. Any space before the # is then
+ removed. Any control character (i.e. a character with a code lower than 32) ends
+ the file name. That includes the terminating zero.
+ */
+ while((unsigned char)*str>=' ' && *str!='#' && y<sizeof(wentp)-1)
+ wentp[y++]=*str++;
+ if(*str=='#') {
+ str--;
+ while(*str==' ' && y>0) {
+ str--;
+ y--;
}
- strcpy(str2,warea);
}
- if(strchr(str2,'#') != 0) {
- if (getword(warea,sizeof(warea),str2,'#')<0) {
- printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",SquidGuardConf);
- exit(1);
- }
- strcpy(str2,warea);
- }
- sprintf(wentp,"%s/%s",logdir,str2);
+ wentp[y]=0;
read_log(wentp,fp_ou);
}
}
} else {
- sprintf(wentp,"%s",SquidGuardLogAlternate);
+ strcpy(wentp,SquidGuardLogAlternate);
read_log(wentp,fp_ou);
}
if (fp_guard) fclose(fp_guard);
if (fp_ou) fclose(fp_ou);
+ if (files_done) {
+ for (y=0; y<nfiles_done; y++)
+ if (files_done[y]) free(files_done[y]);
+ free(files_done);
+ }
+
if(debug) {
- sprintf(msg,"%s: %s",text[54],guard_ou);
- debuga(msg);
+ debuga(_("Sorting file: %s\n"),guard_ou);
}
- sprintf(tmp6,"sort -k 1,1 -k 2,2 -k 4,4 '%s' -o '%s'",guard_in, guard_ou);
+ sprintf(tmp6,"sort -k 1,1 -k 2,2 -k 4,4 \"%s\" -o \"%s\"",guard_in, guard_ou);
cstatus=system(tmp6);
if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
- fprintf(stderr, "SARG: sort command return status %d\n",WEXITSTATUS(cstatus));
- fprintf(stderr, "SARG: sort command: %s\n",tmp6);
- exit(1);
+ debuga(_("sort command return status %d\n"),WEXITSTATUS(cstatus));
+ debuga(_("sort command: %s\n"),tmp6);
+ exit(EXIT_FAILURE);
}
unlink(guard_in);