]>
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("%s",text
[53]);
51 // convert any old report hierarchy
52 dirp
= opendir(outdir
);
53 while ((direntp
= readdir( dirp
)) != NULL
) {
54 if(isdigit(direntp
->d_name
[0]) && isdigit(direntp
->d_name
[1])) {
55 if(IndexTree
== INDEX_TREE_DATE
)
56 file_index_to_date_index(direntp
->d_name
);
58 date_index_to_file_index(direntp
->d_name
);
63 if(IndexTree
== INDEX_TREE_DATE
) {
70 static void make_date_index(void)
72 FILE *fp_ou
, *fp_ou2
, *fp_ou3
;
73 DIR *dirp
, *dirp2
, *dirp3
;
74 struct dirent
*direntp
;
75 struct dirent
*direntp2
;
76 struct dirent
*direntp3
;
77 char yearindex
[MAXLEN
];
80 char monthindex
[MAXLEN
];
81 char monthdir
[MAXLEN
];
82 char monthname1
[9], monthname2
[9];
85 char dayindex
[MAXLEN
];
100 sprintf(yearindex
,"%sindex.html",outdir
);
103 dirp
= opendir(outdir
);
104 while ((direntp
= readdir( dirp
)) != NULL
) {
105 if(strlen(direntp
->d_name
) > 4 || !isdigit(direntp
->d_name
[0]) || !isdigit(direntp
->d_name
[1]) ||
106 !isdigit(direntp
->d_name
[2]) || !isdigit(direntp
->d_name
[3])) continue;
107 year
=atoi(direntp
->d_name
);
108 if (nyears
>=sizeof(yearsort
)/sizeof(yearsort
[0])) {
110 If too many years are listed in the directory, we ignore the earliest years. The yearsort array
111 is big enough to accomodate the most ambitious use of sarg but this safety is added to prevent
112 a crash should the directory be polluted by other entries.
114 if (year
>yearsort
[0]) {
115 for (i
=1 ; i
<nyears
&& year
>yearsort
[i
] ; i
++)
116 yearsort
[i
-1]=yearsort
[i
];
120 for (i
=nyears
; i
>0 && year
<yearsort
[i
-1] ; i
--) {
121 yearsort
[i
]=yearsort
[i
-1];
127 (void)closedir( dirp
);
129 order
=(strcmp(IndexSortOrder
,"A") == 0) ? 1 : -1;
131 if((fp_ou
=fopen(yearindex
,"w"))==NULL
) {
132 fprintf(stderr
, "SARG: (index) %s: %s - %s\n",text
[45],yearindex
,strerror(errno
));
135 write_html_header(fp_ou
,0,"SARG reports");
136 close_html_header(fp_ou
);
137 fputs("<div class=\"index\"><table cellpadding=\"1\" cellspacing=\"2\">\n<tr><td></td><td></td></tr>\n",fp_ou
);
138 fprintf(fp_ou
,"<tr><th class=\"header_l\">%s</th><th class=\"header_l\">%s</th></tr>\n",text
[130],text
[132]);
139 for (y
=0 ; y
<nyears
; y
++) {
143 year
=yearsort
[nyears
-1-y
];
144 sprintf(yearnum
,"%04d",year
);
145 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
));
146 sprintf(yeardir
,"%s%s",outdir
,yearnum
);
149 dirp2
= opendir(yeardir
);
150 while ((direntp2
= readdir( dirp2
)) != NULL
) {
151 if(!isdigit(direntp2
->d_name
[0]) || !isdigit(direntp2
->d_name
[1])) continue;
153 if (sscanf(direntp2
->d_name
,"%d%n",&m1
,&i
)!=1 || m1
<=0 || m1
>12 || i
<0) continue;
154 if (direntp2
->d_name
[i
]=='-') {
155 if (sscanf(direntp2
->d_name
+i
+1,"%d",&m2
)!=1 || m2
<m1
|| m2
>12) continue;
156 } else if (direntp2
->d_name
[i
]!='\0') {
161 if (nmonths
>=sizeof(monthsort
)/sizeof(monthsort
[0])) {
162 fprintf(stderr
,"SARG: Too many month directories in %s\nSupernumerary entries are ignored\n",yeardir
);
166 for (i
=nmonths
; i
>0 && month
<monthsort
[i
-1] ; i
--) {
167 monthsort
[i
]=monthsort
[i
-1];
172 (void)closedir(dirp2
);
173 sprintf(monthindex
,"%s/index.html",yeardir
);
174 if((fp_ou2
=fopen(monthindex
,"w"))==NULL
) {
175 fprintf(stderr
, "SARG: (index) %s: %s - %s\n",text
[45],monthindex
,strerror(errno
));
178 snprintf(title
,sizeof(title
),"SARG: report for %04d",year
);
179 write_html_header(fp_ou2
,1,title
);
180 close_html_header(fp_ou2
);
181 fputs("<div class=\"index\"><table cellpadding=\"1\" cellspacing=\"2\">\n<tr><td></td><td></td></tr>\n",fp_ou2
);
182 fprintf(fp_ou2
,"<tr><th class=\"header_l\">%s/%s</th></tr>\n",text
[130],text
[131]);
183 for (m
=0 ; m
<nmonths
; m
++) {
187 month
=monthsort
[nmonths
-1-m
];
189 if(month
% 16 != 0) {
191 sprintf(monthnum
,"%02d-%02d",m1
,m2
);
192 sprintf(monthname1
,"%02d",m1
);
193 sprintf(monthname2
,"%02d",m2
);
194 name_month(monthname1
,sizeof(monthname1
));
195 name_month(monthname2
,sizeof(monthname2
));
196 sprintf(nmonth
,"%s-%s",monthname1
,monthname2
);
198 sprintf(nmonth
,"%02d",m1
);
199 sprintf(monthnum
,"%02d",m1
);
200 name_month(nmonth
,sizeof(nmonth
));
202 fprintf(fp_ou2
,"<tr><td class=\"data2\"><a href=\"%s/index.html\">%s %s</a></td></tr>\n",monthnum
,yearnum
,nmonth
);
204 sprintf(monthdir
,"%s/%s",yeardir
,monthnum
);
207 dirp3
= opendir(monthdir
);
208 while ((direntp3
= readdir( dirp3
)) != NULL
) {
209 if(!isdigit(direntp3
->d_name
[0]) && !isdigit(direntp3
->d_name
[1])) continue;
211 if (sscanf(direntp3
->d_name
,"%d%n",&d1
,&i
)!=1 || d1
<=0 || d1
>31 || i
<0) continue;
212 if (direntp3
->d_name
[i
]=='-') {
213 if (sscanf(direntp3
->d_name
+i
+1,"%d",&d2
)!=1 || d2
<d1
|| d2
>31) continue;
214 } else if (direntp3
->d_name
[i
]!='\0') {
219 if (ndays
>=sizeof(daysort
)/sizeof(daysort
[0])) {
220 fprintf(stderr
,"SARG: Too many day directories in %s\nSupernumerary entries are ignored\n",monthdir
);
224 for (i
=ndays
; i
>0 && day
<daysort
[i
-1] ; i
--) {
225 daysort
[i
]=daysort
[i
-1];
230 (void)closedir(dirp3
);
231 sprintf(dayindex
,"%s/index.html",monthdir
);
232 if((fp_ou3
=fopen(dayindex
,"w"))==NULL
) {
233 fprintf(stderr
, "SARG: (index) %s: %s - %s\n",text
[45],dayindex
,strerror(errno
));
236 snprintf(title
,sizeof(title
),"SARG: report for %04d/%02d",year
,month
);
237 write_html_header(fp_ou3
,2,title
);
238 close_html_header(fp_ou3
);
239 fputs("<div class=\"index\"><table cellpadding=\"1\" cellspacing=\"2\">\n<tr><td></td><td></td></tr>\n",fp_ou3
);
240 fprintf(fp_ou3
,"<tr><th class=\"header_l\">%s/%s/%s</th></tr>\n",text
[130],text
[131],text
[127]);
241 for (d
=0 ; d
<ndays
; d
++) {
245 day
=daysort
[ndays
-1-d
];
249 sprintf(daynum
,"%02d-%02d",d1
,d2
);
251 sprintf(daynum
,"%02d",d1
);
253 fprintf(fp_ou3
,"<tr><td class=\"data2\"><a href=\"%s/index.html\">%s %s %s</a></td></tr>\n",daynum
,yearnum
,nmonth
,daynum
);
255 fputs("</table></div>\n",fp_ou3
);
256 write_html_trailer(fp_ou3
);
259 fputs("</table></div>\n",fp_ou2
);
260 write_html_trailer(fp_ou2
);
264 fputs("</table></div>\n",fp_ou
);
265 write_html_trailer(fp_ou
);
269 static void make_file_index(void)
271 #define MAX_CREATION_DATE 15
272 #define MAX_DIR_NAME 30
275 struct dirent
*direntp
;
282 char day
[6], mon
[8], year
[40], hour
[10];
283 int iyear
, imonth
, iday
, ihour
, iminute
, isecond
, idst
;
290 struct getwordstruct gwarea
;
294 char creationdate
[MAX_CREATION_DATE
];
295 char dirname
[MAX_DIR_NAME
];
297 } **sortlist
, *item
, **tempsort
;
299 sprintf(wdir
,"%sindex.html",outdir
);
301 order
=(strcmp(IndexSortOrder
,"A") == 0) ? 1 : -1;
303 dirp
= opendir(outdir
);
308 while ((direntp
= readdir( dirp
)) != NULL
) {
309 if (strchr(direntp
->d_name
,'-') == 0) continue;
310 if (strlen(direntp
->d_name
)>MAX_DIR_NAME
) continue;
311 item
=malloc(sizeof(*item
));
313 fprintf(stderr
,"SARG: not enough memory to sort the index\n");
316 if(strcmp(df
,"u") == 0) {
317 strncpy(item
->sortname
,direntp
->d_name
,4);
318 strncpy(month
,direntp
->d_name
+4,3);
320 strncpy(item
->sortname
,direntp
->d_name
+5,4);
321 strncpy(month
,direntp
->d_name
+2,3);
323 item
->sortname
[4]='\0';
326 strcat(item
->sortname
,month
);
327 if(strcmp(df
,"u") == 0) strncat(item
->sortname
,direntp
->d_name
+7,2);
328 else strncat(item
->sortname
,direntp
->d_name
,2);
329 obtdate(outdir
,direntp
->d_name
,data
);
330 if (sscanf(data
,"%d-%d-%d %d:%d:%d %d",&iyear
,&imonth
,&iday
,&ihour
,&iminute
,&isecond
,&idst
)==7) {
331 formatdate(data
,sizeof(data
),iyear
,imonth
,iday
,ihour
,iminute
,isecond
,idst
);
332 snprintf(item
->creationdate
,sizeof(item
->creationdate
),"%04d%02d%02d%02d%02d%02d",iyear
,imonth
,iday
,ihour
,iminute
,isecond
);
335 Old code to parse a date stored by sarg before 2.2.6.1 in the sarg-date file of each report directory.
337 getword_start(&gwarea
,data
);
338 if (getword_skip(16,&gwarea
,' ')<0) {
339 debuga(_("Maybe you have a broken week day in your %s%s/sarg-date file"),outdir
,direntp
->d_name
);
342 if (getword_multisep(mon
,sizeof(mon
),&gwarea
,' ')<0) {
343 debuga(_("Maybe you have a broken month in your %s%s/sarg-date file"),outdir
,direntp
->d_name
);
346 if (getword_multisep(day
,sizeof(day
),&gwarea
,' ')<0) {
347 debuga(_("Maybe you have a broken day in your %s%s/sarg-date file"),outdir
,direntp
->d_name
);
350 if (getword_multisep(hour
,sizeof(hour
),&gwarea
,' ')<0) {
351 debuga(_("Maybe you have a broken time in your %s%s/sarg-date file"),outdir
,direntp
->d_name
);
355 if (getword_multisep(year
,sizeof(year
),&gwarea
,' ')<0) {
356 debuga(_("Maybe you have a broken year in your %s%s/sarg-date file"),outdir
,direntp
->d_name
);
359 } while (year
[0] && !isdigit(year
[0])); //skip time zone information with spaces until the year is found
360 if (sscanf(hour
,"%d:%d:%d",&ihour
,&iminute
,&isecond
)!=3) {
361 debuga(_("Maybe you have a broken time in your %s%s/sarg-date file"),outdir
,direntp
->d_name
);
364 buildymd(day
,mon
,year
,ftime
);
365 snprintf(item
->creationdate
,sizeof(item
->creationdate
),"%s%02d%02d%02d",ftime
, ihour
, iminute
, isecond
);
367 strcpy(item
->dirname
,direntp
->d_name
);
368 strncpy(item
->date
,data
,sizeof(item
->date
));
369 if (nsort
+1>nallocated
) {
371 tempsort
=realloc(sortlist
,nallocated
*sizeof(*item
));
373 fprintf(stderr
,"SARG: not enough memory to sort the index\n");
378 for (i
=nsort
; i
>0 ; i
--) {
379 cmp
=strcmp(item
->sortname
,sortlist
[i
-1]->sortname
);
380 if (cmp
==0) cmp
=strcmp(item
->creationdate
,sortlist
[i
-1]->creationdate
);
384 sortlist
[i
]=sortlist
[i
-1];
390 (void)closedir( dirp
);
392 if((fp_ou
=fopen(wdir
,"w"))==NULL
) {
393 fprintf(stderr
, "SARG: (index) %s: %s\n",text
[45],wdir
);
396 write_html_header(fp_ou
,0,"SARG reports");
397 close_html_header(fp_ou
);
398 fputs("<div class=\"index\"><table cellpadding=\"1\" cellspacing=\"2\">\n<tr><td></td><td></td></tr>\n",fp_ou
);
399 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",text
[101],text
[102],text
[103],text
[93],text
[96]);
400 for (i
=0 ; i
<nsort
; i
++) {
404 item
=sortlist
[nsort
-i
-1];
405 tuser
=obtuser(outdir
,item
->dirname
);
406 obttotal(outdir
,item
->dirname
,tbytes
,tuser
,media
);
407 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
);
409 fputs("</table></div>\n",fp_ou
);
410 write_html_trailer(fp_ou
);
414 for (i
=0 ; i
<nsort
; i
++)
420 static void file_index_to_date_index(const char *entry
)
427 char olddir
[MAXLEN
], newdir
[MAXLEN
];
429 if(strlen(entry
) < 19) return;
433 memset(m1
,0,sizeof(m1
));
434 memset(m2
,0,sizeof(m2
));
438 if(strcmp(df
,"u") == 0) {
439 for (j
=0 ; entry
[i
] && isdigit(entry
[i
]) ; j
++)
440 y1
=y1
*10+(entry
[i
++]-'0');
442 for (j
=0 ; j
<sizeof(m1
)-1 && entry
[i
] && isalpha(entry
[i
]) ; j
++)
446 for (j
=0 ; entry
[i
] && isdigit(entry
[i
]) ; j
++)
447 d1
=d1
*10+(entry
[i
++]-'0');
450 if (entry
[i
++]!='-') return;
452 for (j
=0 ; entry
[i
] && isdigit(entry
[i
]) ; j
++)
453 y2
=y2
*10+(entry
[i
++]-'0');
455 for (j
=0 ; j
<sizeof(m2
)-1 && entry
[i
] && isalpha(entry
[i
]) ; j
++)
459 for (j
=0 ; entry
[i
] && isdigit(entry
[i
]) ; j
++)
460 d2
=d2
*10+(entry
[i
++]-'0');
462 } else if(strcmp(df
,"e") == 0) {
463 for (j
=0 ; entry
[i
] && isdigit(entry
[i
]) ; j
++)
464 d1
=d1
*10+(entry
[i
++]-'0');
466 for (j
=0 ; j
<sizeof(m1
)-1 && entry
[i
] && isalpha(entry
[i
]) ; j
++)
470 for (j
=0 ; entry
[i
] && isdigit(entry
[i
]) ; j
++)
471 y1
=y1
*10+(entry
[i
++]-'0');
474 if (entry
[i
++]!='-') return;
476 for (j
=0 ; entry
[i
] && isdigit(entry
[i
]) ; j
++)
477 d2
=d2
*10+(entry
[i
++]-'0');
479 for (j
=0 ; j
<sizeof(m2
)-1 && entry
[i
] && isalpha(entry
[i
]) ; j
++)
483 for (j
=0 ; entry
[i
] && isdigit(entry
[i
]) ; j
++)
484 y2
=y2
*10+(entry
[i
++]-'0');
491 ndirlen
=sprintf(newdir
,"%s%04d",outdir
,y1
);
492 if(access(newdir
, R_OK
) != 0) mkdir(newdir
,0755);
493 if(strcmp(m1
,m2
) != 0) ndirlen
+=sprintf(newdir
+ndirlen
,"/%s-%s",m1
,m2
);
494 else ndirlen
+=sprintf(newdir
+ndirlen
,"/%s",m1
);
495 if(access(newdir
, R_OK
) != 0) mkdir(newdir
,0755);
497 if(d1
!=d2
) ndirlen
+=sprintf(newdir
+ndirlen
,"/%02d-%02d",d1
,d2
);
498 else ndirlen
+=sprintf(newdir
+ndirlen
,"/%02d",d1
);
500 sprintf(olddir
,"%s%s",outdir
,entry
);
501 if (rename(olddir
,newdir
)) {
502 fprintf(stderr
, "SARG: (index) rename error from \"%s\" to \"%s\" - %s\n",olddir
,newdir
,strerror(errno
));
506 strcpy(newdir
+monthlen
,"/images");
507 if(access(newdir
, R_OK
) != 0) {
509 char linkdir
[MAXLEN
];
511 sprintf(linkdir
,"%simages",outdir
);
512 if (symlink(linkdir
,newdir
)) {
513 fprintf(stderr
, "SARG: failed to create link \"%s\" to \"%s\" - %s\n",linkdir
,newdir
,strerror(errno
));
520 sprintf(cmd
,"ln -s \"%simages\" \"%s/images\"",outdir
,newdir
);
522 if (!WIFEXITED(cstatus
) || WEXITSTATUS(cstatus
)) {
523 fprintf(stderr
, "SARG: command return status %d\n",WEXITSTATUS(cstatus
));
524 fprintf(stderr
, "SARG: command: %s\n",cmd
);
531 static void date_index_to_file_index(const char *entry
)
540 char newdir
[MAXLEN
], olddir
[MAXLEN
];
542 struct dirent
*direntp2
;
543 struct dirent
*direntp3
;
545 if(strlen(entry
) != 4) return;
548 if (sscanf(entry
,"%d%n",&y1
,&next
)!=1 || next
<0 || entry
[next
]) return;
550 val1len
=sprintf(val1
,"%s%s",outdir
,entry
);
551 dirp2
= opendir(val1
);
553 while ((direntp2
= readdir( dirp2
)) != NULL
) {
554 if(!isdigit(direntp2
->d_name
[0]) || !isdigit(direntp2
->d_name
[1])) continue;
556 str
=direntp2
->d_name
;
557 for (j
=0 ; j
<sizeof(m1
) && str
[i
] && isdigit(str
[i
]) ; j
++)
559 if (j
>=sizeof(m1
)) continue;
564 for (j
=0 ; j
<sizeof(m2
) && str
[i
] && isdigit(str
[i
]) ; j
++)
566 if (j
>=sizeof(m2
)) continue;
569 } else if (!str
[i
]) {
575 sprintf(val1
+val1len
,"/%s",direntp2
->d_name
);
576 dirp3
= opendir(val1
);
577 if (!dirp3
) continue;
578 while ((direntp3
= readdir( dirp3
)) != NULL
) {
579 if(!isdigit(direntp3
->d_name
[0]) || !isdigit(direntp3
->d_name
[1])) continue;
581 str
=direntp3
->d_name
;
583 for (j
=0 ; str
[i
] && isdigit(str
[i
]) ; j
++)
584 d1
=d1
*10+(str
[i
++]-'0');
589 for (j
=0 ; str
[i
] && isdigit(str
[i
]) ; j
++)
590 d2
=d2
*10+(str
[i
++]-'0');
592 } else if (!str
[i
]) {
598 if(strcmp(df
,"u") == 0) sprintf(newdir
,"%s%04d%s%02d-%04d%s%02d",outdir
,y1
,m1
,d1
,y1
,m2
,d2
);
599 else if(strcmp(df
,"e") == 0) sprintf(newdir
,"%s%02d%s%04d-%02d%s%04d",outdir
,d1
,m1
,y1
,d2
,m2
,y1
);
601 sprintf(olddir
,"%s%04d/%s/%s",outdir
,y1
,direntp2
->d_name
,direntp3
->d_name
);
602 if(rename(olddir
,newdir
)) {
603 fprintf(stderr
, "SARG: (index) rename error from \"%s\" to \"%s\" - %s\n",olddir
,newdir
,strerror(errno
));
607 (void)closedir( dirp3
);
609 (void)closedir( dirp2
);
612 \bug The links to the images in the reports are broken after moving the directories
613 as the the HTML files are not at the right level for the images any more.