]> git.ipfire.org Git - thirdparty/sarg.git/blame - redirector.c
Update the build date and version number
[thirdparty/sarg.git] / redirector.c
CommitLineData
25697a35 1/*
94ff9470 2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
67302a9e 3 * 1998, 2013
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) {
61 debuga(_("Invalid \"redirector_log_format\" option in your sarg.conf (too many characters before first tag)\n"));
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) {
75 debuga(_("Invalid \"redirector_log_format\" option in your sarg.conf (missing # at end of tag)\n"));
76 exit(EXIT_FAILURE);
77 }
78 if (getword(sep,sizeof(sep),&gwarea1,'#')<0) {
79 debuga(_("Invalid \"redirector_log_format\" option in your sarg.conf (too many characters in column separator)\n"));
80 exit(EXIT_FAILURE);
81 }
82 if(strcmp(leks,"end") != 0) {
83 if (getword_limit(res,sizeof(res),&gwarea,sep[0])<0) {
84 debuga(_("Parsing of tag \"%s\" in redirector log %s returned no result\n"),leks,wentp);
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)) {
96 debuga(_("Hour string too long in redirector log file %s\n"),wentp);
97 RedirectorErrors++;
98 return;
99 }
100 strcpy(hour,res);
101 } else if(strcmp(leks,"source") == 0) {
102 if (strlen(res)>=sizeof(source)) {
103 debuga(_("Banning source name too long in redirector log file %s\n"),wentp);
104 RedirectorErrors++;
105 return;
106 }
107 strcpy(source,res);
108 } else if(strcmp(leks,"list") == 0) {
109 if (strlen(res)>=sizeof(list)) {
110 debuga(_("Banning list name too long in redirector log file %s\n"),wentp);
111 RedirectorErrors++;
112 return;
113 }
114 strcpy(list,res);
115 } else if(strcmp(leks,"ip") == 0) {
116 if (strlen(res)>=sizeof(ip)) {
117 debuga(_("IP address too long in redirector log file %s\n"),wentp);
118 RedirectorErrors++;
119 return;
120 }
121 strcpy(ip,res);
122 } else if(strcmp(leks,"user") == 0) {
123 if (strlen(res)>=sizeof(user)) {
124 debuga(_("User ID too long in redirector log file %s\n"),wentp);
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) {
141 debuga(_("Invalid date found in file %s\n"),wentp);
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) {
149 debuga(_("Invalid time found in file %s\n"),wentp);
150 RedirectorErrors++;
151 return;
152 }
153 if (getword_skip(MAXLEN,&gwarea,'(')<0 || getword(source,sizeof(source),&gwarea,'/')<0) {
154 debuga(_("Invalid redirected source in file %s\n"),wentp);
155 RedirectorErrors++;
156 return;
157 }
158 if (getword(list,sizeof(list),&gwarea,'/')<0) {
159 debuga(_("Invalid redirected list in file %s\n"),wentp);
160 RedirectorErrors++;
161 return;
162 }
163 if (getword_skip(MAXLEN,&gwarea,' ')<0 || getword_limit(full_url,sizeof(full_url),&gwarea,' ')<0) {
164 debuga(_("Invalid URL in file %s\n"),wentp);
165 RedirectorErrors++;
166 return;
167 }
168 if (getword(ip,sizeof(ip),&gwarea,'/')<0) {
169 debuga(_("Invalid source IP in file %s\n"),wentp);
170 RedirectorErrors++;
171 return;
172 }
173 if (getword_skip(MAXLEN,&gwarea,' ')<0 || getword(user,sizeof(user),&gwarea,' ')<0) {
174 debuga(_("Invalid user in file %s\n"),wentp);
175 RedirectorErrors++;
176 return;
177 }
178 }
179 url=process_url(full_url,false);
180
181 //sprintf(warea,"%04d%02d%02d",year,mon,day);
182
183 if(RedirectorFilterOutDate) {
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{
225 FILE *fp_in = NULL;
226 char *buf;
227 int i;
9bd92830 228 longline line;
491b862f 229
9bd92830
FM
230 if(debug) {
231 debuga(_("Reading redirector log file %s\n"),wentp);
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) {
258 debuga(_("Not enough memory to store the name of the new redirector log to be read - %s\n"),strerror(errno));
259 exit(EXIT_FAILURE);
260 }
261 files_done[nfiles_done-1] = strdup(wentp);
262 if (!files_done[nfiles_done-1]) {
263 debuga(_("Not enough memory to store the name of the new redirector log to be read - %s\n"),strerror(errno));
264 exit(EXIT_FAILURE);
265 }
d6e703cc 266
9bd92830 267 if ((fp_in=fopen(wentp,"r"))==NULL) {
d6f0349d 268 debuga(_("(squidguard) Cannot open log file %s: %s\n"),wentp,strerror(errno));
9bd92830
FM
269 exit(EXIT_FAILURE);
270 }
06e3cc62 271
9bd92830
FM
272 if ((line=longline_create())==NULL) {
273 debuga(_("Not enough memory to read the redirector log\n"));
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
FM
279 }
280 fclose(fp_in);
281 longline_destroy(&line);
282 return;
491b862f
GS
283}
284
285
330b1c52 286void redirector_log(void)
25697a35 287{
9bd92830
FM
288 FILE *fp_ou = NULL, *fp_guard = NULL;
289 char buf[MAXLEN];
290 char guard_in[MAXLEN];
9bd92830
FM
291 char logdir[MAXLEN];
292 char user[MAXLEN];
293 char tmp6[MAXLEN];
294 int i;
295 int y;
296 int cstatus;
297 int dfrom, duntil;
298 char *str;
299 char *str2;
25697a35 300
9bd92830 301 str2 = user;
d6e703cc 302
9f93fec3 303 if(SquidGuardConf[0] == '\0' && NRedirectorLogs == 0) {
cb59dc47 304 if (debugz>=LogLevel_Process) debugaz(_("No redirector logs provided to produce that kind of report\n"));
007905af 305 return;
9f93fec3 306 }
25697a35 307
c98d6a0f 308 snprintf(guard_in,sizeof(guard_in),"%s/redirector.int_unsort",tmp);
cf1a88b9 309 if((fp_ou=fopen(guard_in,"w"))==NULL) {
d6f0349d 310 debuga(_("(squidguard) Cannot open log file %s: %s\n"),guard_in,strerror(errno));
9bd92830
FM
311 exit(EXIT_FAILURE);
312 }
25697a35 313
9bd92830
FM
314 dfrom=(period.start.tm_year+1900)*10000+(period.start.tm_mon+1)*100+period.start.tm_mday;
315 duntil=(period.end.tm_year+1900)*10000+(period.end.tm_mon+1)*100+period.end.tm_mday;
25697a35 316
9bd92830
FM
317 if (NRedirectorLogs>0) {
318 for (i=0 ; i<NRedirectorLogs ; i++)
319 read_log(RedirectorLogs[i],fp_ou,dfrom,duntil);
320 } else {
321 if(access(SquidGuardConf, R_OK) != 0) {
322 debuga(_("Cannot open squidGuard config file: %s\n"),SquidGuardConf);
323 exit(EXIT_FAILURE);
324 }
25697a35 325
9bd92830 326 if((fp_guard=fopen(SquidGuardConf,"r"))==NULL) {
d6f0349d 327 debuga(_("(squidguard) Cannot open log file %s: %s\n"),SquidGuardConf,strerror(errno));
9bd92830
FM
328 exit(EXIT_FAILURE);
329 }
5f3cfd1d 330
9bd92830
FM
331 logdir[0]=0;
332 while(fgets(buf,sizeof(buf),fp_guard)!=NULL) {
333 fixendofline(buf);
334 if((str=get_param_value("logdir",buf))!=NULL) {
335 /*
336 We want to tolerate spaces inside the directory name but we must also
337 remove the trailing spaces left by the editor after the directory name.
338 This should not be a problem as nobody use a file name with trailing spaces.
339 */
340 for (y=strlen(str)-1 ; y>=0 && (unsigned char)str[y]<=' ' ; y--);
341 if (y>=sizeof(logdir)-1) y=sizeof(logdir)-2;
342 logdir[y+1] = '\0';
343 while (y>=0) {
344 logdir[y] = str[y];
345 y--;
346 }
347 } else if((str=get_param_value("log",buf))!=NULL) {
348 if((str2=get_param_value("anonymous",str))!=NULL)
349 str=str2;
d6e703cc 350
9bd92830
FM
351 /*
352 If logdir is defined, we prepend it to the log file name, otherwise, we assume
353 the log directive provides an absolute file name to the log file. Therefore,
354 we don't need to add an additionnal / at the beginning of the log file name.
355 */
356 y=(logdir[0]) ? sprintf(wentp,"%s/",logdir) : 0;
357 /*
358 Spaces are allowed in the name of the log file. The file name ends at the first #
359 because it is assumed it is an end of line comment. Any space before the # is then
360 removed. Any control character (i.e. a character with a code lower than 32) ends
361 the file name. That includes the terminating zero.
362 */
363 while((unsigned char)*str>=' ' && *str!='#' && y<sizeof(wentp)-1)
364 wentp[y++]=*str++;
365 if(*str=='#') {
366 str--;
367 while(*str==' ' && y>0) {
368 str--;
369 y--;
370 }
371 }
372 wentp[y]=0;
373 read_log(wentp,fp_ou,dfrom,duntil);
374 }
375 }
376 }
491b862f 377
9bd92830 378 if (fp_guard) fclose(fp_guard);
507460ae
FM
379 if (fp_ou && fclose(fp_ou)==EOF) {
380 debuga(_("Write error in %s: %s\n"),guard_in,strerror(errno));
381 exit(EXIT_FAILURE);
382 }
491b862f 383
9bd92830
FM
384 if (files_done) {
385 for (y=0; y<nfiles_done; y++)
386 if (files_done[y]) free(files_done[y]);
387 free(files_done);
388 }
c274f011 389
cf1a88b9
FM
390 if (redirector_count) {
391 snprintf(redirector_sorted,sizeof(redirector_sorted),"%s/redirector.int_log",tmp);
392 if(debug) {
393 debuga(_("Sorting file: %s\n"),redirector_sorted);
394 }
25697a35 395
cf1a88b9
FM
396 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)) {
397 debuga(_("Sort command too long when sorting file \"%s\" to \"%s\"\n"),guard_in,redirector_sorted);
398 exit(EXIT_FAILURE);
399 }
400 cstatus=system(tmp6);
401 if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
402 debuga(_("sort command return status %d\n"),WEXITSTATUS(cstatus));
403 debuga(_("sort command: %s\n"),tmp6);
404 exit(EXIT_FAILURE);
405 }
9bd92830 406 }
491b862f 407
11767c6a
FM
408 if (!KeepTempLog && unlink(guard_in)) {
409 debuga(_("Cannot delete \"%s\": %s\n"),guard_in,strerror(errno));
08f9b029
FM
410 exit(EXIT_FAILURE);
411 }
9bd92830 412 return;
25697a35 413}
330b1c52 414
7ae50eee
FM
415static void show_ignored_redirector(FILE *fp_ou,int count)
416{
417 char ignored[80];
418
419 snprintf(ignored,sizeof(ignored),ngettext("%d more redirector entry not shown here&hellip;","%d more redirector entries not shown here&hellip;",count),count);
420 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);
421}
422
330b1c52
FM
423void redirector_report(void)
424{
425 FILE *fp_in = NULL, *fp_ou = NULL;
426
427 char *buf;
428 char *url;
330b1c52
FM
429 char report[MAXLEN];
430 char ip[45];
431 char rule[255];
432 char oip[45];
433 char user[MAXLEN];
434 char ouser[MAXLEN];
435 char data[15];
436 char hora[15];
437 char ouser2[255];
438 char oname[MAXLEN];
439 bool z=false;
440 int count=0;
441 long long int data2;
442 bool new_user;
443 struct getwordstruct gwarea;
444 const struct userinfostruct *uinfo;
445 struct tm t;
446 longline line;
447
448 ouser[0]='\0';
449 ouser2[0]='\0';
450
330b1c52 451 if(!redirector_count) {
cb59dc47 452 if (debugz>=LogLevel_Process) {
cf1a88b9
FM
453 if (redirector_sorted[0])
454 debugaz(_("Redirector report not generated because it is empty\n"));
455 }
330b1c52
FM
456 return;
457 }
458
459 snprintf(report,sizeof(report),"%s/redirector.html",outdirname);
460
cf1a88b9 461 if((fp_in=fopen(redirector_sorted,"r"))==NULL) {
d6f0349d 462 debuga(_("(squidguard) Cannot open log file %s: %s\n"),redirector_sorted,strerror(errno));
330b1c52
FM
463 exit(EXIT_FAILURE);
464 }
465
466 if((fp_ou=fopen(report,"w"))==NULL) {
d6f0349d 467 debuga(_("(squidguard) Cannot open log file %s: %s\n"),report,strerror(errno));
330b1c52
FM
468 exit(EXIT_FAILURE);
469 }
470
471 if ((line=longline_create())==NULL) {
472 debuga(_("Not enough memory to read the processed redirector log\n"));
473 exit(EXIT_FAILURE);
474 }
475
476 write_html_header(fp_ou,(IndexTree == INDEX_TREE_DATE) ? 3 : 1,_("Redirector report"),HTML_JS_NONE);
477 fputs("<tr><td class=\"header_c\">",fp_ou);
478 fprintf(fp_ou,_("Period: %s"),period.html);
479 fputs("</td></tr>\n",fp_ou);
480 fprintf(fp_ou,"<tr><th class=\"header_c\">%s</th></tr>\n",_("Redirector report"));
481 close_html_header(fp_ou);
482
483 fputs("<div class=\"report\"><table cellpadding=1 cellspacing=2>\n",fp_ou);
484 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"));
485
486 while((buf=longline_read(fp_in,line))!=NULL) {
487 getword_start(&gwarea,buf);
488 if (getword(user,sizeof(user),&gwarea,'\t')<0) {
cf1a88b9 489 debuga(_("Invalid user in file %s\n"),redirector_sorted);
330b1c52
FM
490 exit(EXIT_FAILURE);
491 }
492 if (getword_atoll(&data2,&gwarea,'\t')<0) {
cf1a88b9 493 debuga(_("Invalid date in file %s\n"),redirector_sorted);
330b1c52
FM
494 exit(EXIT_FAILURE);
495 }
496 if (getword(hora,sizeof(hora),&gwarea,'\t')<0) {
cf1a88b9 497 debuga(_("Invalid time in file %s\n"),redirector_sorted);
330b1c52
FM
498 exit(EXIT_FAILURE);
499 }
500 if (getword(ip,sizeof(ip),&gwarea,'\t')<0) {
cf1a88b9 501 debuga(_("Invalid IP address in file %s\n"),redirector_sorted);
330b1c52
FM
502 exit(EXIT_FAILURE);
503 }
504 if (getword_ptr(buf,&url,&gwarea,'\t')<0) {
cf1a88b9 505 debuga(_("Invalid URL in file %s\n"),redirector_sorted);
330b1c52
FM
506 exit(EXIT_FAILURE);
507 }
508 if (getword(rule,sizeof(rule),&gwarea,'\n')<0) {
cf1a88b9 509 debuga(_("Invalid rule in file %s\n"),redirector_sorted);
330b1c52
FM
510 exit(EXIT_FAILURE);
511 }
512
513 uinfo=userinfo_find_from_id(user);
514 if (!uinfo) {
cf1a88b9 515 debuga(_("Unknown user ID %s in file %s\n"),user,redirector_sorted);
330b1c52
FM
516 exit(EXIT_FAILURE);
517 }
518
519 computedate(data2/10000,(data2/100)%10,data2%100,&t);
520 strftime(data,sizeof(data),"%x",&t);
521
522 new_user=false;
523 if(!z) {
524 strcpy(ouser,user);
525 strcpy(oip,ip);
526 strcpy(oname,ip);
527 if (Ip2Name && !uinfo->id_is_ip) ip2name(oname,sizeof(oname));
528 z=true;
529 new_user=true;
530 } else {
531 if(strcmp(ouser,user) != 0) {
532 strcpy(ouser,user);
533 new_user=true;
534 }
535 if(strcmp(oip,ip) != 0) {
536 strcpy(oip,ip);
537 strcpy(oname,ip);
538 if (Ip2Name && !uinfo->id_is_ip) ip2name(oname,sizeof(oname));
539 new_user=true;
540 }
541 }
542
543 if(SquidGuardReportLimit) {
544 if(strcmp(ouser2,uinfo->label) == 0) {
545 count++;
546 } else {
7ae50eee
FM
547 if(count>SquidGuardReportLimit && SquidGuardReportLimit>0)
548 show_ignored_redirector(fp_ou,count-SquidGuardReportLimit);
330b1c52
FM
549 count=1;
550 strcpy(ouser2,uinfo->label);
551 }
7ae50eee 552 if(count > SquidGuardReportLimit)
330b1c52
FM
553 continue;
554 }
555
556 if (new_user)
557 fprintf(fp_ou,"<tr><td class=\"data2\">%s</td><td class=\"data2\">%s</td>",uinfo->label,ip);
558 else
559 fputs("<tr><td class=\"data2\"></td><td class=\"data2\"></td>",fp_ou);
560 fprintf(fp_ou,"<td class=\"data2\">%s-%s</td><td class=\"data2\">",data,hora);
6fa33a32 561 output_html_link(fp_ou,url,100);
330b1c52
FM
562 fprintf(fp_ou,"</td><td class=\"data2\">%s</td></tr>\n",rule);
563 }
564 fclose(fp_in);
565 longline_destroy(&line);
566
7ae50eee
FM
567 if(count>SquidGuardReportLimit && SquidGuardReportLimit>0)
568 show_ignored_redirector(fp_ou,count-SquidGuardReportLimit);
569
bca2fdfd 570 fputs("</table>\n",fp_ou);
bd43d81f 571
bca2fdfd
FM
572 if (RedirectorErrors>0)
573 {
574 fputs("<div class=\"warn\"><span>",fp_ou);
575 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);
576 fputs("</span></div>\n",fp_ou);
577 }
bd43d81f 578
bca2fdfd 579 fputs("</div>\n",fp_ou);
330b1c52
FM
580 if (write_html_trailer(fp_ou)<0)
581 debuga(_("Write error in file %s\n"),report);
507460ae
FM
582 if (fclose(fp_ou)==EOF) {
583 debuga(_("Write error in %s: %s\n"),report,strerror(errno));
584 exit(EXIT_FAILURE);
585 }
330b1c52 586
cf1a88b9
FM
587 if (!KeepTempLog && unlink(redirector_sorted)) {
588 debuga(_("Cannot delete \"%s\": %s\n"),redirector_sorted,strerror(errno));
330b1c52
FM
589 exit(EXIT_FAILURE);
590 }
591
592 return;
593}