]> git.ipfire.org Git - thirdparty/sarg.git/blob - index.c
Fix several possible sprintf buffer overflows
[thirdparty/sarg.git] / index.c
1 /*
2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
3 * 1998, 2013
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 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);
34
35 void make_index(void)
36 {
37 DIR *dirp;
38 struct dirent *direntp;
39 char wdir[MAXLEN];
40
41 if(LastLog > 0) mklastlog(outdir);
42
43 if(Index == INDEX_NO) {
44 sprintf(wdir,"%sindex.html",outdir);
45 if(access(wdir, R_OK) == 0) {
46 if (unlink(wdir)) {
47 debuga(_("Cannot delete \"%s\": %s\n"),wdir,strerror(errno));
48 exit(EXIT_FAILURE);
49 }
50 }
51 return;
52 }
53
54 if(debug) debuga(_("Making index.html\n"));
55
56 // convert any old report hierarchy
57 if ((dirp = opendir(outdir)) == NULL) {
58 debuga(_("Failed to open directory %s - %s\n"),outdir,strerror(errno));
59 exit(EXIT_FAILURE);
60 }
61 while ((direntp = readdir( dirp )) != NULL) {
62 if(isdigit(direntp->d_name[0]) && isdigit(direntp->d_name[1])) {
63 if(IndexTree == INDEX_TREE_DATE)
64 file_index_to_date_index(direntp->d_name);
65 else
66 date_index_to_file_index(direntp->d_name);
67 }
68 }
69 closedir(dirp);
70
71 if(IndexTree == INDEX_TREE_DATE) {
72 make_date_index();
73 } else {
74 make_file_index();
75 }
76 }
77
78 static void make_date_index(void)
79 {
80 FILE *fp_ou, *fp_ou2, *fp_ou3;
81 DIR *dirp, *dirp2, *dirp3;
82 struct dirent *direntp;
83 struct dirent *direntp2;
84 struct dirent *direntp3;
85 char yearindex[MAXLEN];
86 char yeardir[MAXLEN];
87 char yearnum[10];
88 char monthindex[MAXLEN];
89 char monthdir[MAXLEN];
90 char monthname1[9], monthname2[9];
91 char nmonth[30];
92 char monthnum[10];
93 char dayindex[MAXLEN];
94 char daynum[10];
95 char title[80];
96 int yearsort[150];
97 int nyears;
98 int year;
99 int monthsort[144];
100 int nmonths;
101 int m1, m2, month;
102 int daysort[31*31];
103 int ndays;
104 int d1, d2, day;
105 int i, y, m, d;
106 int order;
107
108 sprintf(yearindex,"%sindex.html",outdir);
109
110 nyears=0;
111 if ((dirp = opendir(outdir)) == NULL) {
112 debuga(_("Failed to open directory %s - %s\n"),outdir,strerror(errno));
113 exit(EXIT_FAILURE);
114 }
115 while ((direntp = readdir( dirp )) != NULL) {
116 if(strlen(direntp->d_name) > 4 || !isdigit(direntp->d_name[0]) || !isdigit(direntp->d_name[1]) ||
117 !isdigit(direntp->d_name[2]) || !isdigit(direntp->d_name[3])) continue;
118 year=atoi(direntp->d_name);
119 if (nyears>=sizeof(yearsort)/sizeof(yearsort[0])) {
120 /*
121 If too many years are listed in the directory, we ignore the earliest years. The yearsort array
122 is big enough to accomodate the most ambitious use of sarg but this safety is added to prevent
123 a crash should the directory be polluted by other entries.
124 */
125 if (year>yearsort[0]) {
126 for (i=1 ; i<nyears && year>yearsort[i] ; i++)
127 yearsort[i-1]=yearsort[i];
128 yearsort[i-1]=year;
129 }
130 } else {
131 for (i=nyears ; i>0 && year<yearsort[i-1] ; i--) {
132 yearsort[i]=yearsort[i-1];
133 }
134 yearsort[i]=year;
135 nyears++;
136 }
137 }
138 closedir( dirp );
139
140 order=(strcmp(IndexSortOrder,"A") == 0) ? 1 : -1;
141
142 if((fp_ou=fopen(yearindex,"w"))==NULL) {
143 debuga(_("(index) Cannot open file %s: %s\n"),yearindex,strerror(errno));
144 exit(EXIT_FAILURE);
145 }
146 write_html_header(fp_ou,0,ngettext("SARG report","SARG reports",nyears),HTML_JS_NONE);
147 close_html_header(fp_ou);
148 fputs("<div class=\"index\"><table cellpadding=\"1\" cellspacing=\"2\">\n",fp_ou);
149 fprintf(fp_ou,"<tr><th class=\"header_l\">%s</th>",_("YEAR"));
150 if (IndexFields & INDEXFIELDS_DIRSIZE)
151 fprintf(fp_ou,"<th class=\"header_l\">%s</th>",_("SIZE"));
152 fputs("</tr>\n",fp_ou);
153 for (y=0 ; y<nyears ; y++) {
154 if (order>0)
155 year=yearsort[y];
156 else
157 year=yearsort[nyears-1-y];
158 sprintf(yearnum,"%04d",year);
159 fprintf(fp_ou,"<tr><td class=\"data2\"><a href=\"%s/index.html\">%s</a></td>",yearnum,yearnum);
160 if (IndexFields & INDEXFIELDS_DIRSIZE)
161 fprintf(fp_ou,"<td class=\"data2\">%s</td>",get_size(outdir,yearnum));
162 fputs("</tr>\n",fp_ou);
163 sprintf(yeardir,"%s%s",outdir,yearnum);
164 // Year dir
165 nmonths=0;
166 if ((dirp2 = opendir(yeardir)) == NULL) {
167 debuga(_("Failed to open directory %s - %s\n"),yeardir,strerror(errno));
168 exit(EXIT_FAILURE);
169 }
170 while ((direntp2 = readdir( dirp2 )) != NULL) {
171 if(!isdigit(direntp2->d_name[0]) || !isdigit(direntp2->d_name[1])) continue;
172 i=-1;
173 if (sscanf(direntp2->d_name,"%d%n",&m1,&i)!=1 || m1<=0 || m1>12 || i<0) continue;
174 if (direntp2->d_name[i]=='-') {
175 if (sscanf(direntp2->d_name+i+1,"%d",&m2)!=1 || m2<m1 || m2>12) continue;
176 } else if (direntp2->d_name[i]!='\0') {
177 continue;
178 } else {
179 m2=0;
180 }
181 if (nmonths>=sizeof(monthsort)/sizeof(monthsort[0])) {
182 debuga(_("Too many month directories in %s\nSupernumerary entries are ignored\n"),yeardir);
183 break;
184 }
185 month=m1*16+m2;
186 for (i=nmonths ; i>0 && month<monthsort[i-1] ; i--) {
187 monthsort[i]=monthsort[i-1];
188 }
189 monthsort[i]=month;
190 nmonths++;
191 }
192 closedir(dirp2);
193 sprintf(monthindex,"%s/index.html",yeardir);
194 if((fp_ou2=fopen(monthindex,"w"))==NULL) {
195 debuga(_("(index) Cannot open file %s: %s\n"),monthindex,strerror(errno));
196 exit(EXIT_FAILURE);
197 }
198 snprintf(title,sizeof(title),ngettext("SARG: report for %04d","SARG: reports for %04d",nmonths),year);
199 write_html_header(fp_ou2,1,title,HTML_JS_NONE);
200 close_html_header(fp_ou2);
201 fputs("<div class=\"index\"><table cellpadding=\"1\" cellspacing=\"2\">\n<tr><td></td><td></td></tr>\n",fp_ou2);
202 fprintf(fp_ou2,"<tr><th class=\"header_l\">%s/%s</th></tr>\n",_("YEAR"),_("MONTH"));
203 for (m=0 ; m<nmonths ; m++) {
204 if (order>0)
205 month=monthsort[m];
206 else
207 month=monthsort[nmonths-1-m];
208 m1=month / 16;
209 if(month % 16 != 0) {
210 m2=month % 16;
211 sprintf(monthnum,"%02d-%02d",m1,m2);
212 sprintf(monthname1,"%02d",m1);
213 sprintf(monthname2,"%02d",m2);
214 name_month(monthname1,sizeof(monthname1));
215 name_month(monthname2,sizeof(monthname2));
216 sprintf(nmonth,"%s-%s",monthname1,monthname2);
217 } else {
218 sprintf(nmonth,"%02d",m1);
219 sprintf(monthnum,"%02d",m1);
220 name_month(nmonth,sizeof(nmonth));
221 }
222 fprintf(fp_ou2,"<tr><td class=\"data2\"><a href=\"%s/index.html\">%s %s</a></td></tr>\n",monthnum,yearnum,nmonth);
223
224 sprintf(monthdir,"%s/%s",yeardir,monthnum);
225 // month dir
226 ndays=0;
227 if ((dirp3 = opendir(monthdir)) == NULL) {
228 debuga(_("Failed to open directory %s - %s\n"),monthdir,strerror(errno));
229 exit(EXIT_FAILURE);
230 }
231 while ((direntp3 = readdir( dirp3 )) != NULL) {
232 if(!isdigit(direntp3->d_name[0]) && !isdigit(direntp3->d_name[1])) continue;
233 i=-1;
234 if (sscanf(direntp3->d_name,"%d%n",&d1,&i)!=1 || d1<=0 || d1>31 || i<0) continue;
235 if (direntp3->d_name[i]=='-') {
236 if (sscanf(direntp3->d_name+i+1,"%d",&d2)!=1 || d2<d1 || d2>31) continue;
237 } else if (direntp3->d_name[i]!='\0') {
238 continue;
239 } else {
240 d2=0;
241 }
242 if (ndays>=sizeof(daysort)/sizeof(daysort[0])) {
243 debuga(_("Too many day directories in %s\nSupernumerary entries are ignored\n"),monthdir);
244 break;
245 }
246 day=d1*32+d2;
247 for (i=ndays ; i>0 && day<daysort[i-1] ; i--) {
248 daysort[i]=daysort[i-1];
249 }
250 daysort[i]=day;
251 ndays++;
252 }
253 closedir(dirp3);
254 sprintf(dayindex,"%s/index.html",monthdir);
255 if((fp_ou3=fopen(dayindex,"w"))==NULL) {
256 debuga(_("(index) Cannot open file %s: %s\n"),dayindex,strerror(errno));
257 exit(EXIT_FAILURE);
258 }
259 snprintf(title,sizeof(title),ngettext("SARG: report for %04d/%02d","SARG: reports for %04d/%02d",ndays),year,month);
260 write_html_header(fp_ou3,2,title,HTML_JS_NONE);
261 close_html_header(fp_ou3);
262 fputs("<div class=\"index\"><table cellpadding=\"1\" cellspacing=\"2\">\n<tr><td></td><td></td></tr>\n",fp_ou3);
263 fprintf(fp_ou3,"<tr><th class=\"header_l\">%s/%s/%s</th></tr>\n",_("YEAR"),_("MONTH"),_("DAYS"));
264 for (d=0 ; d<ndays ; d++) {
265 if (order>0)
266 day=daysort[d];
267 else
268 day=daysort[ndays-1-d];
269 d1=day / 32;
270 if(day % 32 != 0) {
271 d2=day % 32;
272 sprintf(daynum,"%02d-%02d",d1,d2);
273 } else {
274 sprintf(daynum,"%02d",d1);
275 }
276 fprintf(fp_ou3,"<tr><td class=\"data2\"><a href=\"%s/index.html\">%s %s %s</a></td></tr>\n",daynum,yearnum,nmonth,daynum);
277 }
278 fputs("</table></div>\n",fp_ou3);
279 if (write_html_trailer(fp_ou3)<0)
280 debuga(_("Write error in the index %s\n"),dayindex);
281 if (fclose(fp_ou3)==EOF) {
282 debuga(_("Write error in %s: %s\n"),dayindex,strerror(errno));
283 exit(EXIT_FAILURE);
284 }
285 }
286 fputs("</table></div>\n",fp_ou2);
287 if (write_html_trailer(fp_ou2)<0)
288 debuga(_("Write error in the index %s\n"),monthindex);
289 if (fclose(fp_ou2)==EOF) {
290 debuga(_("Write error in %s: %s\n"),monthindex,strerror(errno));
291 exit(EXIT_FAILURE);
292 }
293 }
294
295 fputs("</table></div>\n",fp_ou);
296 if (write_html_trailer(fp_ou)<0)
297 debuga(_("Write error in the index %s\n"),yearindex);
298 if (fclose(fp_ou)==EOF) {
299 debuga(_("Write error in %s: %s\n"),yearindex,strerror(errno));
300 exit(EXIT_FAILURE);
301 }
302 }
303
304 static void make_file_index(void)
305 {
306 #define MAX_CREATION_DATE 15
307 FILE *fp_ou;
308 DIR *dirp;
309 struct dirent *direntp;
310 char wdir[MAXLEN];
311 char data[80];
312 char ftime[128];
313 char day[6], mon[8], year[40], hour[10];
314 long long int tbytes;
315 long long int media;
316 int iyear, imonth, iday, ihour, iminute, isecond, idst;
317 int nsort;
318 int nallocated;
319 int order;
320 int i;
321 int tuser;
322 struct getwordstruct gwarea;
323 struct sortstruct
324 {
325 int year, month, day, sortnum;
326 char creationdate[MAX_CREATION_DATE];
327 char *dirname;
328 char date[60];
329 } **sortlist, *item, **tempsort;
330
331 sprintf(wdir,"%sindex.html",outdir);
332
333 order=(strcmp(IndexSortOrder,"A") == 0) ? 1 : -1;
334
335 if ((dirp = opendir(outdir)) == NULL) {
336 debuga(_("Failed to open directory %s - %s\n"),outdir,strerror(errno));
337 exit(EXIT_FAILURE);
338 }
339
340 nsort=0;
341 nallocated=0;
342 sortlist=NULL;
343 while ((direntp = readdir( dirp )) != NULL) {
344 if (strchr(direntp->d_name,'-') == 0) continue;
345 if (obtdate(outdir,direntp->d_name,data)<0) {
346 debuga(_("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);
347 continue;
348 }
349 item=malloc(sizeof(*item));
350 if (!item) {
351 debuga(_("not enough memory to sort the index\n"));
352 exit(EXIT_FAILURE);
353 }
354 if (df=='u') {
355 item->year=atoi(direntp->d_name);
356 item->month=conv_month(direntp->d_name+4);
357 item->day=atoi(direntp->d_name+7);
358 } else {
359 item->year=atoi(direntp->d_name+5);
360 item->month=conv_month(direntp->d_name+2);
361 item->day=atoi(direntp->d_name);
362 }
363 item->sortnum=(item->year*16+item->month)*32+item->day;
364 if (sscanf(data,"%d-%d-%d %d:%d:%d %d",&iyear,&imonth,&iday,&ihour,&iminute,&isecond,&idst)==7) {
365 formatdate(data,sizeof(data),iyear,imonth,iday,ihour,iminute,isecond,idst);
366 snprintf(item->creationdate,sizeof(item->creationdate),"%04d%02d%02d%02d%02d%02d",iyear,imonth,iday,ihour,iminute,isecond);
367 } else {
368 /*
369 Old code to parse a date stored by sarg before 2.2.6.1 in the sarg-date file of each report directory.
370 */
371 getword_start(&gwarea,data);
372 if (getword_skip(16,&gwarea,' ')<0) {
373 debuga(_("Maybe you have a broken week day in your %s%s/sarg-date file\n"),outdir,direntp->d_name);
374 exit(EXIT_FAILURE);
375 }
376 if (getword_multisep(mon,sizeof(mon),&gwarea,' ')<0) {
377 debuga(_("Maybe you have a broken month in your %s%s/sarg-date file\n"),outdir,direntp->d_name);
378 exit(EXIT_FAILURE);
379 }
380 if (getword_multisep(day,sizeof(day),&gwarea,' ')<0) {
381 debuga(_("Maybe you have a broken day in your %s%s/sarg-date file\n"),outdir,direntp->d_name);
382 exit(EXIT_FAILURE);
383 }
384 if (getword_multisep(hour,sizeof(hour),&gwarea,' ')<0) {
385 debuga(_("Maybe you have a broken time in your %s%s/sarg-date file\n"),outdir,direntp->d_name);
386 exit(EXIT_FAILURE);
387 }
388 do {
389 if (getword_multisep(year,sizeof(year),&gwarea,' ')<0) {
390 debuga(_("Maybe you have a broken year in your %s%s/sarg-date file\n"),outdir,direntp->d_name);
391 exit(EXIT_FAILURE);
392 }
393 } while (year[0] && !isdigit(year[0])); //skip time zone information with spaces until the year is found
394 if (sscanf(hour,"%d:%d:%d",&ihour,&iminute,&isecond)!=3) {
395 debuga(_("Maybe you have a broken time in your %s%s/sarg-date file\n"),outdir,direntp->d_name);
396 exit(EXIT_FAILURE);
397 }
398 buildymd(day,mon,year,ftime,sizeof(ftime));
399 snprintf(item->creationdate,sizeof(item->creationdate),"%s%02d%02d%02d",ftime, ihour, iminute, isecond);
400 }
401 item->dirname=strdup(direntp->d_name);
402 if (!item->dirname) {
403 debuga(_("Not enough memory to store the directory name \"%s\" in the index\n"),direntp->d_name);
404 exit(EXIT_FAILURE);
405 }
406 safe_strcpy(item->date,data,sizeof(item->date));
407 if (nsort+1>nallocated) {
408 nallocated+=10;
409 tempsort=realloc(sortlist,nallocated*sizeof(*item));
410 if (!tempsort) {
411 debuga(_("not enough memory to sort the index\n"));
412 exit(EXIT_FAILURE);
413 }
414 sortlist=tempsort;
415 }
416 for (i=nsort ; i>0 ; i--) {
417 if (item->sortnum>sortlist[i-1]->sortnum) break;
418 if (item->sortnum==sortlist[i-1]->sortnum) {
419 if (strcmp(item->creationdate,sortlist[i-1]->creationdate)>=0) break;
420 }
421 sortlist[i]=sortlist[i-1];
422 }
423 sortlist[i]=item;
424 nsort++;
425 }
426
427 closedir( dirp );
428
429 if((fp_ou=fopen(wdir,"w"))==NULL) {
430 debuga(_("(index) Cannot open file %s: %s\n"),wdir,strerror(errno));
431 exit(EXIT_FAILURE);
432 }
433 write_html_header(fp_ou,0,ngettext("SARG report","SARG reports",nsort),HTML_JS_SORTTABLE);
434 close_html_header(fp_ou);
435 fputs("<div class=\"index\"><table cellpadding=\"1\" cellspacing=\"2\"",fp_ou);
436 if (SortTableJs[0]) fputs(" class=\"sortable\"",fp_ou);
437 fputs(">\n",fp_ou);
438 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",_("FILE/PERIOD"),_("CREATION DATE"),_("USERS"),_("BYTES"),_("AVERAGE"));
439 for (i=0 ; i<nsort ; i++) {
440 if (order>0)
441 item=sortlist[i];
442 else
443 item=sortlist[nsort-i-1];
444 tuser=obtuser(outdir,item->dirname);
445 obttotal(outdir,item->dirname,tuser,&tbytes,&media);
446 fputs("<tr><td class=\"data2\"",fp_ou);
447 if (SortTableJs[0]) fprintf(fp_ou," sorttable_customkey=\"%d\"",item->sortnum);
448 fprintf(fp_ou,"><a href='%s/%s'>%s</a></td>",item->dirname,ReplaceIndex,item->dirname);
449 fputs("<td class=\"data2\"",fp_ou);
450 if (SortTableJs[0]) fprintf(fp_ou," sorttable_customkey=\"%s\"",item->creationdate);
451 fprintf(fp_ou,">%s</td>",item->date);
452 fprintf(fp_ou,"<td class=\"data\">%d</td>",tuser);
453 fputs("<td class=\"data\"",fp_ou);
454 if (SortTableJs[0]) fprintf(fp_ou," sorttable_customkey=\"%"PRId64"\"",(int64_t)tbytes);
455 fprintf(fp_ou,">%s</td>",fixnum(tbytes,1));
456 fputs("<td class=\"data\"",fp_ou);
457 if (SortTableJs[0]) fprintf(fp_ou," sorttable_customkey=\"%"PRId64"\"",(int64_t)media);
458 fprintf(fp_ou,">%s</td></tr>\n",fixnum(media,1));
459 }
460 fputs("</table></div>\n",fp_ou);
461 if (write_html_trailer(fp_ou)<0)
462 debuga(_("Write error in the index %s\n"),wdir);
463 if (fclose(fp_ou)==EOF)
464 debuga(_("Failed to close the index file %s - %s\n"),wdir,strerror(errno));
465
466 if (sortlist) {
467 for (i=0 ; i<nsort ; i++) {
468 free(sortlist[i]->dirname);
469 free(sortlist[i]);
470 }
471 free(sortlist);
472 }
473 }
474
475 static void file_index_to_date_index(const char *entry)
476 {
477 int y1, y2, m1, m2, d1, d2;
478 int i, j;
479 int ndirlen;
480 int monthlen;
481 char sm1[8], sm2[8];
482 char olddir[MAXLEN], newdir[MAXLEN];
483
484 if(strlen(entry) < 19) return;
485
486 y1=0;
487 y2=0;
488 memset(sm1,0,sizeof(sm1));
489 memset(sm2,0,sizeof(sm2));
490 d1=0;
491 d2=0;
492 i=0;
493 if (df=='u') {
494 for (j=0 ; entry[i] && isdigit(entry[i]) ; j++)
495 y1=y1*10+(entry[i++]-'0');
496 if (j!=4) return;
497 for (j=0 ; j<sizeof(sm1)-1 && entry[i] && isalpha(entry[i]) ; j++)
498 sm1[j]=entry[i++];
499 if (j!=3) return;
500 sm1[j]='\0';
501 for (j=0 ; entry[i] && isdigit(entry[i]) ; j++)
502 d1=d1*10+(entry[i++]-'0');
503 if (j!=2) return;
504
505 if (entry[i++]!='-') return;
506
507 for (j=0 ; entry[i] && isdigit(entry[i]) ; j++)
508 y2=y2*10+(entry[i++]-'0');
509 if (j!=4) return;
510 for (j=0 ; j<sizeof(sm2)-1 && entry[i] && isalpha(entry[i]) ; j++)
511 sm2[j]=entry[i++];
512 if (j!=3) return;
513 sm2[j]='\0';
514 for (j=0 ; entry[i] && isdigit(entry[i]) ; j++)
515 d2=d2*10+(entry[i++]-'0');
516 if (j!=2) return;
517 } else if (df=='e') {
518 for (j=0 ; entry[i] && isdigit(entry[i]) ; j++)
519 d1=d1*10+(entry[i++]-'0');
520 if (j!=2) return;
521 for (j=0 ; j<sizeof(sm1)-1 && entry[i] && isalpha(entry[i]) ; j++)
522 sm1[j]=entry[i++];
523 if (j!=3) return;
524 sm1[j]='\0';
525 for (j=0 ; entry[i] && isdigit(entry[i]) ; j++)
526 y1=y1*10+(entry[i++]-'0');
527 if (j!=4) return;
528
529 if (entry[i++]!='-') return;
530
531 for (j=0 ; entry[i] && isdigit(entry[i]) ; j++)
532 d2=d2*10+(entry[i++]-'0');
533 if (j!=2) return;
534 for (j=0 ; j<sizeof(sm2)-1 && entry[i] && isalpha(entry[i]) ; j++)
535 sm2[j]=entry[i++];
536 if (j!=3) return;
537 sm2[j]='\0';
538 for (j=0 ; entry[i] && isdigit(entry[i]) ; j++)
539 y2=y2*10+(entry[i++]-'0');
540 if (j!=4) return;
541 } else
542 return;
543
544 m1=conv_month(sm1);
545 m2=conv_month(sm2);
546 ndirlen=sprintf(newdir,"%s%04d",outdir,y1);
547 if (access(newdir, R_OK) != 0) {
548 if (mkdir(newdir,0755)) {
549 debuga(_("Cannot create directory %s - %s\n"),newdir,strerror(errno));
550 exit(EXIT_FAILURE);
551 }
552 }
553 if(m1 != m2) ndirlen+=sprintf(newdir+ndirlen,"/%02d-%02d",m1,m2);
554 else ndirlen+=sprintf(newdir+ndirlen,"/%02d",m1);
555 if (access(newdir, R_OK) != 0) {
556 if (mkdir(newdir,0755)) {
557 debuga(_("Cannot create directory %s - %s\n"),newdir,strerror(errno));
558 exit(EXIT_FAILURE);
559 }
560 }
561 monthlen=ndirlen;
562 if(d1!=d2) ndirlen+=sprintf(newdir+ndirlen,"/%02d-%02d",d1,d2);
563 else ndirlen+=sprintf(newdir+ndirlen,"/%02d",d1);
564
565 sprintf(olddir,"%s%s",outdir,entry);
566 if (rename(olddir,newdir)) {
567 debuga(_("(index) rename error from \"%s\" to \"%s\" - %s\n"),olddir,newdir,strerror(errno));
568 exit(EXIT_FAILURE);
569 }
570
571 strcpy(newdir+monthlen,"/images");
572 if(access(newdir, R_OK) != 0) {
573 #ifdef HAVE_SYMLINK
574 char linkdir[MAXLEN];
575
576 sprintf(linkdir,"%simages",outdir);
577 if (symlink(linkdir,newdir)) {
578 debuga(_("failed to create link \"%s\" to \"%s\" - %s\n"),linkdir,newdir,strerror(errno));
579 exit(EXIT_FAILURE);
580 }
581 #else
582 char cmd[MAXLEN];
583 int cstatus;
584
585 sprintf(cmd,"ln -s \"%simages\" \"%s/images\"",outdir,newdir);
586 cstatus=system(cmd);
587 if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
588 debuga(_("command return status %d\n"),WEXITSTATUS(cstatus));
589 debuga(_("command: %s\n"),cmd);
590 exit(EXIT_FAILURE);
591 }
592 #endif
593 }
594 }
595
596 static void date_index_to_file_index(const char *entry)
597 {
598 int y1, next;
599 int m1, m2;
600 int d1, d2;
601 int val1len;
602 int i, j;
603 char val1[MAXLEN];
604 const char *sm1, *sm2;
605 char *str;
606 char newdir[MAXLEN], olddir[MAXLEN];
607 DIR *dirp2, *dirp3;
608 struct dirent *direntp2;
609 struct dirent *direntp3;
610
611 if(strlen(entry) != 4) return;
612
613 next=-1;
614 if (sscanf(entry,"%d%n",&y1,&next)!=1 || next<0 || entry[next]) return;
615
616 val1len=snprintf(val1,sizeof(val1),"%s%s",outdir,entry);
617 dirp2 = opendir(val1);
618 if (!dirp2) return;
619 while ((direntp2 = readdir( dirp2 )) != NULL) {
620 if(!isdigit(direntp2->d_name[0]) || !isdigit(direntp2->d_name[1])) continue;
621 i=0;
622 str=direntp2->d_name;
623 m1=0;
624 for (j=0 ; j<2 && str[i] && isdigit(str[i]) ; j++)
625 m1=(m1*10)+(str[i++]-'0');
626 if (j>=2) continue;
627 sm1=conv_month_name(m1);
628 if (str[i]=='-') {
629 i++;
630 m2=0;
631 for (j=0 ; j<2 && str[i] && isdigit(str[i]) ; j++)
632 m2=(m2*10)+(str[i++]-'0');
633 if (j>=2) continue;
634 sm2=conv_month_name(m2);
635 } else if (!str[i]) {
636 sm2=sm1;
637 } else {
638 continue;
639 }
640
641 sprintf(val1+val1len,"/%s",direntp2->d_name);
642 dirp3 = opendir(val1);
643 if (!dirp3) continue;
644 while ((direntp3 = readdir( dirp3 )) != NULL) {
645 if(!isdigit(direntp3->d_name[0]) || !isdigit(direntp3->d_name[1])) continue;
646 i=0;
647 str=direntp3->d_name;
648 d1=0;
649 for (j=0 ; str[i] && isdigit(str[i]) ; j++)
650 d1=d1*10+(str[i++]-'0');
651 if (j!=2) continue;
652 if (str[i]=='-') {
653 i++;
654 d2=0;
655 for (j=0 ; str[i] && isdigit(str[i]) ; j++)
656 d2=d2*10+(str[i++]-'0');
657 if (j!=2) continue;
658 } else if (!str[i]) {
659 d2=d1;
660 } else {
661 continue;
662 }
663
664 if (df=='u') sprintf(newdir,"%s%04d%s%02d-%04d%s%02d",outdir,y1,sm1,d1,y1,sm2,d2);
665 else if (df=='e') sprintf(newdir,"%s%02d%s%04d-%02d%s%04d",outdir,d1,sm1,y1,d2,sm2,y1);
666 else continue;
667 sprintf(olddir,"%s%04d/%s/%s",outdir,y1,direntp2->d_name,direntp3->d_name);
668 if(rename(olddir,newdir)) {
669 debuga(_("(index) rename error from \"%s\" to \"%s\" - %s\n"),olddir,newdir,strerror(errno));
670 exit(EXIT_FAILURE);
671 }
672 }
673 closedir( dirp3 );
674 }
675 closedir( dirp2 );
676
677 /*!
678 \bug The links to the images in the reports are broken after moving the directories
679 as the the HTML files are not at the right level for the images any more.
680 */
681 }
682