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