]> git.ipfire.org Git - thirdparty/sarg.git/blame - redirector.c
Generate redirector log even if -d is not given
[thirdparty/sarg.git] / redirector.c
CommitLineData
25697a35 1/*
94ff9470 2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
110ce984 3 * 1998, 2015
25697a35
GS
4 *
5 * SARG donations:
6 * please look at http://sarg.sourceforge.net/donations.php
1164c474
FM
7 * Support:
8 * http://sourceforge.net/projects/sarg/forums/forum/363374
25697a35
GS
9 * ---------------------------------------------------------------------
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
24 *
25 */
26
27#include "include/conf.h"
5f3cfd1d 28#include "include/defs.h"
25697a35 29
d6e703cc
FM
30static char **files_done = NULL;
31static int nfiles_done = 0;
32
bca2fdfd
FM
33//! The number of invalid lines found in the redirector report.
34static int RedirectorErrors=0;
cf1a88b9
FM
35//! The file containing the sorted entries.
36static char redirector_sorted[MAXLEN]="";
d6e703cc 37
bca2fdfd 38static void parse_log(FILE *fp_ou,char *buf)
491b862f 39{
9bd92830
FM
40 char leks[5], sep[2], res[MAXLEN];
41 char hour[15];
42 char source[128], list[128];
0a6722a1
FM
43 char full_url[MAX_URL_LEN];
44 const char *url;
9bd92830 45 char user[MAX_USER_LEN];
ad4353be 46 char ip[45];
b6b6cb8c 47 char userlabel[MAX_USER_LEN];
9bd92830
FM
48 long long int lmon, lday, lyear;
49 int mon, day, year;
50 int idata=0;
9bd92830
FM
51 bool id_is_ip;
52 struct getwordstruct gwarea;
53 struct getwordstruct gwarea1;
54 struct userinfostruct *uinfo;
bca2fdfd
FM
55
56 getword_start(&gwarea,buf);
57 if(RedirectorLogFormat[0] != '\0') {
58 getword_start(&gwarea1,RedirectorLogFormat);
59 leks[0]='\0';
60 if (getword(leks,sizeof(leks),&gwarea1,'#')<0) {
af961877 61 debuga(__FILE__,__LINE__,_("Invalid \"redirector_log_format\" option in your sarg.conf (too many characters before first tag)\n"));
bca2fdfd
FM
62 exit(EXIT_FAILURE);
63 }
64 year=0;
65 mon=0;
66 day=0;
67 hour[0]='\0';
68 source[0]='\0';
69 list[0]='\0';
70 ip[0]='\0';
71 user[0]='\0';
72 full_url[0]='\0';
73 while(strcmp(leks,"end") != 0) {
74 if (getword(leks,sizeof(leks),&gwarea1,'#')<0) {
af961877 75 debuga(__FILE__,__LINE__,_("Invalid \"redirector_log_format\" option in your sarg.conf (missing # at end of tag)\n"));
bca2fdfd
FM
76 exit(EXIT_FAILURE);
77 }
78 if (getword(sep,sizeof(sep),&gwarea1,'#')<0) {
af961877 79 debuga(__FILE__,__LINE__,_("Invalid \"redirector_log_format\" option in your sarg.conf (too many characters in column separator)\n"));
bca2fdfd
FM
80 exit(EXIT_FAILURE);
81 }
82 if(strcmp(leks,"end") != 0) {
83 if (getword_limit(res,sizeof(res),&gwarea,sep[0])<0) {
af961877 84 debuga(__FILE__,__LINE__,_("Parsing of tag \"%s\" in redirector log \"%s\" returned no result\n"),leks,wentp);
bca2fdfd
FM
85 RedirectorErrors++;
86 return;
87 }
88 if(strcmp(leks,"year") == 0) {
89 year=atoi(res);
90 } else if(strcmp(leks,"mon") == 0) {
91 mon=atoi(res);
92 } else if(strcmp(leks,"day") == 0) {
93 day=atoi(res);
94 } else if(strcmp(leks,"hour") == 0) {
95 if (strlen(res)>=sizeof(hour)) {
af961877 96 debuga(__FILE__,__LINE__,_("Hour string too long in redirector log file \"%s\"\n"),wentp);
bca2fdfd
FM
97 RedirectorErrors++;
98 return;
99 }
100 strcpy(hour,res);
101 } else if(strcmp(leks,"source") == 0) {
102 if (strlen(res)>=sizeof(source)) {
af961877 103 debuga(__FILE__,__LINE__,_("Banning source name too long in redirector log file \"%s\"\n"),wentp);
bca2fdfd
FM
104 RedirectorErrors++;
105 return;
106 }
107 strcpy(source,res);
108 } else if(strcmp(leks,"list") == 0) {
109 if (strlen(res)>=sizeof(list)) {
af961877 110 debuga(__FILE__,__LINE__,_("Banning list name too long in redirector log file \"%s\"\n"),wentp);
bca2fdfd
FM
111 RedirectorErrors++;
112 return;
113 }
114 strcpy(list,res);
115 } else if(strcmp(leks,"ip") == 0) {
116 if (strlen(res)>=sizeof(ip)) {
af961877 117 debuga(__FILE__,__LINE__,_("IP address too long in redirector log file \"%s\"\n"),wentp);
bca2fdfd
FM
118 RedirectorErrors++;
119 return;
120 }
121 strcpy(ip,res);
122 } else if(strcmp(leks,"user") == 0) {
123 if (strlen(res)>=sizeof(user)) {
af961877 124 debuga(__FILE__,__LINE__,_("User ID too long in redirector log file \"%s\"\n"),wentp);
bca2fdfd
FM
125 RedirectorErrors++;
126 return;
127 }
128 strcpy(user,res);
129 } else if(strcmp(leks,"url") == 0) {
d19124ac
FM
130 /*
131 * Don't worry about the url being truncated as we only keep the host name
132 * any way...
133 */
134 safe_strcpy(full_url,res,sizeof(full_url));
bca2fdfd
FM
135 }
136 }
137 }
138 } else {
139 if (getword_atoll(&lyear,&gwarea,'-')<0 || getword_atoll(&lmon,&gwarea,'-')<0 ||
140 getword_atoll(&lday,&gwarea,' ')<0) {
af961877 141 debuga(__FILE__,__LINE__,_("Invalid date in file \"%s\"\n"),wentp);
bca2fdfd
FM
142 RedirectorErrors++;
143 return;
144 }
145 year=(int)lyear;
146 mon=(int)lmon;
147 day=(int)lday;
148 if (getword(hour,sizeof(hour),&gwarea,' ')<0) {
af961877 149 debuga(__FILE__,__LINE__,_("Invalid time in file \"%s\"\n"),wentp);
bca2fdfd
FM
150 RedirectorErrors++;
151 return;
152 }
153 if (getword_skip(MAXLEN,&gwarea,'(')<0 || getword(source,sizeof(source),&gwarea,'/')<0) {
af961877 154 debuga(__FILE__,__LINE__,_("Invalid redirected source in file \"%s\"\n"),wentp);
bca2fdfd
FM
155 RedirectorErrors++;
156 return;
157 }
158 if (getword(list,sizeof(list),&gwarea,'/')<0) {
af961877 159 debuga(__FILE__,__LINE__,_("Invalid redirected list in file \"%s\"\n"),wentp);
bca2fdfd
FM
160 RedirectorErrors++;
161 return;
162 }
163 if (getword_skip(MAXLEN,&gwarea,' ')<0 || getword_limit(full_url,sizeof(full_url),&gwarea,' ')<0) {
af961877 164 debuga(__FILE__,__LINE__,_("Invalid url in file \"%s\"\n"),wentp);
bca2fdfd
FM
165 RedirectorErrors++;
166 return;
167 }
168 if (getword(ip,sizeof(ip),&gwarea,'/')<0) {
af961877 169 debuga(__FILE__,__LINE__,_("Invalid source IP in file \"%s\"\n"),wentp);
bca2fdfd
FM
170 RedirectorErrors++;
171 return;
172 }
173 if (getword_skip(MAXLEN,&gwarea,' ')<0 || getword(user,sizeof(user),&gwarea,' ')<0) {
af961877 174 debuga(__FILE__,__LINE__,_("Invalid user in file \"%s\"\n"),wentp);
bca2fdfd
FM
175 RedirectorErrors++;
176 return;
177 }
178 }
179 url=process_url(full_url,false);
180
181 //sprintf(warea,"%04d%02d%02d",year,mon,day);
182
22774edd 183 if (RedirectorFilterOutDate && (dfrom!=0 || duntil!=0)) {
bca2fdfd
FM
184 idata = year*10000+mon*100+day;
185 if(idata < dfrom || idata > duntil)
186 return;
187 }
188
189 if(UserIp) {
190 strcpy(user,ip);
191 id_is_ip=true;
192 } else {
193 id_is_ip=false;
81a022d8 194 if (user[0]=='\0' || (user[1]=='\0' && (user[0]=='-' || user[0]==' '))) {
bca2fdfd
FM
195 if(RecordsWithoutUser == RECORDWITHOUTUSER_IP) {
196 strcpy(user,ip);
197 id_is_ip=true;
198 }
199 if(RecordsWithoutUser == RECORDWITHOUTUSER_IGNORE)
200 return;
201 if(RecordsWithoutUser == RECORDWITHOUTUSER_EVERYBODY)
202 strcpy(user,"everybody");
203 }
204 }
205 uinfo=userinfo_find_from_id(user);
206 if (!uinfo) {
aa6ac9f2 207 uinfo=userinfo_create(user,(id_is_ip) ? NULL : ip);
bca2fdfd
FM
208 uinfo->no_report=true;
209 if(Ip2Name && id_is_ip) ip2name(user,sizeof(user));
b6b6cb8c
FM
210 user_find(userlabel,MAX_USER_LEN, user);
211 userinfo_label(uinfo,userlabel);
bca2fdfd
FM
212 }
213 fprintf(fp_ou,"%s\t%04d%02d%02d\t%s\t%s\t%s\t",uinfo->id,year,mon,day,hour,ip,url);
214 if (source[0] && list[0])
215 fprintf(fp_ou,"%s/%s\n",source,list);
216 else if (source[0])
217 fprintf(fp_ou,"%s\n",source);
218 else
219 fprintf(fp_ou,"%s\n",list);
220 redirector_count++;
221}
222
223static void read_log(const char *wentp, FILE *fp_ou,int dfrom,int duntil)
224{
800eafb8 225 FileObject *fp_in = NULL;
bca2fdfd
FM
226 char *buf;
227 int i;
9bd92830 228 longline line;
491b862f 229
9bd92830 230 if(debug) {
af961877 231 debuga(__FILE__,__LINE__,_("Reading redirector log file \"%s\"\n"),wentp);
9bd92830 232 }
d6e703cc 233
9bd92830
FM
234 /* With squidGuard, you can log groups in only one log file.
235 We must parse each log files only one time. Example :
236 dest porn {
237 domainlist porn/domains
238 urllist porn/urls
239 log file1.log
240 }
241 dest aggressive {
242 domainlist aggressive/domains
243 urllist aggressive/urls
244 log file2.log
245 }
246 dest audio-video {
247 domainlist audio-video/domains
248 urllist audio-video/urls
249 log file1.log
250 }
251 */
252 for (i=0; i<nfiles_done; i++)
253 if (!strcmp(wentp, files_done[i])) return;
06e3cc62 254
9bd92830
FM
255 nfiles_done++;
256 files_done = realloc(files_done, nfiles_done*sizeof(char *));
257 if (!files_done) {
af961877 258 debuga(__FILE__,__LINE__,_("Not enough memory to store the name of the new redirector log to be read - %s\n"),strerror(errno));
9bd92830
FM
259 exit(EXIT_FAILURE);
260 }
261 files_done[nfiles_done-1] = strdup(wentp);
262 if (!files_done[nfiles_done-1]) {
af961877 263 debuga(__FILE__,__LINE__,_("Not enough memory to store the name of the new redirector log to be read - %s\n"),strerror(errno));
9bd92830
FM
264 exit(EXIT_FAILURE);
265 }
d6e703cc 266
800eafb8
FM
267 if ((fp_in=FileObject_Open(wentp))==NULL) {
268 debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),wentp,FileObject_GetLastOpenError());
9bd92830
FM
269 exit(EXIT_FAILURE);
270 }
06e3cc62 271
9bd92830 272 if ((line=longline_create())==NULL) {
af961877 273 debuga(__FILE__,__LINE__,_("Not enough memory to read file \"%s\"\n"),wentp);
9bd92830
FM
274 exit(EXIT_FAILURE);
275 }
2d4c92a1 276
9bd92830 277 while ((buf=longline_read(fp_in,line)) != NULL) {
bca2fdfd 278 parse_log(fp_ou,buf);
9bd92830 279 }
800eafb8
FM
280 if (FileObject_Close(fp_in)) {
281 debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),wentp,FileObject_GetLastCloseError());
204781f4
FM
282 exit(EXIT_FAILURE);
283 }
9bd92830
FM
284 longline_destroy(&line);
285 return;
491b862f
GS
286}
287
288
330b1c52 289void redirector_log(void)
25697a35 290{
9bd92830
FM
291 FILE *fp_ou = NULL, *fp_guard = NULL;
292 char buf[MAXLEN];
293 char guard_in[MAXLEN];
9bd92830
FM
294 char logdir[MAXLEN];
295 char user[MAXLEN];
296 char tmp6[MAXLEN];
297 int i;
298 int y;
299 int cstatus;
300 int dfrom, duntil;
301 char *str;
302 char *str2;
25697a35 303
9bd92830 304 str2 = user;
d6e703cc 305
9f93fec3 306 if(SquidGuardConf[0] == '\0' && NRedirectorLogs == 0) {
af961877 307 if (debugz>=LogLevel_Process) debugaz(__FILE__,__LINE__,_("No redirector logs provided to produce that kind of report\n"));
007905af 308 return;
9f93fec3 309 }
25697a35 310
c98d6a0f 311 snprintf(guard_in,sizeof(guard_in),"%s/redirector.int_unsort",tmp);
cf1a88b9 312 if((fp_ou=fopen(guard_in,"w"))==NULL) {
af961877 313 debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),guard_in,strerror(errno));
9bd92830
FM
314 exit(EXIT_FAILURE);
315 }
25697a35 316
9bd92830
FM
317 dfrom=(period.start.tm_year+1900)*10000+(period.start.tm_mon+1)*100+period.start.tm_mday;
318 duntil=(period.end.tm_year+1900)*10000+(period.end.tm_mon+1)*100+period.end.tm_mday;
25697a35 319
9bd92830
FM
320 if (NRedirectorLogs>0) {
321 for (i=0 ; i<NRedirectorLogs ; i++)
322 read_log(RedirectorLogs[i],fp_ou,dfrom,duntil);
323 } else {
324 if(access(SquidGuardConf, R_OK) != 0) {
af961877 325 debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),SquidGuardConf,strerror(errno));
9bd92830
FM
326 exit(EXIT_FAILURE);
327 }
25697a35 328
9bd92830 329 if((fp_guard=fopen(SquidGuardConf,"r"))==NULL) {
af961877 330 debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),SquidGuardConf,strerror(errno));
9bd92830
FM
331 exit(EXIT_FAILURE);
332 }
5f3cfd1d 333
9bd92830
FM
334 logdir[0]=0;
335 while(fgets(buf,sizeof(buf),fp_guard)!=NULL) {
336 fixendofline(buf);
337 if((str=get_param_value("logdir",buf))!=NULL) {
338 /*
339 We want to tolerate spaces inside the directory name but we must also
340 remove the trailing spaces left by the editor after the directory name.
341 This should not be a problem as nobody use a file name with trailing spaces.
342 */
343 for (y=strlen(str)-1 ; y>=0 && (unsigned char)str[y]<=' ' ; y--);
344 if (y>=sizeof(logdir)-1) y=sizeof(logdir)-2;
345 logdir[y+1] = '\0';
346 while (y>=0) {
347 logdir[y] = str[y];
348 y--;
349 }
350 } else if((str=get_param_value("log",buf))!=NULL) {
351 if((str2=get_param_value("anonymous",str))!=NULL)
352 str=str2;
d6e703cc 353
9bd92830
FM
354 /*
355 If logdir is defined, we prepend it to the log file name, otherwise, we assume
356 the log directive provides an absolute file name to the log file. Therefore,
357 we don't need to add an additionnal / at the beginning of the log file name.
358 */
359 y=(logdir[0]) ? sprintf(wentp,"%s/",logdir) : 0;
360 /*
361 Spaces are allowed in the name of the log file. The file name ends at the first #
362 because it is assumed it is an end of line comment. Any space before the # is then
363 removed. Any control character (i.e. a character with a code lower than 32) ends
364 the file name. That includes the terminating zero.
365 */
366 while((unsigned char)*str>=' ' && *str!='#' && y<sizeof(wentp)-1)
367 wentp[y++]=*str++;
368 if(*str=='#') {
369 str--;
370 while(*str==' ' && y>0) {
371 str--;
372 y--;
373 }
374 }
375 wentp[y]=0;
376 read_log(wentp,fp_ou,dfrom,duntil);
377 }
378 }
204781f4 379 if (fclose(fp_guard)==EOF) {
af961877 380 debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),SquidGuardConf,strerror(errno));
204781f4
FM
381 exit(EXIT_FAILURE);
382 }
9bd92830 383 }
491b862f 384
507460ae 385 if (fp_ou && fclose(fp_ou)==EOF) {
af961877 386 debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),guard_in,strerror(errno));
507460ae
FM
387 exit(EXIT_FAILURE);
388 }
491b862f 389
9bd92830
FM
390 if (files_done) {
391 for (y=0; y<nfiles_done; y++)
392 if (files_done[y]) free(files_done[y]);
393 free(files_done);
394 }
c274f011 395
cf1a88b9
FM
396 if (redirector_count) {
397 snprintf(redirector_sorted,sizeof(redirector_sorted),"%s/redirector.int_log",tmp);
398 if(debug) {
af961877 399 debuga(__FILE__,__LINE__,_("Sorting file \"%s\"\n"),redirector_sorted);
cf1a88b9 400 }
25697a35 401
cf1a88b9 402 if (snprintf(tmp6,sizeof(tmp6),"sort -t \"\t\" -k 1,1 -k 2,2 -k 4,4 \"%s\" -o \"%s\"",guard_in, redirector_sorted)>=sizeof(tmp6)) {
af961877 403 debuga(__FILE__,__LINE__,_("Sort command too long when sorting file \"%s\" to \"%s\"\n"),guard_in,redirector_sorted);
cf1a88b9
FM
404 exit(EXIT_FAILURE);
405 }
406 cstatus=system(tmp6);
407 if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
af961877
FM
408 debuga(__FILE__,__LINE__,_("sort command return status %d\n"),WEXITSTATUS(cstatus));
409 debuga(__FILE__,__LINE__,_("sort command: %s\n"),tmp6);
cf1a88b9
FM
410 exit(EXIT_FAILURE);
411 }
9bd92830 412 }
491b862f 413
11767c6a 414 if (!KeepTempLog && unlink(guard_in)) {
af961877 415 debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),guard_in,strerror(errno));
08f9b029
FM
416 exit(EXIT_FAILURE);
417 }
9bd92830 418 return;
25697a35 419}
330b1c52 420
7ae50eee
FM
421static void show_ignored_redirector(FILE *fp_ou,int count)
422{
423 char ignored[80];
424
425 snprintf(ignored,sizeof(ignored),ngettext("%d more redirector entry not shown here&hellip;","%d more redirector entries not shown here&hellip;",count),count);
426 fprintf(fp_ou,"<tr><td class=\"data\"></td><td class=\"data\"></td><td class=\"data\"></td><td class=\"data2 more\">%s</td><td class=\"data\"></td></tr>\n",ignored);
427}
428
330b1c52
FM
429void redirector_report(void)
430{
800eafb8
FM
431 FileObject *fp_in = NULL;
432 FILE *fp_ou = NULL;
330b1c52
FM
433
434 char *buf;
435 char *url;
330b1c52
FM
436 char report[MAXLEN];
437 char ip[45];
438 char rule[255];
439 char oip[45];
440 char user[MAXLEN];
441 char ouser[MAXLEN];
442 char data[15];
443 char hora[15];
444 char ouser2[255];
445 char oname[MAXLEN];
446 bool z=false;
447 int count=0;
448 long long int data2;
449 bool new_user;
450 struct getwordstruct gwarea;
451 const struct userinfostruct *uinfo;
452 struct tm t;
453 longline line;
454
455 ouser[0]='\0';
456 ouser2[0]='\0';
457
330b1c52 458 if(!redirector_count) {
cb59dc47 459 if (debugz>=LogLevel_Process) {
cf1a88b9 460 if (redirector_sorted[0])
af961877 461 debugaz(__FILE__,__LINE__,_("Redirector report not generated because it is empty\n"));
cf1a88b9 462 }
330b1c52
FM
463 return;
464 }
465
466 snprintf(report,sizeof(report),"%s/redirector.html",outdirname);
467
800eafb8
FM
468 if((fp_in=FileObject_Open(redirector_sorted))==NULL) {
469 debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),redirector_sorted,FileObject_GetLastOpenError());
330b1c52
FM
470 exit(EXIT_FAILURE);
471 }
472
473 if((fp_ou=fopen(report,"w"))==NULL) {
af961877 474 debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),report,strerror(errno));
330b1c52
FM
475 exit(EXIT_FAILURE);
476 }
477
478 if ((line=longline_create())==NULL) {
af961877 479 debuga(__FILE__,__LINE__,_("Not enough memory to read file \"%s\"\n"),redirector_sorted);
330b1c52
FM
480 exit(EXIT_FAILURE);
481 }
482
483 write_html_header(fp_ou,(IndexTree == INDEX_TREE_DATE) ? 3 : 1,_("Redirector report"),HTML_JS_NONE);
484 fputs("<tr><td class=\"header_c\">",fp_ou);
485 fprintf(fp_ou,_("Period: %s"),period.html);
486 fputs("</td></tr>\n",fp_ou);
487 fprintf(fp_ou,"<tr><th class=\"header_c\">%s</th></tr>\n",_("Redirector report"));
488 close_html_header(fp_ou);
489
490 fputs("<div class=\"report\"><table cellpadding=1 cellspacing=2>\n",fp_ou);
491 fprintf(fp_ou,"<tr><th class=\"header_l\">%s</th><th class=\"header_l\">%s</th><th class=\"header_l\">%s</th><th class=\"header_l\">%s</th><th class=\"header_l\">%s</th></tr>\n",_("USERID"),_("IP/NAME"),_("DATE/TIME"),_("ACCESSED SITE"),_("RULE"));
492
493 while((buf=longline_read(fp_in,line))!=NULL) {
494 getword_start(&gwarea,buf);
495 if (getword(user,sizeof(user),&gwarea,'\t')<0) {
af961877 496 debuga(__FILE__,__LINE__,_("Invalid user in file \"%s\"\n"),redirector_sorted);
330b1c52
FM
497 exit(EXIT_FAILURE);
498 }
499 if (getword_atoll(&data2,&gwarea,'\t')<0) {
af961877 500 debuga(__FILE__,__LINE__,_("Invalid date in file \"%s\"\n"),redirector_sorted);
330b1c52
FM
501 exit(EXIT_FAILURE);
502 }
503 if (getword(hora,sizeof(hora),&gwarea,'\t')<0) {
af961877 504 debuga(__FILE__,__LINE__,_("Invalid time in file \"%s\"\n"),redirector_sorted);
330b1c52
FM
505 exit(EXIT_FAILURE);
506 }
507 if (getword(ip,sizeof(ip),&gwarea,'\t')<0) {
af961877 508 debuga(__FILE__,__LINE__,_("Invalid IP address in file \"%s\"\n"),redirector_sorted);
330b1c52
FM
509 exit(EXIT_FAILURE);
510 }
511 if (getword_ptr(buf,&url,&gwarea,'\t')<0) {
af961877 512 debuga(__FILE__,__LINE__,_("Invalid url in file \"%s\"\n"),redirector_sorted);
330b1c52
FM
513 exit(EXIT_FAILURE);
514 }
515 if (getword(rule,sizeof(rule),&gwarea,'\n')<0) {
af961877 516 debuga(__FILE__,__LINE__,_("Invalid rule in file \"%s\"\n"),redirector_sorted);
330b1c52
FM
517 exit(EXIT_FAILURE);
518 }
519
520 uinfo=userinfo_find_from_id(user);
521 if (!uinfo) {
af961877 522 debuga(__FILE__,__LINE__,_("Unknown user ID %s in file \"%s\"\n"),user,redirector_sorted);
330b1c52
FM
523 exit(EXIT_FAILURE);
524 }
525
526 computedate(data2/10000,(data2/100)%10,data2%100,&t);
527 strftime(data,sizeof(data),"%x",&t);
528
529 new_user=false;
530 if(!z) {
531 strcpy(ouser,user);
532 strcpy(oip,ip);
533 strcpy(oname,ip);
534 if (Ip2Name && !uinfo->id_is_ip) ip2name(oname,sizeof(oname));
535 z=true;
536 new_user=true;
537 } else {
538 if(strcmp(ouser,user) != 0) {
539 strcpy(ouser,user);
540 new_user=true;
541 }
542 if(strcmp(oip,ip) != 0) {
543 strcpy(oip,ip);
544 strcpy(oname,ip);
545 if (Ip2Name && !uinfo->id_is_ip) ip2name(oname,sizeof(oname));
546 new_user=true;
547 }
548 }
549
550 if(SquidGuardReportLimit) {
551 if(strcmp(ouser2,uinfo->label) == 0) {
552 count++;
553 } else {
7ae50eee
FM
554 if(count>SquidGuardReportLimit && SquidGuardReportLimit>0)
555 show_ignored_redirector(fp_ou,count-SquidGuardReportLimit);
330b1c52
FM
556 count=1;
557 strcpy(ouser2,uinfo->label);
558 }
7ae50eee 559 if(count > SquidGuardReportLimit)
330b1c52
FM
560 continue;
561 }
562
563 if (new_user)
564 fprintf(fp_ou,"<tr><td class=\"data2\">%s</td><td class=\"data2\">%s</td>",uinfo->label,ip);
565 else
566 fputs("<tr><td class=\"data2\"></td><td class=\"data2\"></td>",fp_ou);
567 fprintf(fp_ou,"<td class=\"data2\">%s-%s</td><td class=\"data2\">",data,hora);
6fa33a32 568 output_html_link(fp_ou,url,100);
330b1c52
FM
569 fprintf(fp_ou,"</td><td class=\"data2\">%s</td></tr>\n",rule);
570 }
800eafb8
FM
571 if (FileObject_Close(fp_in)) {
572 debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),redirector_sorted,FileObject_GetLastCloseError());
204781f4
FM
573 exit(EXIT_FAILURE);
574 }
330b1c52
FM
575 longline_destroy(&line);
576
7ae50eee
FM
577 if(count>SquidGuardReportLimit && SquidGuardReportLimit>0)
578 show_ignored_redirector(fp_ou,count-SquidGuardReportLimit);
579
bca2fdfd 580 fputs("</table>\n",fp_ou);
bd43d81f 581
bca2fdfd
FM
582 if (RedirectorErrors>0)
583 {
584 fputs("<div class=\"warn\"><span>",fp_ou);
585 fprintf(fp_ou,ngettext("%d error found in the log file. Some entries may be missing.","%d errors found in the log file. Some entries may be missing.",RedirectorErrors),RedirectorErrors);
586 fputs("</span></div>\n",fp_ou);
587 }
bd43d81f 588
bca2fdfd 589 fputs("</div>\n",fp_ou);
342bd723 590 write_html_trailer(fp_ou);
507460ae 591 if (fclose(fp_ou)==EOF) {
af961877 592 debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),report,strerror(errno));
507460ae
FM
593 exit(EXIT_FAILURE);
594 }
330b1c52 595
cf1a88b9 596 if (!KeepTempLog && unlink(redirector_sorted)) {
af961877 597 debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),redirector_sorted,strerror(errno));
330b1c52
FM
598 exit(EXIT_FAILURE);
599 }
600
601 return;
602}