sarg  2.4.0
About: SARG ia a Squid Analysis Report Generator.
  Fossies Dox: sarg-2.4.0.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

index.c
Go to the documentation of this file.
1 /*
2  * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
3  * 1998, 2015
4  *
5  * SARG donations:
6  * please look at http://sarg.sourceforge.net/donations.php
7  * Support:
8  * http://sourceforge.net/projects/sarg/forums/forum/363374
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"
28 #include "include/defs.h"
29 
30 #ifdef HAVE_LSTAT
31 #define MY_LSTAT lstat
32 #else
33 #define MY_LSTAT stat
34 #endif
35 
36 
37 static void make_date_index(void);
38 static void make_file_index(void);
39 static void file_index_to_date_index(const char *entry);
40 static void date_index_to_file_index(const char *entry);
41 
42 void make_index(void)
43 {
44  DIR *dirp;
45  struct dirent *direntp;
46  char wdir[MAXLEN];
47 
48  if (LastLog > 0) mklastlog(outdir);
49 
50  if (Index == INDEX_NO) {
51  if (snprintf(wdir,sizeof(wdir),"%s"INDEX_HTML_FILE,outdir)>=sizeof(wdir)) {
52  debuga(__FILE__,__LINE__,_("Path too long: "));
54  exit(EXIT_FAILURE);
55  }
56  if (access(wdir, R_OK) == 0) {
57  if (unlink(wdir)) {
58  debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),wdir,strerror(errno));
59  exit(EXIT_FAILURE);
60  }
61  }
62  return;
63  }
64 
65  if (debug) {
66  // TRANSLATORS: The %s is the name of the html index file (index.html).
67  debuga(__FILE__,__LINE__,_("Making %s\n"),INDEX_HTML_FILE);
68  }
69 
70  // convert any old report hierarchy
71  if ((dirp = opendir(outdir)) == NULL) {
72  debuga(__FILE__,__LINE__,_("Cannot open directory \"%s\": %s\n"),outdir,strerror(errno));
73  exit(EXIT_FAILURE);
74  }
75  while ((direntp = readdir( dirp )) != NULL) {
76  if (isdigit(direntp->d_name[0]) && isdigit(direntp->d_name[1])) {
78  file_index_to_date_index(direntp->d_name);
79  else
80  date_index_to_file_index(direntp->d_name);
81  }
82  }
83  closedir(dirp);
84 
85  if (IndexTree == INDEX_TREE_DATE) {
87  } else {
89  }
90 }
91 
112 static long long int get_file_size(struct stat *statb)
113 {
114 #ifdef __linux__
115  long long int blocks;
116 
117  //return(statb->st_size);//the size of the file content
118  //return(statb->st_blocks*512);//what is the purpose of this size?
119  if (statb->st_blksize==0) return(statb->st_size);
120  blocks=(statb->st_size+statb->st_blksize-1)/statb->st_blksize;
121  return(blocks*statb->st_blksize);//how many bytes occupied on disk
122 #else
123  return(statb->st_size);
124 #endif
125 }
126 
141 static long long int get_size(char *path,int path_size)
142 {
143  int path_len;
144  DIR *dirp;
145  struct dirent *direntp;
146  struct stat statb;
147  int name_len;
148  long long int total_size=0;
149  char *dir_list=NULL;
150  int dir_filled=0;
151  int dir_allocated=0;
152 
153  path_len=strlen(path);
154  if (path_len+2>=path_size) {
155  debuga(__FILE__,__LINE__,_("Path too long: "));
156  debuga_more("%s\n",path);
157  exit(EXIT_FAILURE);
158  }
159  if ((dirp=opendir(path))==NULL) {
160  debuga(__FILE__,__LINE__,_("Cannot open directory \"%s\": %s\n"),path,strerror(errno));
161  exit(EXIT_FAILURE);
162  }
163  path[path_len++]='/';
164  while ((direntp=readdir(dirp))!=NULL) {
165  if (direntp->d_name[0]=='.' && (direntp->d_name[1]=='\0' || (direntp->d_name[1]=='.' && direntp->d_name[2]=='\0'))) continue;
166  name_len=strlen(direntp->d_name);
167  if (path_len+name_len+1>=path_size) {
168  debuga(__FILE__,__LINE__,_("Path too long: "));
169  debuga_more("%s%s\n",path,direntp->d_name);
170  exit(EXIT_FAILURE);
171  }
172  strcpy(path+path_len,direntp->d_name);
173  if (MY_LSTAT(path,&statb) == -1) {
174  debuga(__FILE__,__LINE__,_("Failed to get the statistics of file \"%s\": %s\n"),path,strerror(errno));
175  continue;
176  }
177  if (S_ISDIR(statb.st_mode))
178  {
179  if (!dir_list || dir_filled+name_len>=dir_allocated)
180  {
181  int size=3*(name_len+1);//make room for three file names like this one
182  if (size<256) size=256;
183  dir_allocated+=size;
184  dir_list=realloc(dir_list,dir_allocated);
185  if (!dir_list) {
186  debuga(__FILE__,__LINE__,_("Not enough memory to recurse into subdirectory \"%s\"\n"),path);
187  exit(EXIT_FAILURE);
188  }
189  }
190  strcpy(dir_list+dir_filled,direntp->d_name);
191  dir_filled+=name_len+1;
192  total_size+=get_file_size(&statb);
193  }
194  else if (S_ISREG(statb.st_mode))
195  {
196  total_size+=get_file_size(&statb);
197  }
198  }
199  closedir(dirp);
200 
201  if (dir_list)
202  {
203  int start=0;
204 
205  while (start<dir_filled)
206  {
207  name_len=strlen(dir_list+start);
208  strcpy(path+path_len,dir_list+start);
209  total_size+=get_size(path,path_size);
210  start+=name_len+1;
211  }
212  free(dir_list);
213  }
214 
215  path[path_len-1]='\0';//restore original string
216  return (total_size);
217 }
218 
233 static long long int make_date_index_day(char *monthdir,int monthdir_size,int order,const char *yearnum,const char *monthnum)
234 {
235  int monthdir_len;
236  int ndays;
237  DIR *dirp3;
238  struct dirent *direntp;
239  struct stat statb;
240  int i;
241  int daysort[31*31];
242  int d1, d2, day;
243  FILE *fp_ou;
244  char title[80];
245  char daynum[10];
246  int d;
247  long long int total_size=0;
248  long long int sub_size;
249  int name_len;
250 
251  ndays=0;
252  if ((dirp3 = opendir(monthdir)) == NULL) {
253  debuga(__FILE__,__LINE__,_("Cannot open directory \"%s\": %s\n"),monthdir,strerror(errno));
254  exit(EXIT_FAILURE);
255  }
256  monthdir_len=strlen(monthdir);
257  if (monthdir_len+strlen(INDEX_HTML_FILE)+2>=monthdir_size) {
258  debuga(__FILE__,__LINE__,_("Path too long: "));
259  debuga_more("%s/%s\n",monthdir,INDEX_HTML_FILE);
260  exit(EXIT_FAILURE);
261  }
262  monthdir[monthdir_len++]='/';
263  while ((direntp = readdir( dirp3 )) != NULL) {
264  if (direntp->d_name[0]=='.' && (direntp->d_name[1]=='\0' || (direntp->d_name[1]=='.' && direntp->d_name[2]=='\0'))) continue;
265  name_len=strlen(direntp->d_name);
266  if (monthdir_len+name_len+1>=monthdir_size) {
267  debuga(__FILE__,__LINE__,_("Path too long: "));
268  debuga_more("%s%s\n",monthdir,direntp->d_name);
269  exit(EXIT_FAILURE);
270  }
271  strcpy(monthdir+monthdir_len,direntp->d_name);
272  if (MY_LSTAT(monthdir,&statb) == -1) {
273  debuga(__FILE__,__LINE__,_("Failed to get the statistics of file \"%s\": %s\n"),monthdir,strerror(errno));
274  continue;
275  }
276  if (S_ISDIR(statb.st_mode))
277  {
278  if (!isdigit(direntp->d_name[0]) && !isdigit(direntp->d_name[1])) continue;
279  i=-1;
280  if (sscanf(direntp->d_name,"%d%n",&d1,&i)!=1 || d1<1 || d1>31 || i<0) continue;
281  if (direntp->d_name[i]=='-') {
282  if (sscanf(direntp->d_name+i+1,"%d",&d2)!=1 || d2<1 || d2>31) continue;
283  } else if (direntp->d_name[i]!='\0') {
284  continue;
285  } else {
286  d2=0;
287  }
288  if (ndays>=sizeof(daysort)/sizeof(daysort[0])) {
289  debuga(__FILE__,__LINE__,_("Too many day directories in %s\nSupernumerary entries are ignored\n"),monthdir);
290  break;
291  }
292  day=(d1 << 5) | d2;
293  for (i=ndays ; i>0 && day<daysort[i-1] ; i--) {
294  daysort[i]=daysort[i-1];
295  }
296  daysort[i]=day;
297  ndays++;
298  total_size+=get_file_size(&statb);
299  }
300  else if (S_ISREG(statb.st_mode))
301  {
302  total_size+=get_file_size(&statb);
303  }
304  }
305  closedir(dirp3);
306 
307  strcpy(monthdir+monthdir_len,INDEX_HTML_FILE);
308  if ((fp_ou=fopen(monthdir,"w"))==NULL) {
309  debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),monthdir,strerror(errno));
310  exit(EXIT_FAILURE);
311  }
312  snprintf(title,sizeof(title),ngettext("SARG: report for %s/%s","SARG: reports for %s/%s",ndays),yearnum,monthnum);
313  write_html_header(fp_ou,2,title,HTML_JS_NONE);
314  close_html_header(fp_ou);
315  fputs("<div class=\"index\"><table cellpadding=\"1\" cellspacing=\"2\">\n<tr><td></td><td></td></tr>\n",fp_ou);
316  fprintf(fp_ou,"<tr><th class=\"header_l\">%s/%s/%s</th>",_("YEAR"),_("MONTH"),_("DAYS"));
318  fprintf(fp_ou,"<th class=\"header_l\">%s</th>",_("SIZE"));
319  fputs("</tr>\n",fp_ou);
320  for (d=0 ; d<ndays ; d++) {
321  if (order>0)
322  day=daysort[d];
323  else
324  day=daysort[ndays-1-d];
325  d1=(day >> 5) & 0x1F;
326  if ((day & 0x1F) != 0) {
327  d2=day & 0x1F;
328  snprintf(daynum,sizeof(daynum),"%02d-%02d",d1,d2);
329  } else {
330  snprintf(daynum,sizeof(daynum),"%02d",d1);
331  }
332  strcpy(monthdir+monthdir_len,daynum);
333  sub_size=get_size(monthdir,monthdir_size);
334 
335  fprintf(fp_ou,"<tr><td class=\"data2\"><a href=\"%s/%s\">%s %s %s</a></td>",daynum,INDEX_HTML_FILE,yearnum,monthnum,daynum);
337  {
338  char size_str[40];
339 
340  strncpy(size_str,fixnum(sub_size,1),sizeof(size_str)-1);
341  size_str[sizeof(size_str)-1]='\0';
342  fprintf(fp_ou,"<td class=\"data2\">%s</td>",size_str);
343  }
344  fputs("</tr>\n",fp_ou);
345  total_size+=sub_size;
346  }
347  fputs("</table></div>\n",fp_ou);
348  monthdir[monthdir_len-1]='\0';
349  write_html_trailer(fp_ou);
350  if (fclose(fp_ou)==EOF) {
351  strcpy(monthdir+monthdir_len,INDEX_HTML_FILE);
352  debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),monthdir,strerror(errno));
353  exit(EXIT_FAILURE);
354  }
355  return(total_size);
356 }
357 
365 static void name_month(int month,char *month_name,int month_size)
366 {
367  const char *m[12]={N_("January"),N_("February"),N_("March"),N_("April"),N_("May"),N_("June"),N_("July"),
368  N_("August"),N_("September"),N_("October"),N_("November"),N_("December")};
369 
370  if (month<1 || month>12) {
371  debuga(__FILE__,__LINE__,_("The internal list of month names is invalid. Please report this bug to the translator.\n"));
372  exit(EXIT_FAILURE);
373  }
374  strncpy(month_name,_(m[month-1]),month_size-1);
375  month_name[month_size-1]='\0';
376 }
377 
391 static long long int make_date_index_month(char *yeardir,int yeardir_size,int order,const char *yearnum)
392 {
393  int yeardir_len;
394  int nmonths;
395  DIR *dirp2;
396  struct dirent *direntp;
397  struct stat statb;
398  int i;
399  int monthsort[144];
400  int m1, m2, month;
401  FILE *fp_ou;
402  char title[80];
403  char monthname1[9], monthname2[9];
404  char nmonth[30];
405  char monthnum[10];
406  int m;
407  long long int total_size=0;
408  long long int sub_size;
409  int name_len;
410 
411  nmonths=0;
412  if ((dirp2 = opendir(yeardir)) == NULL) {
413  debuga(__FILE__,__LINE__,_("Cannot open directory \"%s\": %s\n"),yeardir,strerror(errno));
414  exit(EXIT_FAILURE);
415  }
416  yeardir_len=strlen(yeardir);
417  if (yeardir_len+strlen(INDEX_HTML_FILE)+2>=yeardir_size) {
418  debuga(__FILE__,__LINE__,_("Path too long: "));
419  debuga_more("%s/%s\n",yeardir,INDEX_HTML_FILE);
420  exit(EXIT_FAILURE);
421  }
422  yeardir[yeardir_len++]='/';
423  while ((direntp = readdir( dirp2 )) != NULL) {
424  if (direntp->d_name[0]=='.' && (direntp->d_name[1]=='\0' || (direntp->d_name[1]=='.' && direntp->d_name[2]=='\0'))) continue;
425  name_len=strlen(direntp->d_name);
426  if (yeardir_len+name_len+1>=yeardir_size) {
427  debuga(__FILE__,__LINE__,_("Path too long: "));
428  debuga_more("%s%s\n",yeardir,direntp->d_name);
429  exit(EXIT_FAILURE);
430  }
431  strcpy(yeardir+yeardir_len,direntp->d_name);
432  if (MY_LSTAT(yeardir,&statb) == -1) {
433  debuga(__FILE__,__LINE__,_("Failed to get the statistics of file \"%s\": %s\n"),yeardir,strerror(errno));
434  continue;
435  }
436  if (S_ISDIR(statb.st_mode))
437  {
438  if (!isdigit(direntp->d_name[0]) || !isdigit(direntp->d_name[1])) continue;
439  i=-1;
440  if (sscanf(direntp->d_name,"%d%n",&m1,&i)!=1 || m1<1 || m1>12 || i<0) continue;
441  if (direntp->d_name[i]=='-') {
442  if (sscanf(direntp->d_name+i+1,"%d",&m2)!=1 || m2<1 || m2>12) continue;
443  } else if (direntp->d_name[i]!='\0') {
444  continue;
445  } else {
446  m2=0;
447  }
448  if (nmonths>=sizeof(monthsort)/sizeof(monthsort[0])) {
449  debuga(__FILE__,__LINE__,_("Too many month directories in %s\nSupernumerary entries are ignored\n"),yeardir);
450  break;
451  }
452  month=(m1<<4) | m2;
453  for (i=nmonths ; i>0 && month<monthsort[i-1] ; i--) {
454  monthsort[i]=monthsort[i-1];
455  }
456  monthsort[i]=month;
457  nmonths++;
458  total_size+=get_file_size(&statb);
459  }
460  else if (S_ISREG(statb.st_mode))
461  {
462  total_size+=get_file_size(&statb);
463  }
464  }
465  closedir(dirp2);
466 
467  strcpy(yeardir+yeardir_len,INDEX_HTML_FILE);
468  if ((fp_ou=fopen(yeardir,"w"))==NULL) {
469  debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),yeardir,strerror(errno));
470  exit(EXIT_FAILURE);
471  }
472  snprintf(title,sizeof(title),ngettext("SARG: report for %s","SARG: reports for %s",nmonths),yearnum);
473  write_html_header(fp_ou,1,title,HTML_JS_NONE);
474  close_html_header(fp_ou);
475  fputs("<div class=\"index\"><table cellpadding=\"1\" cellspacing=\"2\">\n<tr><td></td><td></td></tr>\n",fp_ou);
476  fprintf(fp_ou,"<tr><th class=\"header_l\">%s/%s</th>",_("YEAR"),_("MONTH"));
478  fprintf(fp_ou,"<th class=\"header_l\">%s</th>",_("SIZE"));
479  fputs("</tr>\n",fp_ou);
480  for (m=0 ; m<nmonths ; m++) {
481  if (order>0)
482  month=monthsort[m];
483  else
484  month=monthsort[nmonths-1-m];
485  m1=(month >> 4) & 0x0F;
486  if ((month & 0x0F) != 0) {
487  m2=month & 0x0F;
488  snprintf(monthnum,sizeof(monthnum),"%02d-%02d",m1,m2);
489  name_month(m1,monthname1,sizeof(monthname1));
490  name_month(m2,monthname2,sizeof(monthname2));
491  snprintf(nmonth,sizeof(nmonth),"%s-%s",monthname1,monthname2);
492  } else {
493  snprintf(monthnum,sizeof(monthnum),"%02d",m1);
494  name_month(m1,nmonth,sizeof(nmonth));
495  }
496  if (yeardir_len+strlen(monthnum)+1>=yeardir_size) {
497  yeardir[yeardir_len]='\0';
498  debuga(__FILE__,__LINE__,_("Path too long: "));
499  debuga_more("%s%s\n",yeardir,monthnum);
500  exit(EXIT_FAILURE);
501  }
502  strcpy(yeardir+yeardir_len,monthnum);
503  sub_size=make_date_index_day(yeardir,yeardir_size,order,yearnum,nmonth);
504 
505  fprintf(fp_ou,"<tr><td class=\"data2\"><a href=\"%s/%s\">%s %s</a></td>",monthnum,INDEX_HTML_FILE,yearnum,nmonth);
507  {
508  char size_str[40];
509 
510  strncpy(size_str,fixnum(sub_size,1),sizeof(size_str)-1);
511  size_str[sizeof(size_str)-1]='\0';
512  fprintf(fp_ou,"<td class=\"data2\">%s</td>",size_str);
513  }
514  fputs("</tr>\n",fp_ou);
515  total_size+=sub_size;
516  }
517  fputs("</table></div>\n",fp_ou);
518  yeardir[yeardir_len-1]='\0';
519  write_html_trailer(fp_ou);
520  if (fclose(fp_ou)==EOF) {
521  strcpy(yeardir+yeardir_len,INDEX_HTML_FILE);
522  debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),yeardir,strerror(errno));
523  exit(EXIT_FAILURE);
524  }
525  return(total_size);
526 }
527 
531 static void make_date_index(void)
532 {
533  FILE *fp_ou;
534  DIR *dirp;
535  struct dirent *direntp;
536  char yearindex[MAXLEN];
537  char yeardir[MAXLEN];
538  char yearnum[10];
539  int yearsort[150];
540  int nyears;
541  int year;
542  int i, y;
543  int order;
544  int yeardirlen;
545  long long int total_size;
546 
547  nyears=0;
548  if ((dirp = opendir(outdir)) == NULL) {
549  debuga(__FILE__,__LINE__,_("Cannot open directory \"%s\": %s\n"),outdir,strerror(errno));
550  exit(EXIT_FAILURE);
551  }
552  while ((direntp = readdir( dirp )) != NULL) {
553  if (!isdigit(direntp->d_name[0]) || !isdigit(direntp->d_name[1]) ||
554  !isdigit(direntp->d_name[2]) || !isdigit(direntp->d_name[3])) continue;
555  year=atoi(direntp->d_name) << 10;
556  if (direntp->d_name[4]=='-')
557  {
558  if (!isdigit(direntp->d_name[5]) || !isdigit(direntp->d_name[6]) ||
559  !isdigit(direntp->d_name[7]) || !isdigit(direntp->d_name[8])) continue;
560  if (direntp->d_name[9]) continue;
561  year|=atoi(direntp->d_name+5);
562  }
563  else
564  {
565  if (direntp->d_name[4]) continue;
566  }
567  if (nyears>=sizeof(yearsort)/sizeof(yearsort[0])) {
568  /*
569  If too many years are listed in the directory, we ignore the earliest years. The yearsort array
570  is big enough to accomodate the most ambitious use of sarg but this safety is added to prevent
571  a crash should the directory be polluted by other entries.
572  */
573  if (year>yearsort[0]) {
574  for (i=1 ; i<nyears && year>yearsort[i] ; i++)
575  yearsort[i-1]=yearsort[i];
576  yearsort[i-1]=year;
577  }
578  } else {
579  for (i=nyears ; i>0 && year<yearsort[i-1] ; i--) {
580  yearsort[i]=yearsort[i-1];
581  }
582  yearsort[i]=year;
583  nyears++;
584  }
585  }
586  closedir( dirp );
587 
588  order=(strcmp(IndexSortOrder,"A") == 0) ? 1 : -1;
589 
590  if (snprintf(yearindex,sizeof(yearindex),"%s"INDEX_HTML_FILE,outdir)>=sizeof(yearindex)) {
591  debuga(__FILE__,__LINE__,_("Resulting index file name too long. File name is \"%s/%s\""),outdir,INDEX_HTML_FILE);
592  exit(EXIT_FAILURE);
593  }
594  if ((fp_ou=fopen(yearindex,"w"))==NULL) {
595  debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),yearindex,strerror(errno));
596  exit(EXIT_FAILURE);
597  }
598  write_html_header(fp_ou,0,ngettext("SARG report","SARG reports",nyears),HTML_JS_NONE);
599  close_html_header(fp_ou);
600  fputs("<div class=\"index\"><table cellpadding=\"1\" cellspacing=\"2\">\n",fp_ou);
601  fprintf(fp_ou,"<tr><th class=\"header_l\">%s</th>",_("YEAR"));
603  fprintf(fp_ou,"<th class=\"header_l\">%s</th>",_("SIZE"));
604  fputs("</tr>\n",fp_ou);
605 
606  yeardirlen=strlen(outdir);
607  if (yeardirlen>=sizeof(yeardir)) {
608  debuga(__FILE__,__LINE__,_("Path too long: "));
609  debuga_more("%s",outdir);
610  exit(EXIT_FAILURE);
611  }
612  strcpy(yeardir,outdir);
613 
614  for (y=0 ; y<nyears ; y++) {
615  if (order>0)
616  year=yearsort[y];
617  else
618  year=yearsort[nyears-1-y];
619  if ((year & 0x3FF)==0)
620  snprintf(yearnum,sizeof(yearnum),"%04d",year>>10);
621  else
622  snprintf(yearnum,sizeof(yearnum),"%04d-%04d",year>>10,year & 0x3FF);
623  strcpy(yeardir+yeardirlen,yearnum);
624  total_size=make_date_index_month(yeardir,sizeof(yeardir),order,yearnum);
625 
626  fprintf(fp_ou,"<tr><td class=\"data2\"><a href=\"%s/%s\">%s</a></td>",yearnum,INDEX_HTML_FILE,yearnum);
628  {
629  char size_str[40];
630 
631  strncpy(size_str,fixnum(total_size,1),sizeof(size_str)-1);
632  size_str[sizeof(size_str)-1]='\0';
633  fprintf(fp_ou,"<td class=\"data2\">%s</td>",size_str);
634  }
635  fputs("</tr>\n",fp_ou);
636  }
637 
638  fputs("</table></div>\n",fp_ou);
639  write_html_trailer(fp_ou);
640  if (fclose(fp_ou)==EOF) {
641  debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),yearindex,strerror(errno));
642  exit(EXIT_FAILURE);
643  }
644 }
645 
646 static void make_file_index(void)
647 {
648  #define MAX_CREATION_DATE 15
649  FILE *fp_ou;
650  DIR *dirp;
651  struct dirent *direntp;
652  char wdir[MAXLEN];
653  char data[80];
654  char ftime[9];
655  char day[6], mon[8], year[40], hour[10];
656  long long int tbytes;
657  long long int media;
658  int iyear, imonth, iday, ihour, iminute, isecond, idst;
659  int nsort;
660  int nallocated;
661  int order;
662  int i;
663  int tuser;
664  struct getwordstruct gwarea;
665  struct sortstruct
666  {
667  int year, month, day, sortnum;
668  char creationdate[MAX_CREATION_DATE];
669  char *dirname;
670  char date[60];
671  } **sortlist, *item, **tempsort;
672 
673  if (snprintf(wdir,sizeof(wdir),"%s"INDEX_HTML_FILE,outdir)>=sizeof(wdir)) {
674  debuga(__FILE__,__LINE__,_("Path too long: "));
676  exit(EXIT_FAILURE);
677  }
678 
679  order=(strcmp(IndexSortOrder,"A") == 0) ? 1 : -1;
680 
681  if ((dirp = opendir(outdir)) == NULL) {
682  debuga(__FILE__,__LINE__,_("Cannot open directory \"%s\": %s\n"),outdir,strerror(errno));
683  exit(EXIT_FAILURE);
684  }
685 
686  nsort=0;
687  nallocated=0;
688  sortlist=NULL;
689  while ((direntp = readdir( dirp )) != NULL) {
690  if (strchr(direntp->d_name,'-') == 0) continue;
691  if (obtdate(outdir,direntp->d_name,data)<0) {
692  debuga(__FILE__,__LINE__,_("The directory \"%s%s\" looks like a report directory but doesn't contain a sarg-date file. You should delete it\n"),outdir,direntp->d_name);
693  continue;
694  }
695  item=malloc(sizeof(*item));
696  if (!item) {
697  debuga(__FILE__,__LINE__,_("not enough memory to sort the index\n"));
698  exit(EXIT_FAILURE);
699  }
700  if (df=='u') {
701  item->year=atoi(direntp->d_name);
702  item->month=conv_month(direntp->d_name+4);
703  item->day=atoi(direntp->d_name+7);
704  } else {
705  item->year=atoi(direntp->d_name+5);
706  item->month=conv_month(direntp->d_name+2);
707  item->day=atoi(direntp->d_name);
708  }
709  item->sortnum=(item->year*16+item->month)*32+item->day;
710  if (sscanf(data,"%d-%d-%d %d:%d:%d %d",&iyear,&imonth,&iday,&ihour,&iminute,&isecond,&idst)==7) {
711  formatdate(data,sizeof(data),iyear,imonth,iday,ihour,iminute,isecond,idst);
712  snprintf(item->creationdate,sizeof(item->creationdate),"%04d%02d%02d%02d%02d%02d",iyear,imonth,iday,ihour,iminute,isecond);
713  } else {
714  /*
715  Old code to parse a date stored by sarg before 2.2.6.1 in the sarg-date file of each report directory.
716  */
717  getword_start(&gwarea,data);
718  if (getword_skip(16,&gwarea,' ')<0) {
719  debuga(__FILE__,__LINE__,_("Invalid date in file \"%s%s/sarg-date\"\n"),outdir,direntp->d_name);
720  exit(EXIT_FAILURE);
721  }
722  if (getword_multisep(mon,sizeof(mon),&gwarea,' ')<0) {
723  debuga(__FILE__,__LINE__,_("Invalid date in file \"%s%s/sarg-date\"\n"),outdir,direntp->d_name);
724  exit(EXIT_FAILURE);
725  }
726  if (getword_multisep(day,sizeof(day),&gwarea,' ')<0) {
727  debuga(__FILE__,__LINE__,_("Invalid date in file \"%s%s/sarg-date\"\n"),outdir,direntp->d_name);
728  exit(EXIT_FAILURE);
729  }
730  if (getword_multisep(hour,sizeof(hour),&gwarea,' ')<0) {
731  debuga(__FILE__,__LINE__,_("Invalid time in file \"%s%s/sarg-date\"\n"),outdir,direntp->d_name);
732  exit(EXIT_FAILURE);
733  }
734  do {
735  if (getword_multisep(year,sizeof(year),&gwarea,' ')<0) {
736  debuga(__FILE__,__LINE__,_("Invalid date in file \"%s%s/sarg-date\"\n"),outdir,direntp->d_name);
737  exit(EXIT_FAILURE);
738  }
739  } while (year[0] && !isdigit(year[0])); //skip time zone information with spaces until the year is found
740  if (sscanf(hour,"%d:%d:%d",&ihour,&iminute,&isecond)!=3) {
741  debuga(__FILE__,__LINE__,_("Invalid time in file \"%s%s/sarg-date\"\n"),outdir,direntp->d_name);
742  exit(EXIT_FAILURE);
743  }
744  buildymd(day,mon,year,ftime,sizeof(ftime));
745  snprintf(item->creationdate,sizeof(item->creationdate),"%s%02d%02d%02d",ftime, ihour, iminute, isecond);
746  }
747  item->dirname=strdup(direntp->d_name);
748  if (!item->dirname) {
749  debuga(__FILE__,__LINE__,_("Not enough memory to store the directory name \"%s\" in the index\n"),direntp->d_name);
750  exit(EXIT_FAILURE);
751  }
752  safe_strcpy(item->date,data,sizeof(item->date));
753  if (nsort+1>nallocated) {
754  nallocated+=10;
755  tempsort=realloc(sortlist,nallocated*sizeof(*item));
756  if (!tempsort) {
757  debuga(__FILE__,__LINE__,_("not enough memory to sort the index\n"));
758  exit(EXIT_FAILURE);
759  }
760  sortlist=tempsort;
761  }
762  for (i=nsort ; i>0 ; i--) {
763  if (item->sortnum>sortlist[i-1]->sortnum) break;
764  if (item->sortnum==sortlist[i-1]->sortnum) {
765  if (strcmp(item->creationdate,sortlist[i-1]->creationdate)>=0) break;
766  }
767  sortlist[i]=sortlist[i-1];
768  }
769  sortlist[i]=item;
770  nsort++;
771  }
772 
773  closedir( dirp );
774 
775  if ((fp_ou=fopen(wdir,"w"))==NULL) {
776  debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),wdir,strerror(errno));
777  exit(EXIT_FAILURE);
778  }
779  write_html_header(fp_ou,0,ngettext("SARG report","SARG reports",nsort),HTML_JS_SORTTABLE);
780  close_html_header(fp_ou);
781  fputs("<div class=\"index\"><table cellpadding=\"1\" cellspacing=\"2\"",fp_ou);
782  if (SortTableJs[0]) fputs(" class=\"sortable\"",fp_ou);
783  fputs(">\n",fp_ou);
784  fprintf(fp_ou,"<thead><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></thead>\n",
785  _("FILE/PERIOD"),_("CREATION DATE"),_("USERS"),_("BYTES"),_("AVERAGE"));
786  for (i=0 ; i<nsort ; i++) {
787  if (order>0)
788  item=sortlist[i];
789  else
790  item=sortlist[nsort-i-1];
791  tuser=obtuser(outdir,item->dirname);
792  obttotal(outdir,item->dirname,tuser,&tbytes,&media);
793  fputs("<tr><td class=\"data2\"",fp_ou);
794  if (SortTableJs[0]) fprintf(fp_ou," sorttable_customkey=\"%d\"",item->sortnum);
795  fprintf(fp_ou,"><a href='%s/%s'>%s</a></td>",item->dirname,ReplaceIndex,item->dirname);
796  fputs("<td class=\"data2\"",fp_ou);
797  if (SortTableJs[0]) fprintf(fp_ou," sorttable_customkey=\"%s\"",item->creationdate);
798  fprintf(fp_ou,">%s</td>",item->date);
799  fprintf(fp_ou,"<td class=\"data\">%d</td>",tuser);
800  fputs("<td class=\"data\"",fp_ou);
801  if (SortTableJs[0]) fprintf(fp_ou," sorttable_customkey=\"%"PRId64"\"",(int64_t)tbytes);
802  fprintf(fp_ou,">%s</td>",fixnum(tbytes,1));
803  fputs("<td class=\"data\"",fp_ou);
804  if (SortTableJs[0]) fprintf(fp_ou," sorttable_customkey=\"%"PRId64"\"",(int64_t)media);
805  fprintf(fp_ou,">%s</td></tr>\n",fixnum(media,1));
806  }
807  fputs("</table></div>\n",fp_ou);
808  write_html_trailer(fp_ou);
809  if (fclose(fp_ou)==EOF)
810  debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),wdir,strerror(errno));
811 
812  if (sortlist) {
813  for (i=0 ; i<nsort ; i++) {
814  free(sortlist[i]->dirname);
815  free(sortlist[i]);
816  }
817  free(sortlist);
818  }
819 }
820 
821 static void file_index_to_date_index(const char *entry)
822 {
823  int y1, y2, m1, m2, d1, d2;
824  int i, j;
825  int ndirlen;
826  int monthlen;
827  char sm1[8], sm2[8];
828  char olddir[MAXLEN], newdir[MAXLEN];
829 
830  if (strlen(entry) < 19) return;
831 
832  y1=0;
833  y2=0;
834  memset(sm1,0,sizeof(sm1));
835  memset(sm2,0,sizeof(sm2));
836  d1=0;
837  d2=0;
838  i=0;
839  if (df=='u') {
840  for (j=0 ; entry[i] && isdigit(entry[i]) ; j++)
841  y1=y1*10+(entry[i++]-'0');
842  if (j!=4) return;
843  for (j=0 ; j<sizeof(sm1)-1 && entry[i] && isalpha(entry[i]) ; j++)
844  sm1[j]=entry[i++];
845  if (j!=3) return;
846  sm1[j]='\0';
847  for (j=0 ; entry[i] && isdigit(entry[i]) ; j++)
848  d1=d1*10+(entry[i++]-'0');
849  if (j!=2) return;
850 
851  if (entry[i++]!='-') return;
852 
853  for (j=0 ; entry[i] && isdigit(entry[i]) ; j++)
854  y2=y2*10+(entry[i++]-'0');
855  if (j!=4) return;
856  for (j=0 ; j<sizeof(sm2)-1 && entry[i] && isalpha(entry[i]) ; j++)
857  sm2[j]=entry[i++];
858  if (j!=3) return;
859  sm2[j]='\0';
860  for (j=0 ; entry[i] && isdigit(entry[i]) ; j++)
861  d2=d2*10+(entry[i++]-'0');
862  if (j!=2) return;
863  } else if (df=='e') {
864  for (j=0 ; entry[i] && isdigit(entry[i]) ; j++)
865  d1=d1*10+(entry[i++]-'0');
866  if (j!=2) return;
867  for (j=0 ; j<sizeof(sm1)-1 && entry[i] && isalpha(entry[i]) ; j++)
868  sm1[j]=entry[i++];
869  if (j!=3) return;
870  sm1[j]='\0';
871  for (j=0 ; entry[i] && isdigit(entry[i]) ; j++)
872  y1=y1*10+(entry[i++]-'0');
873  if (j!=4) return;
874 
875  if (entry[i++]!='-') return;
876 
877  for (j=0 ; entry[i] && isdigit(entry[i]) ; j++)
878  d2=d2*10+(entry[i++]-'0');
879  if (j!=2) return;
880  for (j=0 ; j<sizeof(sm2)-1 && entry[i] && isalpha(entry[i]) ; j++)
881  sm2[j]=entry[i++];
882  if (j!=3) return;
883  sm2[j]='\0';
884  for (j=0 ; entry[i] && isdigit(entry[i]) ; j++)
885  y2=y2*10+(entry[i++]-'0');
886  if (j!=4) return;
887  } else
888  return;
889 
890  m1=conv_month(sm1);
891  m2=conv_month(sm2);
892  ndirlen=snprintf(newdir,sizeof(newdir),"%s%04d",outdir,y1);
893  if (ndirlen>=sizeof(newdir)) {
894  debuga(__FILE__,__LINE__,_("Path too long: "));
895  debuga_more("%s%04d",outdir,y1);
896  exit(EXIT_FAILURE);
897  }
898  if (access(newdir, R_OK) != 0) {
899  if (PortableMkDir(newdir,0755)) {
900  debuga(__FILE__,__LINE__,_("Cannot create directory \"%s\": %s\n"),newdir,strerror(errno));
901  exit(EXIT_FAILURE);
902  }
903  }
904  if (m1 != m2) ndirlen+=snprintf(newdir+ndirlen,sizeof(newdir)-ndirlen,"/%02d-%02d",m1,m2);
905  else ndirlen+=snprintf(newdir+ndirlen,sizeof(newdir)-ndirlen,"/%02d",m1);
906  if (ndirlen>=sizeof(newdir)) {
907  debuga(__FILE__,__LINE__,_("Path too long: "));
908  debuga_more("%s",newdir);
909  exit(EXIT_FAILURE);
910  }
911  if (access(newdir, R_OK) != 0) {
912  if (PortableMkDir(newdir,0755)) {
913  debuga(__FILE__,__LINE__,_("Cannot create directory \"%s\": %s\n"),newdir,strerror(errno));
914  exit(EXIT_FAILURE);
915  }
916  }
917  monthlen=ndirlen;
918  if (d1!=d2) ndirlen+=snprintf(newdir+ndirlen,sizeof(newdir)-ndirlen,"/%02d-%02d",d1,d2);
919  else ndirlen+=snprintf(newdir+ndirlen,sizeof(newdir)-ndirlen,"/%02d",d1);
920  if (ndirlen>=sizeof(newdir)) {
921  debuga(__FILE__,__LINE__,_("Path too long: "));
922  debuga_more("%s",newdir);
923  exit(EXIT_FAILURE);
924  }
925 
926  if (snprintf(olddir,sizeof(olddir),"%s%s",outdir,entry)>=sizeof(olddir)) {
927  debuga(__FILE__,__LINE__,_("Path too long: "));
928  debuga_more("%s%s",outdir,entry);
929  exit(EXIT_FAILURE);
930  }
931  if (rename(olddir,newdir)) {
932  debuga(__FILE__,__LINE__,_("Error renaming \"%s\" to \"%s\": %s\n"),olddir,newdir,strerror(errno));
933  exit(EXIT_FAILURE);
934  }
935 
936  strcpy(newdir+monthlen,"/images");
937  if (access(newdir, R_OK) != 0) {
938 #ifdef HAVE_SYMLINK
939  char linkdir[MAXLEN];
940 
941  format_path(__FILE__, __LINE__, linkdir, sizeof(linkdir), "%simages", outdir);
942  if (symlink(linkdir,newdir)) {
943  debuga(__FILE__,__LINE__,_("Failed to create link \"%s\" to \"%s\": %s\n"),linkdir,newdir,strerror(errno));
944  exit(EXIT_FAILURE);
945  }
946 #else
947  char cmd[MAXLEN];
948  int cstatus;
949 
950  sprintf(cmd,"ln -s \"%simages\" \"%s/images\"",outdir,newdir);
951  cstatus=system(cmd);
952  if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
953  debuga(__FILE__,__LINE__,_("command return status %d\n"),WEXITSTATUS(cstatus));
954  debuga(__FILE__,__LINE__,_("command: %s\n"),cmd);
955  exit(EXIT_FAILURE);
956  }
957 #endif
958  }
959 }
960 
961 static void date_index_to_file_index(const char *entry)
962 {
963  int y1, next;
964  int m1, m2;
965  int d1, d2;
966  int val1len;
967  int i, j;
968  char val1[MAXLEN];
969  const char *sm1, *sm2;
970  char *str;
971  char newdir[MAXLEN], olddir[MAXLEN];
972  DIR *dirp2, *dirp3;
973  struct dirent *direntp2;
974  struct dirent *direntp3;
975 
976  if (strlen(entry) != 4) return;
977 
978  next=-1;
979  if (sscanf(entry,"%d%n",&y1,&next)!=1 || next<0 || entry[next]) return;
980 
981  val1len=snprintf(val1,sizeof(val1),"%s%s",outdir,entry);
982  dirp2 = opendir(val1);
983  if (!dirp2) return;
984  while ((direntp2 = readdir( dirp2 )) != NULL) {
985  if (!isdigit(direntp2->d_name[0]) || !isdigit(direntp2->d_name[1])) continue;
986  i=0;
987  str=direntp2->d_name;
988  m1=0;
989  for (j=0 ; j<2 && str[i] && isdigit(str[i]) ; j++)
990  m1=(m1*10)+(str[i++]-'0');
991  if (j>=2) continue;
992  sm1=conv_month_name(m1);
993  if (str[i]=='-') {
994  i++;
995  m2=0;
996  for (j=0 ; j<2 && str[i] && isdigit(str[i]) ; j++)
997  m2=(m2*10)+(str[i++]-'0');
998  if (j>=2) continue;
999  sm2=conv_month_name(m2);
1000  } else if (!str[i]) {
1001  sm2=sm1;
1002  } else {
1003  continue;
1004  }
1005 
1006  sprintf(val1+val1len,"/%s",direntp2->d_name);
1007  dirp3 = opendir(val1);
1008  if (!dirp3) continue;
1009  while ((direntp3 = readdir( dirp3 )) != NULL) {
1010  if (!isdigit(direntp3->d_name[0]) || !isdigit(direntp3->d_name[1])) continue;
1011  i=0;
1012  str=direntp3->d_name;
1013  d1=0;
1014  for (j=0 ; str[i] && isdigit(str[i]) ; j++)
1015  d1=d1*10+(str[i++]-'0');
1016  if (j!=2) continue;
1017  if (str[i]=='-') {
1018  i++;
1019  d2=0;
1020  for (j=0 ; str[i] && isdigit(str[i]) ; j++)
1021  d2=d2*10+(str[i++]-'0');
1022  if (j!=2) continue;
1023  } else if (!str[i]) {
1024  d2=d1;
1025  } else {
1026  continue;
1027  }
1028 
1029  if (df=='u') {
1030  format_path(__FILE__, __LINE__, newdir, sizeof(newdir), "%s%04d%s%02d-%04d%s%02d", outdir, y1, sm1, d1, y1, sm2, d2);
1031  } else if (df=='e') {
1032  format_path(__FILE__, __LINE__, newdir, sizeof(newdir), "%s%02d%s%04d-%02d%s%04d", outdir, d1, sm1, y1, d2, sm2, y1);
1033  } else {
1034  continue;
1035  }
1036  format_path(__FILE__, __LINE__, olddir, sizeof(olddir), "%s%04d/%s/%s", outdir, y1, direntp2->d_name, direntp3->d_name);
1037  if (rename(olddir,newdir)) {
1038  debuga(__FILE__,__LINE__,_("Error renaming \"%s\" to \"%s\": %s\n"),olddir,newdir,strerror(errno));
1039  exit(EXIT_FAILURE);
1040  }
1041  }
1042  closedir(dirp3);
1043  }
1044  closedir(dirp2);
1045 
1050 }
1051 
if
if( $written !=strlen( $url))
Definition: sarg-squidguard-block2.php:97
getword_start
void getword_start(struct getwordstruct *gwarea, const char *line)
Definition: util.c:74
write_html_header
void write_html_header(FILE *fp_ou, int depth, const char *title, int javascript)
Definition: util.c:2144
debuga
void debuga(const char *File, int Line, const char *msg,...)
Definition: util.c:601
HTML_JS_SORTTABLE
#define HTML_JS_SORTTABLE
Bit to include sorttable.js in the html plage.
Definition: conf.h:287
IndexSortOrder
char IndexSortOrder[5]
Definition: conf.h:393
Index
unsigned long int Index
Definition: conf.h:323
make_file_index
static void make_file_index(void)
Definition: index.c:646
INDEX_HTML_FILE
#define INDEX_HTML_FILE
Name of the html file containing the index of a report file.
Definition: conf.h:296
outdir
char outdir[20000]
Definition: conf.h:310
format_path
int format_path(const char *file, int line, char *output_buffer, int buffer_size, const char *format,...)
Definition: util.c:2665
file_index_to_date_index
static void file_index_to_date_index(const char *entry)
Definition: index.c:821
LastLog
int LastLog
Definition: conf.h:320
MY_LSTAT
#define MY_LSTAT
Definition: index.c:33
_
#define _(String)
Definition: conf.h:155
ReplaceIndex
char ReplaceIndex[256]
Definition: conf.h:322
MAXLEN
#define MAXLEN
Definition: conf.h:176
getword_skip
int getword_skip(int limit, struct getwordstruct *gwarea, char stop)
Definition: util.c:160
INDEX_NO
#define INDEX_NO
Definition: conf.h:237
INDEX_TREE_DATE
#define INDEX_TREE_DATE
Definition: conf.h:240
PortableMkDir
int PortableMkDir(const char *path, int mode)
Definition: util.c:403
make_index
void make_index(void)
Definition: index.c:42
N_
#define N_(String)
Definition: conf.h:156
mklastlog
void mklastlog(const char *outdir)
Definition: lastlog.c:256
HTML_JS_NONE
#define HTML_JS_NONE
Value to exclude all the javascripts from the html page.
Definition: conf.h:285
INDEXFIELDS_DIRSIZE
#define INDEXFIELDS_DIRSIZE
Definition: conf.h:243
IndexFields
unsigned long int IndexFields
The columns to show in the index of the reports.
Definition: conf.h:418
name_month
static void name_month(int month, char *month_name, int month_size)
Definition: index.c:365
close_html_header
void close_html_header(FILE *fp_ou)
Definition: util.c:2152
SortTableJs
char SortTableJs[256]
The full path to sorttable.js if the table in the reports must be dynamicaly sorted.
Definition: conf.h:457
make_date_index_day
static long long int make_date_index_day(char *monthdir, int monthdir_size, int order, const char *yearnum, const char *monthnum)
Definition: index.c:233
IndexTree
unsigned long int IndexTree
How to display the index of the reports.
Definition: conf.h:416
get_file_size
static long long int get_file_size(struct stat *statb)
Definition: index.c:112
val1
char val1[20000]
Definition: conf.h:423
conv_month
int conv_month(const char *month)
Definition: util.c:575
fixnum
char * fixnum(long long int value, int n)
Definition: util.c:670
obttotal
void obttotal(const char *dirname, const char *name, int nuser, long long int *tbytes, long long int *media)
Definition: util.c:938
get_size
static long long int get_size(char *path, int path_size)
Definition: index.c:141
conf.h
Include headers and define global variables. */.
df
char df
Definition: conf.h:319
formatdate
void formatdate(char *date, int date_size, int year, int month, int day, int hour, int minute, int second, int dst)
Definition: util.c:871
obtdate
int obtdate(const char *dirname, const char *name, char *data)
Definition: util.c:835
conv_month_name
const char * conv_month_name(int month)
Definition: util.c:584
date_index_to_file_index
static void date_index_to_file_index(const char *entry)
Definition: index.c:961
getword_multisep
int getword_multisep(char *word, int limit, struct getwordstruct *gwarea, char stop)
Definition: util.c:134
getwordstruct
Definition: defs.h:26
make_date_index_month
static long long int make_date_index_month(char *yeardir, int yeardir_size, int order, const char *yearnum)
Definition: index.c:391
safe_strcpy
void safe_strcpy(char *dest, const char *src, int length)
Definition: util.c:1550
write_html_trailer
void write_html_trailer(FILE *fp_ou)
Definition: util.c:2157
defs.h
Declaration of the structures and functions.
ngettext
#define ngettext(Msgid1, Msgid2, N)
Definition: gettext.h:75
cmd
char cmd[255]
Definition: conf.h:442
obtuser
int obtuser(const char *dirname, const char *name)
Definition: util.c:901
debuga_more
void debuga_more(const char *msg,...)
Definition: util.c:631
debug
int debug
Definition: conf.h:489
MAX_CREATION_DATE
#define MAX_CREATION_DATE
buildymd
void buildymd(const char *dia, const char *mes, const char *ano, char *wdata, int wdata_size)
Definition: util.c:566
make_date_index
static void make_date_index(void)
Definition: index.c:531