]>
git.ipfire.org Git - thirdparty/sarg.git/blob - index.c
2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
6 * please look at http://sarg.sourceforge.net/donations.php
8 * http://sourceforge.net/projects/sarg/forums/forum/363374
9 * ---------------------------------------------------------------------
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.
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.
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.
27 #include "include/conf.h"
28 #include "include/defs.h"
30 static void make_date_index(void);
31 static void make_file_index(void);
32 static void file_index_to_date_index(const char *entry
);
33 static void date_index_to_file_index(const char *entry
);
38 struct dirent
*direntp
;
41 if(LastLog
> 0) mklastlog(outdir
);
43 if(Index
== INDEX_NO
) {
44 sprintf(wdir
,"%sindex.html",outdir
);
45 if(access(wdir
, R_OK
) == 0) unlink(wdir
);
49 if(debug
) debuga(_("Making index.html\n"));
51 // convert any old report hierarchy
52 if ((dirp
= opendir(outdir
)) == NULL
) {
53 debuga(_("Failed to open directory %s - %s\n"),outdir
,strerror(errno
));
56 while ((direntp
= readdir( dirp
)) != NULL
) {
57 if(isdigit(direntp
->d_name
[0]) && isdigit(direntp
->d_name
[1])) {
58 if(IndexTree
== INDEX_TREE_DATE
)
59 file_index_to_date_index(direntp
->d_name
);
61 date_index_to_file_index(direntp
->d_name
);
66 if(IndexTree
== INDEX_TREE_DATE
) {
73 static void make_date_index(void)
75 FILE *fp_ou
, *fp_ou2
, *fp_ou3
;
76 DIR *dirp
, *dirp2
, *dirp3
;
77 struct dirent
*direntp
;
78 struct dirent
*direntp2
;
79 struct dirent
*direntp3
;
80 char yearindex
[MAXLEN
];
83 char monthindex
[MAXLEN
];
84 char monthdir
[MAXLEN
];
85 char monthname1
[9], monthname2
[9];
88 char dayindex
[MAXLEN
];
103 sprintf(yearindex
,"%sindex.html",outdir
);
106 if ((dirp
= opendir(outdir
)) == NULL
) {
107 debuga(_("Failed to open directory %s - %s\n"),outdir
,strerror(errno
));
110 while ((direntp
= readdir( dirp
)) != NULL
) {
111 if(strlen(direntp
->d_name
) > 4 || !isdigit(direntp
->d_name
[0]) || !isdigit(direntp
->d_name
[1]) ||
112 !isdigit(direntp
->d_name
[2]) || !isdigit(direntp
->d_name
[3])) continue;
113 year
=atoi(direntp
->d_name
);
114 if (nyears
>=sizeof(yearsort
)/sizeof(yearsort
[0])) {
116 If too many years are listed in the directory, we ignore the earliest years. The yearsort array
117 is big enough to accomodate the most ambitious use of sarg but this safety is added to prevent
118 a crash should the directory be polluted by other entries.
120 if (year
>yearsort
[0]) {
121 for (i
=1 ; i
<nyears
&& year
>yearsort
[i
] ; i
++)
122 yearsort
[i
-1]=yearsort
[i
];
126 for (i
=nyears
; i
>0 && year
<yearsort
[i
-1] ; i
--) {
127 yearsort
[i
]=yearsort
[i
-1];
135 order
=(strcmp(IndexSortOrder
,"A") == 0) ? 1 : -1;
137 if((fp_ou
=fopen(yearindex
,"w"))==NULL
) {
138 debuga(_("(index) Cannot open file %s - %s\n"),yearindex
,strerror(errno
));
141 write_html_header(fp_ou
,0,ngettext("SARG report","SARG reports",nyears
));
142 close_html_header(fp_ou
);
143 fputs("<div class=\"index\"><table cellpadding=\"1\" cellspacing=\"2\">\n<tr><td></td><td></td></tr>\n",fp_ou
);
144 fprintf(fp_ou
,"<tr><th class=\"header_l\">%s</th><th class=\"header_l\">%s</th></tr>\n",_("YEAR"),_("SIZE"));
145 for (y
=0 ; y
<nyears
; y
++) {
149 year
=yearsort
[nyears
-1-y
];
150 sprintf(yearnum
,"%04d",year
);
151 fprintf(fp_ou
,"<tr><td class=\"data2\"><a href=\"%s/index.html\">%s</a></td><td class=\"data2\">%s</td></tr>\n",yearnum
,yearnum
,get_size(outdir
,yearnum
));
152 sprintf(yeardir
,"%s%s",outdir
,yearnum
);
155 if ((dirp2
= opendir(yeardir
)) == NULL
) {
156 debuga(_("Failed to open directory %s - %s\n"),yeardir
,strerror(errno
));
159 while ((direntp2
= readdir( dirp2
)) != NULL
) {
160 if(!isdigit(direntp2
->d_name
[0]) || !isdigit(direntp2
->d_name
[1])) continue;
162 if (sscanf(direntp2
->d_name
,"%d%n",&m1
,&i
)!=1 || m1
<=0 || m1
>12 || i
<0) continue;
163 if (direntp2
->d_name
[i
]=='-') {
164 if (sscanf(direntp2
->d_name
+i
+1,"%d",&m2
)!=1 || m2
<m1
|| m2
>12) continue;
165 } else if (direntp2
->d_name
[i
]!='\0') {
170 if (nmonths
>=sizeof(monthsort
)/sizeof(monthsort
[0])) {
171 debuga(_("Too many month directories in %s\nSupernumerary entries are ignored\n"),yeardir
);
175 for (i
=nmonths
; i
>0 && month
<monthsort
[i
-1] ; i
--) {
176 monthsort
[i
]=monthsort
[i
-1];
182 sprintf(monthindex
,"%s/index.html",yeardir
);
183 if((fp_ou2
=fopen(monthindex
,"w"))==NULL
) {
184 debuga(_("(index) Cannot open file %s - %s\n"),monthindex
,strerror(errno
));
187 snprintf(title
,sizeof(title
),ngettext("SARG: report for %04d","SARG: reports for %04d",nmonths
),year
);
188 write_html_header(fp_ou2
,1,title
);
189 close_html_header(fp_ou2
);
190 fputs("<div class=\"index\"><table cellpadding=\"1\" cellspacing=\"2\">\n<tr><td></td><td></td></tr>\n",fp_ou2
);
191 fprintf(fp_ou2
,"<tr><th class=\"header_l\">%s/%s</th></tr>\n",_("YEAR"),_("MONTH"));
192 for (m
=0 ; m
<nmonths
; m
++) {
196 month
=monthsort
[nmonths
-1-m
];
198 if(month
% 16 != 0) {
200 sprintf(monthnum
,"%02d-%02d",m1
,m2
);
201 sprintf(monthname1
,"%02d",m1
);
202 sprintf(monthname2
,"%02d",m2
);
203 name_month(monthname1
,sizeof(monthname1
));
204 name_month(monthname2
,sizeof(monthname2
));
205 sprintf(nmonth
,"%s-%s",monthname1
,monthname2
);
207 sprintf(nmonth
,"%02d",m1
);
208 sprintf(monthnum
,"%02d",m1
);
209 name_month(nmonth
,sizeof(nmonth
));
211 fprintf(fp_ou2
,"<tr><td class=\"data2\"><a href=\"%s/index.html\">%s %s</a></td></tr>\n",monthnum
,yearnum
,nmonth
);
213 sprintf(monthdir
,"%s/%s",yeardir
,monthnum
);
216 if ((dirp3
= opendir(monthdir
)) == NULL
) {
217 debuga(_("Failed to open directory %s - %s\n"),monthdir
,strerror(errno
));
220 while ((direntp3
= readdir( dirp3
)) != NULL
) {
221 if(!isdigit(direntp3
->d_name
[0]) && !isdigit(direntp3
->d_name
[1])) continue;
223 if (sscanf(direntp3
->d_name
,"%d%n",&d1
,&i
)!=1 || d1
<=0 || d1
>31 || i
<0) continue;
224 if (direntp3
->d_name
[i
]=='-') {
225 if (sscanf(direntp3
->d_name
+i
+1,"%d",&d2
)!=1 || d2
<d1
|| d2
>31) continue;
226 } else if (direntp3
->d_name
[i
]!='\0') {
231 if (ndays
>=sizeof(daysort
)/sizeof(daysort
[0])) {
232 debuga(_("Too many day directories in %s\nSupernumerary entries are ignored\n"),monthdir
);
236 for (i
=ndays
; i
>0 && day
<daysort
[i
-1] ; i
--) {
237 daysort
[i
]=daysort
[i
-1];
243 sprintf(dayindex
,"%s/index.html",monthdir
);
244 if((fp_ou3
=fopen(dayindex
,"w"))==NULL
) {
245 debuga(_("(index) Cannot open file %s - %s\n"),dayindex
,strerror(errno
));
248 snprintf(title
,sizeof(title
),ngettext("SARG: report for %04d/%02d","SARG: reports for %04d/%02d",ndays
),year
,month
);
249 write_html_header(fp_ou3
,2,title
);
250 close_html_header(fp_ou3
);
251 fputs("<div class=\"index\"><table cellpadding=\"1\" cellspacing=\"2\">\n<tr><td></td><td></td></tr>\n",fp_ou3
);
252 fprintf(fp_ou3
,"<tr><th class=\"header_l\">%s/%s/%s</th></tr>\n",_("YEAR"),_("MONTH"),_("DAYS"));
253 for (d
=0 ; d
<ndays
; d
++) {
257 day
=daysort
[ndays
-1-d
];
261 sprintf(daynum
,"%02d-%02d",d1
,d2
);
263 sprintf(daynum
,"%02d",d1
);
265 fprintf(fp_ou3
,"<tr><td class=\"data2\"><a href=\"%s/index.html\">%s %s %s</a></td></tr>\n",daynum
,yearnum
,nmonth
,daynum
);
267 fputs("</table></div>\n",fp_ou3
);
268 if (write_html_trailer(fp_ou3
)<0)
269 debuga(_("Write error in the index %s\n"),dayindex
);
270 if (fclose(fp_ou3
)==EOF
)
271 debuga(_("Failed to close the index file %s - %s\n"),dayindex
,strerror(errno
));
273 fputs("</table></div>\n",fp_ou2
);
274 if (write_html_trailer(fp_ou2
)<0)
275 debuga(_("Write error in the index %s\n"),monthindex
);
276 if (fclose(fp_ou2
)==EOF
)
277 debuga(_("Failed to close the index file %s - %s\n"),monthindex
,strerror(errno
));
280 fputs("</table></div>\n",fp_ou
);
281 if (write_html_trailer(fp_ou
)<0)
282 debuga(_("Write error in the index %s\n"),yearindex
);
283 if (fclose(fp_ou
)==EOF
)
284 debuga(_("Failed to close the index file %s - %s\n"),yearindex
,strerror(errno
));
287 static void make_file_index(void)
289 #define MAX_CREATION_DATE 15
290 #define MAX_DIR_NAME 30
293 struct dirent
*direntp
;
299 char day
[6], mon
[8], year
[40], hour
[10];
300 int iyear
, imonth
, iday
, ihour
, iminute
, isecond
, idst
;
306 struct getwordstruct gwarea
;
309 int year
, month
, day
, sortnum
;
310 char creationdate
[MAX_CREATION_DATE
];
311 char dirname
[MAX_DIR_NAME
];
313 } **sortlist
, *item
, **tempsort
;
315 sprintf(wdir
,"%sindex.html",outdir
);
317 order
=(strcmp(IndexSortOrder
,"A") == 0) ? 1 : -1;
319 if ((dirp
= opendir(outdir
)) == NULL
) {
320 debuga(_("Failed to open directory %s - %s\n"),outdir
,strerror(errno
));
327 while ((direntp
= readdir( dirp
)) != NULL
) {
328 if (strchr(direntp
->d_name
,'-') == 0) continue;
329 if (strlen(direntp
->d_name
)>MAX_DIR_NAME
) continue;
330 item
=malloc(sizeof(*item
));
332 debuga(_("not enough memory to sort the index\n"));
335 if(strcmp(df
,"u") == 0) {
336 item
->year
=atoi(direntp
->d_name
);
337 item
->month
=conv_month(direntp
->d_name
+4);
338 item
->day
=atoi(direntp
->d_name
+7);
340 item
->year
=atoi(direntp
->d_name
+5);
341 item
->month
=conv_month(direntp
->d_name
+2);
342 item
->day
=atoi(direntp
->d_name
);
344 item
->sortnum
=(item
->year
*16+item
->month
)*32+item
->day
;
345 obtdate(outdir
,direntp
->d_name
,data
);
346 if (sscanf(data
,"%d-%d-%d %d:%d:%d %d",&iyear
,&imonth
,&iday
,&ihour
,&iminute
,&isecond
,&idst
)==7) {
347 formatdate(data
,sizeof(data
),iyear
,imonth
,iday
,ihour
,iminute
,isecond
,idst
);
348 snprintf(item
->creationdate
,sizeof(item
->creationdate
),"%04d%02d%02d%02d%02d%02d",iyear
,imonth
,iday
,ihour
,iminute
,isecond
);
351 Old code to parse a date stored by sarg before 2.2.6.1 in the sarg-date file of each report directory.
353 getword_start(&gwarea
,data
);
354 if (getword_skip(16,&gwarea
,' ')<0) {
355 debuga(_("Maybe you have a broken week day in your %s%s/sarg-date file\n"),outdir
,direntp
->d_name
);
358 if (getword_multisep(mon
,sizeof(mon
),&gwarea
,' ')<0) {
359 debuga(_("Maybe you have a broken month in your %s%s/sarg-date file\n"),outdir
,direntp
->d_name
);
362 if (getword_multisep(day
,sizeof(day
),&gwarea
,' ')<0) {
363 debuga(_("Maybe you have a broken day in your %s%s/sarg-date file\n"),outdir
,direntp
->d_name
);
366 if (getword_multisep(hour
,sizeof(hour
),&gwarea
,' ')<0) {
367 debuga(_("Maybe you have a broken time in your %s%s/sarg-date file\n"),outdir
,direntp
->d_name
);
371 if (getword_multisep(year
,sizeof(year
),&gwarea
,' ')<0) {
372 debuga(_("Maybe you have a broken year in your %s%s/sarg-date file\n"),outdir
,direntp
->d_name
);
375 } while (year
[0] && !isdigit(year
[0])); //skip time zone information with spaces until the year is found
376 if (sscanf(hour
,"%d:%d:%d",&ihour
,&iminute
,&isecond
)!=3) {
377 debuga(_("Maybe you have a broken time in your %s%s/sarg-date file\n"),outdir
,direntp
->d_name
);
380 buildymd(day
,mon
,year
,ftime
);
381 snprintf(item
->creationdate
,sizeof(item
->creationdate
),"%s%02d%02d%02d",ftime
, ihour
, iminute
, isecond
);
383 strcpy(item
->dirname
,direntp
->d_name
);
384 strncpy(item
->date
,data
,sizeof(item
->date
));
385 if (nsort
+1>nallocated
) {
387 tempsort
=realloc(sortlist
,nallocated
*sizeof(*item
));
389 debuga(_("not enough memory to sort the index\n"));
394 for (i
=nsort
; i
>0 ; i
--) {
395 if (item
->sortnum
>sortlist
[i
-1]->sortnum
) break;
396 if (item
->sortnum
==sortlist
[i
-1]->sortnum
) {
397 if (strcmp(item
->creationdate
,sortlist
[i
-1]->creationdate
)>=0) break;
399 sortlist
[i
]=sortlist
[i
-1];
407 if((fp_ou
=fopen(wdir
,"w"))==NULL
) {
408 debuga(_("(index) Cannot open file %s\n"),wdir
);
411 write_html_header(fp_ou
,0,ngettext("SARG report","SARG reports",nsort
));
412 close_html_header(fp_ou
);
413 fputs("<div class=\"index\"><table cellpadding=\"1\" cellspacing=\"2\">\n<tr><td></td><td></td></tr>\n",fp_ou
);
414 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",_("FILE/PERIOD"),_("CREATION DATE"),_("USERS"),_("BYTES"),_("AVERAGE"));
415 for (i
=0 ; i
<nsort
; i
++) {
419 item
=sortlist
[nsort
-i
-1];
420 tuser
=obtuser(outdir
,item
->dirname
);
421 obttotal(outdir
,item
->dirname
,tbytes
,tuser
,media
);
422 fprintf(fp_ou
,"<tr><td class=\"data2\"><a href='%s/%s'>%s</a></td><td class=\"data2\">%s</td><td class=\"data\">%d</td><td class=\"data\">%s</td><td class=\"data\">%s</td></tr>\n",item
->dirname
,ReplaceIndex
,item
->dirname
,item
->date
,tuser
,tbytes
,media
);
424 fputs("</table></div>\n",fp_ou
);
425 if (write_html_trailer(fp_ou
)<0)
426 debuga(_("Write error in the index %s\n"),wdir
);
427 if (fclose(fp_ou
)==EOF
)
428 debuga(_("Failed to close the index file %s - %s\n"),wdir
,strerror(errno
));
431 for (i
=0 ; i
<nsort
; i
++)
437 static void file_index_to_date_index(const char *entry
)
439 int y1
, y2
, m1
, m2
, d1
, d2
;
444 char olddir
[MAXLEN
], newdir
[MAXLEN
];
446 if(strlen(entry
) < 19) return;
450 memset(sm1
,0,sizeof(sm1
));
451 memset(sm2
,0,sizeof(sm2
));
455 if(strcmp(df
,"u") == 0) {
456 for (j
=0 ; entry
[i
] && isdigit(entry
[i
]) ; j
++)
457 y1
=y1
*10+(entry
[i
++]-'0');
459 for (j
=0 ; j
<sizeof(sm1
)-1 && entry
[i
] && isalpha(entry
[i
]) ; j
++)
463 for (j
=0 ; entry
[i
] && isdigit(entry
[i
]) ; j
++)
464 d1
=d1
*10+(entry
[i
++]-'0');
467 if (entry
[i
++]!='-') return;
469 for (j
=0 ; entry
[i
] && isdigit(entry
[i
]) ; j
++)
470 y2
=y2
*10+(entry
[i
++]-'0');
472 for (j
=0 ; j
<sizeof(sm2
)-1 && entry
[i
] && isalpha(entry
[i
]) ; j
++)
476 for (j
=0 ; entry
[i
] && isdigit(entry
[i
]) ; j
++)
477 d2
=d2
*10+(entry
[i
++]-'0');
479 } else if(strcmp(df
,"e") == 0) {
480 for (j
=0 ; entry
[i
] && isdigit(entry
[i
]) ; j
++)
481 d1
=d1
*10+(entry
[i
++]-'0');
483 for (j
=0 ; j
<sizeof(sm1
)-1 && entry
[i
] && isalpha(entry
[i
]) ; j
++)
487 for (j
=0 ; entry
[i
] && isdigit(entry
[i
]) ; j
++)
488 y1
=y1
*10+(entry
[i
++]-'0');
491 if (entry
[i
++]!='-') return;
493 for (j
=0 ; entry
[i
] && isdigit(entry
[i
]) ; j
++)
494 d2
=d2
*10+(entry
[i
++]-'0');
496 for (j
=0 ; j
<sizeof(sm2
)-1 && entry
[i
] && isalpha(entry
[i
]) ; j
++)
500 for (j
=0 ; entry
[i
] && isdigit(entry
[i
]) ; j
++)
501 y2
=y2
*10+(entry
[i
++]-'0');
508 ndirlen
=sprintf(newdir
,"%s%04d",outdir
,y1
);
509 if(access(newdir
, R_OK
) != 0) mkdir(newdir
,0755);
510 if(m1
!= m2
) ndirlen
+=sprintf(newdir
+ndirlen
,"/%02d-%02d",m1
,m2
);
511 else ndirlen
+=sprintf(newdir
+ndirlen
,"/%02d",m1
);
512 if(access(newdir
, R_OK
) != 0) mkdir(newdir
,0755);
514 if(d1
!=d2
) ndirlen
+=sprintf(newdir
+ndirlen
,"/%02d-%02d",d1
,d2
);
515 else ndirlen
+=sprintf(newdir
+ndirlen
,"/%02d",d1
);
517 sprintf(olddir
,"%s%s",outdir
,entry
);
518 if (rename(olddir
,newdir
)) {
519 debuga(_("(index) rename error from \"%s\" to \"%s\" - %s\n"),olddir
,newdir
,strerror(errno
));
523 strcpy(newdir
+monthlen
,"/images");
524 if(access(newdir
, R_OK
) != 0) {
526 char linkdir
[MAXLEN
];
528 sprintf(linkdir
,"%simages",outdir
);
529 if (symlink(linkdir
,newdir
)) {
530 debuga(_("failed to create link \"%s\" to \"%s\" - %s\n"),linkdir
,newdir
,strerror(errno
));
537 sprintf(cmd
,"ln -s \"%simages\" \"%s/images\"",outdir
,newdir
);
539 if (!WIFEXITED(cstatus
) || WEXITSTATUS(cstatus
)) {
540 debuga(_("command return status %d\n"),WEXITSTATUS(cstatus
));
541 debuga(_("command: %s\n"),cmd
);
548 static void date_index_to_file_index(const char *entry
)
556 const char *sm1
, *sm2
;
558 char newdir
[MAXLEN
], olddir
[MAXLEN
];
560 struct dirent
*direntp2
;
561 struct dirent
*direntp3
;
563 if(strlen(entry
) != 4) return;
566 if (sscanf(entry
,"%d%n",&y1
,&next
)!=1 || next
<0 || entry
[next
]) return;
568 val1len
=snprintf(val1
,sizeof(val1
),"%s%s",outdir
,entry
);
569 dirp2
= opendir(val1
);
571 while ((direntp2
= readdir( dirp2
)) != NULL
) {
572 if(!isdigit(direntp2
->d_name
[0]) || !isdigit(direntp2
->d_name
[1])) continue;
574 str
=direntp2
->d_name
;
576 for (j
=0 ; j
<2 && str
[i
] && isdigit(str
[i
]) ; j
++)
577 m1
=(m1
*10)+(str
[i
++]-'0');
579 sm1
=conv_month_name(m1
);
583 for (j
=0 ; j
<2 && str
[i
] && isdigit(str
[i
]) ; j
++)
584 m2
=(m2
*10)+(str
[i
++]-'0');
586 sm2
=conv_month_name(m2
);
587 } else if (!str
[i
]) {
593 sprintf(val1
+val1len
,"/%s",direntp2
->d_name
);
594 dirp3
= opendir(val1
);
595 if (!dirp3
) continue;
596 while ((direntp3
= readdir( dirp3
)) != NULL
) {
597 if(!isdigit(direntp3
->d_name
[0]) || !isdigit(direntp3
->d_name
[1])) continue;
599 str
=direntp3
->d_name
;
601 for (j
=0 ; str
[i
] && isdigit(str
[i
]) ; j
++)
602 d1
=d1
*10+(str
[i
++]-'0');
607 for (j
=0 ; str
[i
] && isdigit(str
[i
]) ; j
++)
608 d2
=d2
*10+(str
[i
++]-'0');
610 } else if (!str
[i
]) {
616 if(strcmp(df
,"u") == 0) sprintf(newdir
,"%s%04d%s%02d-%04d%s%02d",outdir
,y1
,sm1
,d1
,y1
,sm2
,d2
);
617 else if(strcmp(df
,"e") == 0) sprintf(newdir
,"%s%02d%s%04d-%02d%s%04d",outdir
,d1
,sm1
,y1
,d2
,sm2
,y1
);
619 sprintf(olddir
,"%s%04d/%s/%s",outdir
,y1
,direntp2
->d_name
,direntp3
->d_name
);
620 if(rename(olddir
,newdir
)) {
621 debuga(_("(index) rename error from \"%s\" to \"%s\" - %s\n"),olddir
,newdir
,strerror(errno
));
630 \bug The links to the images in the reports are broken after moving the directories
631 as the the HTML files are not at the right level for the images any more.