]> git.ipfire.org Git - thirdparty/sarg.git/blame - redirector.c
Add support to decompress xz files
[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
02d231f3 315 getperiod_torange(&period,&dfrom,&duntil);
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) {
af961877 322 debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),SquidGuardConf,strerror(errno));
9bd92830
FM
323 exit(EXIT_FAILURE);
324 }
25697a35 325
9bd92830 326 if((fp_guard=fopen(SquidGuardConf,"r"))==NULL) {
af961877 327 debuga(__FILE__,__LINE__,_("Cannot open 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 }
204781f4 376 if (fclose(fp_guard)==EOF) {
af961877 377 debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),SquidGuardConf,strerror(errno));
204781f4
FM
378 exit(EXIT_FAILURE);
379 }
9bd92830 380 }
491b862f 381
507460ae 382 if (fp_ou && fclose(fp_ou)==EOF) {
af961877 383 debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),guard_in,strerror(errno));
507460ae
FM
384 exit(EXIT_FAILURE);
385 }
491b862f 386
9bd92830
FM
387 if (files_done) {
388 for (y=0; y<nfiles_done; y++)
389 if (files_done[y]) free(files_done[y]);
390 free(files_done);
391 }
c274f011 392
cf1a88b9
FM
393 if (redirector_count) {
394 snprintf(redirector_sorted,sizeof(redirector_sorted),"%s/redirector.int_log",tmp);
395 if(debug) {
af961877 396 debuga(__FILE__,__LINE__,_("Sorting file \"%s\"\n"),redirector_sorted);
cf1a88b9 397 }
25697a35 398
cf1a88b9 399 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 400 debuga(__FILE__,__LINE__,_("Sort command too long when sorting file \"%s\" to \"%s\"\n"),guard_in,redirector_sorted);
cf1a88b9
FM
401 exit(EXIT_FAILURE);
402 }
403 cstatus=system(tmp6);
404 if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
af961877
FM
405 debuga(__FILE__,__LINE__,_("sort command return status %d\n"),WEXITSTATUS(cstatus));
406 debuga(__FILE__,__LINE__,_("sort command: %s\n"),tmp6);
cf1a88b9
FM
407 exit(EXIT_FAILURE);
408 }
9bd92830 409 }
491b862f 410
11767c6a 411 if (!KeepTempLog && unlink(guard_in)) {
af961877 412 debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),guard_in,strerror(errno));
08f9b029
FM
413 exit(EXIT_FAILURE);
414 }
9bd92830 415 return;
25697a35 416}
330b1c52 417
7ae50eee
FM
418static void show_ignored_redirector(FILE *fp_ou,int count)
419{
420 char ignored[80];
421
422 snprintf(ignored,sizeof(ignored),ngettext("%d more redirector entry not shown here&hellip;","%d more redirector entries not shown here&hellip;",count),count);
423 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);
424}
425
330b1c52
FM
426void redirector_report(void)
427{
800eafb8
FM
428 FileObject *fp_in = NULL;
429 FILE *fp_ou = NULL;
330b1c52
FM
430
431 char *buf;
432 char *url;
330b1c52
FM
433 char report[MAXLEN];
434 char ip[45];
435 char rule[255];
436 char oip[45];
437 char user[MAXLEN];
438 char ouser[MAXLEN];
439 char data[15];
440 char hora[15];
441 char ouser2[255];
442 char oname[MAXLEN];
443 bool z=false;
444 int count=0;
445 long long int data2;
446 bool new_user;
447 struct getwordstruct gwarea;
448 const struct userinfostruct *uinfo;
449 struct tm t;
450 longline line;
451
452 ouser[0]='\0';
453 ouser2[0]='\0';
454
330b1c52 455 if(!redirector_count) {
cb59dc47 456 if (debugz>=LogLevel_Process) {
cf1a88b9 457 if (redirector_sorted[0])
af961877 458 debugaz(__FILE__,__LINE__,_("Redirector report not generated because it is empty\n"));
cf1a88b9 459 }
330b1c52
FM
460 return;
461 }
462
463 snprintf(report,sizeof(report),"%s/redirector.html",outdirname);
464
800eafb8
FM
465 if((fp_in=FileObject_Open(redirector_sorted))==NULL) {
466 debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),redirector_sorted,FileObject_GetLastOpenError());
330b1c52
FM
467 exit(EXIT_FAILURE);
468 }
469
470 if((fp_ou=fopen(report,"w"))==NULL) {
af961877 471 debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),report,strerror(errno));
330b1c52
FM
472 exit(EXIT_FAILURE);
473 }
474
475 if ((line=longline_create())==NULL) {
af961877 476 debuga(__FILE__,__LINE__,_("Not enough memory to read file \"%s\"\n"),redirector_sorted);
330b1c52
FM
477 exit(EXIT_FAILURE);
478 }
479
480 write_html_header(fp_ou,(IndexTree == INDEX_TREE_DATE) ? 3 : 1,_("Redirector report"),HTML_JS_NONE);
481 fputs("<tr><td class=\"header_c\">",fp_ou);
482 fprintf(fp_ou,_("Period: %s"),period.html);
483 fputs("</td></tr>\n",fp_ou);
484 fprintf(fp_ou,"<tr><th class=\"header_c\">%s</th></tr>\n",_("Redirector report"));
485 close_html_header(fp_ou);
486
487 fputs("<div class=\"report\"><table cellpadding=1 cellspacing=2>\n",fp_ou);
488 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"));
489
490 while((buf=longline_read(fp_in,line))!=NULL) {
491 getword_start(&gwarea,buf);
492 if (getword(user,sizeof(user),&gwarea,'\t')<0) {
af961877 493 debuga(__FILE__,__LINE__,_("Invalid user in file \"%s\"\n"),redirector_sorted);
330b1c52
FM
494 exit(EXIT_FAILURE);
495 }
496 if (getword_atoll(&data2,&gwarea,'\t')<0) {
af961877 497 debuga(__FILE__,__LINE__,_("Invalid date in file \"%s\"\n"),redirector_sorted);
330b1c52
FM
498 exit(EXIT_FAILURE);
499 }
500 if (getword(hora,sizeof(hora),&gwarea,'\t')<0) {
af961877 501 debuga(__FILE__,__LINE__,_("Invalid time in file \"%s\"\n"),redirector_sorted);
330b1c52
FM
502 exit(EXIT_FAILURE);
503 }
504 if (getword(ip,sizeof(ip),&gwarea,'\t')<0) {
af961877 505 debuga(__FILE__,__LINE__,_("Invalid IP address in file \"%s\"\n"),redirector_sorted);
330b1c52
FM
506 exit(EXIT_FAILURE);
507 }
508 if (getword_ptr(buf,&url,&gwarea,'\t')<0) {
af961877 509 debuga(__FILE__,__LINE__,_("Invalid url in file \"%s\"\n"),redirector_sorted);
330b1c52
FM
510 exit(EXIT_FAILURE);
511 }
512 if (getword(rule,sizeof(rule),&gwarea,'\n')<0) {
af961877 513 debuga(__FILE__,__LINE__,_("Invalid rule in file \"%s\"\n"),redirector_sorted);
330b1c52
FM
514 exit(EXIT_FAILURE);
515 }
516
517 uinfo=userinfo_find_from_id(user);
518 if (!uinfo) {
af961877 519 debuga(__FILE__,__LINE__,_("Unknown user ID %s in file \"%s\"\n"),user,redirector_sorted);
330b1c52
FM
520 exit(EXIT_FAILURE);
521 }
522
358e16ce 523 computedate(data2/10000,(data2/100)%100,data2%100,&t);
330b1c52
FM
524 strftime(data,sizeof(data),"%x",&t);
525
526 new_user=false;
527 if(!z) {
528 strcpy(ouser,user);
529 strcpy(oip,ip);
530 strcpy(oname,ip);
531 if (Ip2Name && !uinfo->id_is_ip) ip2name(oname,sizeof(oname));
532 z=true;
533 new_user=true;
534 } else {
535 if(strcmp(ouser,user) != 0) {
536 strcpy(ouser,user);
537 new_user=true;
538 }
539 if(strcmp(oip,ip) != 0) {
540 strcpy(oip,ip);
541 strcpy(oname,ip);
542 if (Ip2Name && !uinfo->id_is_ip) ip2name(oname,sizeof(oname));
543 new_user=true;
544 }
545 }
546
547 if(SquidGuardReportLimit) {
548 if(strcmp(ouser2,uinfo->label) == 0) {
549 count++;
550 } else {
7ae50eee
FM
551 if(count>SquidGuardReportLimit && SquidGuardReportLimit>0)
552 show_ignored_redirector(fp_ou,count-SquidGuardReportLimit);
330b1c52
FM
553 count=1;
554 strcpy(ouser2,uinfo->label);
555 }
7ae50eee 556 if(count > SquidGuardReportLimit)
330b1c52
FM
557 continue;
558 }
559
560 if (new_user)
561 fprintf(fp_ou,"<tr><td class=\"data2\">%s</td><td class=\"data2\">%s</td>",uinfo->label,ip);
562 else
563 fputs("<tr><td class=\"data2\"></td><td class=\"data2\"></td>",fp_ou);
564 fprintf(fp_ou,"<td class=\"data2\">%s-%s</td><td class=\"data2\">",data,hora);
6fa33a32 565 output_html_link(fp_ou,url,100);
330b1c52
FM
566 fprintf(fp_ou,"</td><td class=\"data2\">%s</td></tr>\n",rule);
567 }
800eafb8
FM
568 if (FileObject_Close(fp_in)) {
569 debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),redirector_sorted,FileObject_GetLastCloseError());
204781f4
FM
570 exit(EXIT_FAILURE);
571 }
330b1c52
FM
572 longline_destroy(&line);
573
7ae50eee
FM
574 if(count>SquidGuardReportLimit && SquidGuardReportLimit>0)
575 show_ignored_redirector(fp_ou,count-SquidGuardReportLimit);
576
bca2fdfd 577 fputs("</table>\n",fp_ou);
bd43d81f 578
bca2fdfd
FM
579 if (RedirectorErrors>0)
580 {
581 fputs("<div class=\"warn\"><span>",fp_ou);
582 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);
583 fputs("</span></div>\n",fp_ou);
584 }
bd43d81f 585
bca2fdfd 586 fputs("</div>\n",fp_ou);
342bd723 587 write_html_trailer(fp_ou);
507460ae 588 if (fclose(fp_ou)==EOF) {
af961877 589 debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),report,strerror(errno));
507460ae
FM
590 exit(EXIT_FAILURE);
591 }
330b1c52 592
cf1a88b9 593 if (!KeepTempLog && unlink(redirector_sorted)) {
af961877 594 debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),redirector_sorted,strerror(errno));
330b1c52
FM
595 exit(EXIT_FAILURE);
596 }
597
598 return;
599}