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