]> git.ipfire.org Git - thirdparty/sarg.git/blob - util.c
Change year source files's header
[thirdparty/sarg.git] / util.c
1 /*
2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
3 * 1998, 2011
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 // #define LEGACY_MY_ATOLL
28 // #define LEGACY_TESTVALIDUSERCHAR
29
30 #include "include/conf.h"
31 #include "include/defs.h"
32
33 #if defined(HAVE_BACKTRACE)
34 #define USE_GETWORD_BACKTRACE 1
35 #else
36 #define USE_GETWORD_BACKTRACE 0
37 #endif
38
39 static char mtab1[12][4]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
40
41 //! The list of the HTTP codes to exclude from the report.
42 static char *excludecode=NULL;
43
44 #if USE_GETWORD_BACKTRACE
45 static void getword_backtrace(void)
46 {
47 void *buffer[5];
48 int i, n;
49 char **calls;
50
51 n=backtrace(buffer,sizeof(buffer)/sizeof(buffer[0]));
52 if (n<=0) return;
53 calls=backtrace_symbols(buffer,n);
54 if (calls) {
55 debuga(_("getword backtrace:\n"));
56 for (i=0 ; i<n ; i++) {
57 fprintf(stderr,"SARG: %d:%s\n",i+1,calls[i]);
58 }
59 free(calls);
60 }
61 }
62 #endif //USE_GETWORD_BACKTRACE
63
64 void getword_start(struct getwordstruct *gwarea, const char *line)
65 {
66 gwarea->beginning=line;
67 gwarea->current=line;
68 gwarea->modified=0;
69 }
70
71 void getword_restart(struct getwordstruct *gwarea)
72 {
73 if (gwarea->modified) {
74 debuga(_("Cannot parse again the line as it was modified\n"));
75 exit(EXIT_FAILURE);
76 }
77 gwarea->current=gwarea->beginning;
78 }
79
80 int getword(char *word, int limit, struct getwordstruct *gwarea, char stop)
81 {
82 int x;
83
84 for(x=0;((gwarea->current[x]) && (gwarea->current[x] != stop ));x++) {
85 if(x>=limit) {
86 printf("SARG: getword loop detected after %d bytes.\n",x);
87 printf("SARG: Line=\"%s\"\n",gwarea->beginning);
88 printf("SARG: Record=\"%s\"\n",gwarea->current);
89 printf("SARG: searching for \'x%x\'\n",stop);
90 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
91 word[(limit>0) ? limit-1 : 0]='\0';
92 #if USE_GETWORD_BACKTRACE
93 getword_backtrace();
94 #endif
95 return(-1);
96 }
97 word[x] = gwarea->current[x];
98 }
99
100 word[x] = '\0';
101 if (gwarea->current[x]) ++x;
102 gwarea->current+=x;
103 return(0);
104 }
105
106 int getword_limit(char *word, int limit, struct getwordstruct *gwarea, char stop)
107 {
108 int x;
109
110 limit--;
111 for(x=0; x<limit && gwarea->current[x] && gwarea->current[x] != stop ;x++) {
112 word[x] = gwarea->current[x];
113 }
114 word[x] = '\0';
115 gwarea->current+=x;
116 while (*gwarea->current && *gwarea->current != stop) gwarea->current++;
117 if (*gwarea->current) ++gwarea->current;
118 return(0);
119 }
120
121 int getword_multisep(char *word, int limit, struct getwordstruct *gwarea, char stop)
122 {
123 int x;
124
125 for(x=0;((gwarea->current[x]) && (gwarea->current[x] != stop ));x++) {
126 if(x>=limit) {
127 printf("SARG: getword_multisep loop detected.\n");
128 printf("SARG: Line=\"%s\"\n",gwarea->beginning);
129 printf("SARG: Record=\"%s\"\n",gwarea->current);
130 printf("SARG: searching for \'x%x\'\n",stop);
131 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
132 if (limit>0) word[limit-1]='\0';
133 #if USE_GETWORD_BACKTRACE
134 getword_backtrace();
135 #endif
136 //exit(EXIT_FAILURE);
137 return(-1);
138 }
139 word[x] = gwarea->current[x];
140 }
141
142 word[x] = '\0';
143 while (gwarea->current[x] && gwarea->current[x]==stop) ++x;
144 gwarea->current+=x;
145 return(0);
146 }
147
148 int getword_skip(int limit, struct getwordstruct *gwarea, char stop)
149 {
150 int x;
151
152 for(x=0;(gwarea->current[x] && (gwarea->current[x] != stop ));x++) {
153 if(x>=limit) {
154 printf("SARG: getword_skip loop detected after %d bytes.\n",x);
155 printf("SARG: Line=\"%s\"\n",gwarea->beginning);
156 printf("SARG: Record=\"%s\"\n",gwarea->current);
157 printf("SARG: searching for \'x%x\'\n",stop);
158 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
159 #if USE_GETWORD_BACKTRACE
160 getword_backtrace();
161 #endif
162 return(-1);
163 }
164 }
165
166 if (gwarea->current[x]) ++x;
167 gwarea->current+=x;
168 return(0);
169 }
170
171 int getword_atoll(long long int *number, struct getwordstruct *gwarea, char stop)
172 {
173 int x;
174 int sign=+1;
175
176 if (gwarea->current[0] == '-') {
177 gwarea->current++;
178 sign=-1;
179 } else if (gwarea->current[0] == '+') {
180 gwarea->current++;
181 }
182 *number=0LL;
183 for(x=0;isdigit(gwarea->current[x]);x++) {
184 *number=(*number * 10) + gwarea->current[x]-'0';
185 }
186 if(gwarea->current[x] && gwarea->current[x]!=stop) {
187 printf("SARG: getword_atoll loop detected after %d bytes.\n",x);
188 printf("SARG: Line=\"%s\"\n",gwarea->beginning);
189 printf("SARG: Record=\"%s\"\n",gwarea->current);
190 printf("SARG: searching for \'x%x\'\n",stop);
191 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
192 #if USE_GETWORD_BACKTRACE
193 getword_backtrace();
194 #endif
195 return(-1);
196 }
197 *number*=sign;
198
199 if (gwarea->current[x]) ++x;
200 gwarea->current+=x;
201 return(0);
202 }
203
204
205 int getword_ptr(char *orig_line,char **word, struct getwordstruct *gwarea, char stop)
206 {
207 /*!
208 \note Why pass the original buffer to the function ? Because we must modify it to
209 insert the terminating ASCII zero for the word we return and that's not compatible
210 with getword_restart(). Moreover, getword_start() sometime works on constant strings
211 so this function require the original buffer to detect any missuse.
212 */
213 int x;
214 int sep;
215 int start;
216
217 if (orig_line && orig_line!=gwarea->beginning) {
218 debuga(_("Invalid buffer passed to getword_ptr\n"));
219 return(-1);
220 }
221
222 start=(gwarea->current-gwarea->beginning);
223 if (word && orig_line) *word=orig_line+start;
224 for(x=0;((gwarea->current[x]) && (gwarea->current[x] != stop ));x++);
225 sep=(gwarea->current[x]!='\0');
226 if (word && orig_line) orig_line[start+x] = '\0';
227 if (sep) ++x;
228 gwarea->current+=x;
229 gwarea->modified=1;
230 return(0);
231 }
232
233 #define MAXLLL 30 //!< Maximum number of digits in long long (a guess).
234 long long int my_atoll (const char *nptr)
235 {
236 long long int returnval=0LL;
237 int max_digits = MAXLLL ;
238
239 // Soak up all the white space
240 while (isspace( *nptr )) {
241 nptr++;
242 }
243
244 //For each character left to right
245 //change the character to a single digit
246 //multiply what we had before by 10 and add the new digit
247
248 while (--max_digits && isdigit( *nptr ))
249 {
250 returnval = ( returnval * 10 ) + ( *nptr++ - '0' ) ;
251 }
252
253 return returnval;
254 }
255
256 int is_absolute(const char *path)
257 {
258 if (*path=='/') return(1);
259 #ifdef WINDOWS
260 if (isalpha(path[0]) && path[1]==':') return(1);
261 #endif
262 return(0);
263 }
264
265 void my_mkdir(const char *name)
266 {
267 char w0[MAXLEN];
268 int i;
269 int chars;
270
271 if(!is_absolute(name)) {
272 debuga(_("Invalid path (%s). Please, use absolute paths only.\n"),name);
273 debuga(_("process aborted.\n"));
274 exit(EXIT_FAILURE);
275 }
276
277 chars=0;
278 for (i=0 ; name[i] ; i++) {
279 if (i>=sizeof(w0)) {
280 debuga(_("directory name too long: %s\n"),name);
281 exit(EXIT_FAILURE);
282 }
283 if (chars>0 && name[i] == '/') {
284 w0[i] = '\0';
285 if (access(w0, R_OK) != 0) {
286 if (mkdir(w0,0755)) {
287 debuga(_("Cannot create directory %s - %s\n"),w0,strerror(errno));
288 debuga(_("process aborted.\n"));
289 exit(EXIT_FAILURE);
290 }
291 }
292 }
293 if (name[i] != '/') chars++;
294 w0[i] = name[i];
295 }
296
297 if (access(name, R_OK) != 0) {
298 if (mkdir(name,0755)) {
299 debuga(_("Cannot create directory %s - %s\n"),name,strerror(errno));
300 debuga(_("process aborted.\n"));
301 exit(EXIT_FAILURE);
302 }
303 }
304 }
305
306
307 void my_lltoa(unsigned long long int n, char *s, int ssize, int len)
308 {
309 int i;
310 int slen = 0;
311 int j;
312 char c;
313
314 ssize--;
315 if (len>ssize) {
316 debuga(_("The requested number of digits passed to my_lltoa (%d) is bigger than the output buffer size (%d)\n"),len,ssize);
317 abort();
318 }
319
320 do {
321 s[slen++] = (n % 10) + '0';
322 } while ((n /= 10) > 0 && slen<ssize);
323 s[slen] = '\0';
324
325 for (i = 0, j = slen-1; i<j; i++, j--) {
326 c = s[i];
327 s[i] = s[j];
328 s[j] = c;
329 }
330
331 if(len>slen) {
332 i=len-slen;
333 for(j=slen; j>=0; j--)
334 s[j+i]=s[j];
335 for(j=0 ; j<i ; j++)
336 s[j]='0';
337 }
338 }
339
340 int month2num(const char *month)
341 {
342 int m;
343
344 for(m=0 ; m<12 && strcmp(mtab1[m],month) != 0; m++);
345 return(m);
346 }
347
348 int builddia(int day, int month, int year)
349 {
350 return(year*10000+month*100+day);
351 }
352
353
354 void buildymd(const char *dia, const char *mes, const char *ano, char *wdata)
355 {
356 int nmes;
357
358 nmes=month2num(mes);
359 sprintf(wdata,"%04d%02d%02d",atoi(ano),nmes+1,atoi(dia));
360 }
361
362
363 int conv_month(const char *month)
364 {
365 int x;
366
367 for(x=0; x<12 && strncmp(mtab1[x],month,3)!=0; x++);
368 return(x+1);
369 }
370
371
372 const char *conv_month_name(int month)
373 {
374 static char str[4];
375
376 if (month<1 || month>12) {
377 snprintf(str,sizeof(str),"%03d",month);
378 return(str);
379 }
380 return(mtab1[month-1]);
381 }
382
383
384 void name_month(char *month,int month_len)
385 {
386 int x, z=atoi(month)-1;
387 char m[255];
388 char w[20];
389 struct getwordstruct gwarea;
390
391 strcpy(m,_("January,February,March,April,May,June,July,August,September,October,November,December"));
392 getword_start(&gwarea,m);
393
394 for(x=0; x<z; x++)
395 if (getword_multisep(w,sizeof(w),&gwarea,',')<0) {
396 printf("SARG: Maybe you have a broken record or garbage in the names of the months.\n");
397 exit(EXIT_FAILURE);
398 }
399 if (getword_multisep(month,month_len,&gwarea,',')<0) {
400 printf("SARG: Maybe you have a broken record or garbage in the name of the months.\n");
401 exit(EXIT_FAILURE);
402 }
403 }
404
405
406 void debuga(const char *msg,...)
407 {
408 va_list ap;
409
410 fputs(_("SARG: "),stderr);
411 va_start(ap,msg);
412 vfprintf(stderr,msg,ap);
413 va_end(ap);
414 }
415
416
417 void debugaz(const char *head, const char *msg)
418 {
419 fprintf(stderr, "SARG: (util) %s=%s\n",head, msg);
420 }
421
422
423 char *fixnum(long long int value, int n)
424 {
425 #define MAXLEN_FIXNUM 256
426 char num[MAXLEN_FIXNUM]="";
427 char buf[MAXLEN_FIXNUM * 2];
428 char *pbuf;
429 static char ret[MAXLEN_FIXNUM * 2];
430 char *pret;
431 register int i, j, k;
432 int numlen;
433 static char abbrev[30];
434
435 my_lltoa(value, num, sizeof(num), 0);
436
437 if(DisplayedValues==DISPLAY_ABBREV) {
438 numlen = strlen(num);
439 if(numlen <= 3)
440 sprintf(abbrev,"%s",num);
441 if(numlen == 4 || numlen == 7 || numlen == 10 || numlen == 13) {
442 snprintf(abbrev,2,"%s",num);
443 strncat(abbrev,".",1);
444 strncat(abbrev,num+1,2);
445 if(!n) return(abbrev);
446 if(numlen == 4)
447 strncat(abbrev,"K",1);
448 else if(numlen == 7)
449 strncat(abbrev,"M",1);
450 else if(numlen == 10)
451 strncat(abbrev,"G",1);
452 else if(numlen == 13)
453 strncat(abbrev,"T",1);
454 }
455 if(numlen == 5 || numlen == 8 || numlen == 11 || numlen == 14) {
456 snprintf(abbrev,3,"%s",num);
457 strncat(abbrev,".",1);
458 strncat(abbrev,num+2,2);
459 if(!n) return(abbrev);
460 if(numlen == 5)
461 strncat(abbrev,"K",1);
462 else if(numlen == 8)
463 strncat(abbrev,"M",1);
464 else if(numlen == 11)
465 strncat(abbrev,"G",1);
466 else if(numlen == 14)
467 strncat(abbrev,"T",1);
468 }
469 if(numlen == 6 || numlen == 9 || numlen == 12 || numlen == 15) {
470 snprintf(abbrev,4,"%s",num);
471 strncat(abbrev,".",1);
472 strncat(abbrev,num+3,2);
473 if(!n) return(abbrev);
474 if(numlen == 6)
475 strncat(abbrev,"K",1);
476 else if(numlen == 9)
477 strncat(abbrev,"M",1);
478 else if(numlen == 12)
479 strncat(abbrev,"G",1);
480 else if(numlen == 15)
481 strncat(abbrev,"T",1);
482 }
483
484 return(abbrev);
485 }
486
487 bzero(buf, MAXLEN_FIXNUM*2);
488
489 pbuf = buf;
490 pret = ret;
491 k = 0;
492
493 for ( i = strlen(num) - 1, j = 0 ; i > -1; i--) {
494 if ( k == 2 && i != 0 ) {
495 k = 0;
496 pbuf[j++] = num[i];
497 pbuf[j++] = (UseComma) ? ',' : '.';
498 continue;
499 }
500 pbuf[j] = num[i];
501 j++;
502 k++;
503 }
504
505 pret[0]='\0';
506
507 for ( i = strlen(pbuf) - 1, j = 0 ; i > -1; i--, j++)
508 pret[j] = pbuf[i];
509
510 pret[j] = '\0';
511
512 return pret;
513 }
514
515
516 char *fixnum2(long long int value, int n)
517 {
518 #define MAXLEN_FIXNUM2 1024
519 char num[MAXLEN_FIXNUM2];
520 char buf[MAXLEN_FIXNUM2 * 2];
521 char *pbuf;
522 static char ret[MAXLEN_FIXNUM2 * 2];
523 char *pret;
524 register int i, j, k;
525
526 my_lltoa(value, num, sizeof(num), 0);
527 bzero(buf, MAXLEN_FIXNUM2*2);
528
529 pbuf = buf;
530 pret = ret;
531 k = 0;
532
533 for ( i = strlen(num) - 1, j = 0 ; i > -1; i--) {
534 if ( k == 2 && i != 0 ) {
535 k = 0;
536 pbuf[j++] = num[i];
537 pbuf[j++] = (UseComma) ? ',' : '.';
538 continue;
539 }
540 pbuf[j] = num[i];
541 j++;
542 k++;
543 }
544
545 pret[0]='\0';
546
547 for ( i = strlen(pbuf) - 1, j = 0 ; i > -1; i--, j++)
548 pret[j] = pbuf[i];
549
550 pret[j] = '\0';
551
552 return pret;
553 }
554
555
556 char *buildtime(long long int elap)
557 {
558 int num = elap / 1000;
559 int hor = 0;
560 int min = 0;
561 int sec = 0;
562 static char buf[12];
563
564 buf[0]='\0';
565
566 hor=num / 3600;
567 min=(num % 3600) / 60;
568 sec=num % 60;
569 sprintf(buf,"%02d:%02d:%02d",hor,min,sec);
570
571 return(buf);
572 }
573
574
575 void obtdate(const char *dirname, const char *name, char *data)
576 {
577 FILE *fp_in;
578 char wdir[MAXLEN];
579
580 sprintf(wdir,"%s%s/sarg-date",dirname,name);
581 if ((fp_in = fopen(wdir, "rt")) == 0) {
582 sprintf(wdir,"%s%s/date",dirname,name);
583 if ((fp_in = fopen(wdir, "rt")) == 0) {
584 data[0]='\0';
585 return;
586 }
587 }
588
589 if (!fgets(data,80,fp_in)) {
590 debuga(_("Failed to read the date in %s\n"),wdir);
591 exit(EXIT_FAILURE);
592 }
593 fclose(fp_in);
594 fixendofline(data);
595
596 return;
597 }
598
599
600 void formatdate(char *date,int date_size,int year,int month,int day,int hour,int minute,int second,int dst)
601 {
602 struct tm ltm;
603 time_t unixtime;
604 struct tm *fulltm;
605
606 memset(&ltm,0,sizeof(ltm));
607 if (year>=1900) ltm.tm_year=year-1900;
608 if (month>=1 && month<=12) ltm.tm_mon=month-1;
609 if (day>=1 && day<=31) ltm.tm_mday=day;
610 if (hour>=0 && hour<24) ltm.tm_hour=hour;
611 if (minute>=0 && minute<60) ltm.tm_min=minute;
612 if (second>=0 && second<60) ltm.tm_sec=second;
613 ltm.tm_isdst=dst;
614 unixtime=mktime(&ltm); //fill the missing entries
615 fulltm=localtime(&unixtime);
616 //strftime(date,date_size,"%a %b %d %H:%M:%S %Z %Y",fulltm);
617 strftime(date,date_size,"%c",fulltm);
618 }
619
620
621 void computedate(int year,int month,int day,struct tm *t)
622 {
623 memset(t,0,sizeof(*t));
624 t->tm_year=year-1900;
625 t->tm_mon=month-1;
626 t->tm_mday=day;
627 }
628
629
630 int obtuser(const char *dirname, const char *name)
631 {
632 FILE *fp_in;
633 char wdir[MAXLEN];
634 char tuser[20];
635 int nuser;
636
637 sprintf(wdir,"%s%s/sarg-users",dirname,name);
638 if((fp_in=fopen(wdir,"r"))==NULL) {
639 sprintf(wdir,"%s%s/users",dirname,name);
640 if((fp_in=fopen(wdir,"r"))==NULL) {
641 return(0);
642 }
643 }
644
645 if (!fgets(tuser,sizeof(tuser),fp_in)) {
646 debuga(_("Failed to read the number of users in %s\n"),wdir);
647 exit(EXIT_FAILURE);
648 }
649 fclose(fp_in);
650 nuser=atoi(tuser);
651
652 return(nuser);
653 }
654
655
656 void obttotal(const char *dirname, const char *name, int nuser, long long int *tbytes, long long int *media)
657 {
658 FILE *fp_in;
659 char *buf;
660 char wdir[MAXLEN];
661 char user[MAX_USER_LEN];
662 char sep;
663 struct getwordstruct gwarea;
664 longline line;
665
666 *tbytes=0;
667 *media=0;
668
669 sprintf(wdir,"%s%s/sarg-general",dirname,name);
670 if ((fp_in = fopen(wdir, "r")) == 0) {
671 sprintf(wdir,"%s%s/general",dirname,name);
672 if ((fp_in = fopen(wdir, "r")) == 0) {
673 return;
674 }
675 }
676
677 if ((line=longline_create())==NULL) {
678 debuga(_("Not enough memory to read the file %s\n"),wdir);
679 exit(EXIT_FAILURE);
680 }
681
682 while((buf=longline_read(fp_in,line))!=NULL) {
683 if (strncmp(buf,"TOTAL\t",6) == 0)
684 sep='\t'; //new file
685 else if (strncmp(buf,"TOTAL ",6) == 0)
686 sep=' '; //old file
687 else
688 continue;
689 getword_start(&gwarea,buf);
690 if (getword(user,sizeof(user),&gwarea,sep)<0) {
691 debuga(_("There is a invalid user in file %s\n"),wdir);
692 exit(EXIT_FAILURE);
693 }
694 if(strcmp(user,"TOTAL") != 0)
695 continue;
696 if (getword_skip(MAXLEN,&gwarea,sep)<0) {
697 debuga(_("There a broken total number of access in file %s\n"),wdir);
698 exit(EXIT_FAILURE);
699 }
700 if (getword_atoll(tbytes,&gwarea,sep)<0) {
701 debuga(_("There is a broken number of bytes in file %s\n"),wdir);
702 exit(EXIT_FAILURE);
703 }
704 break;
705 }
706 fclose(fp_in);
707 longline_destroy(&line);
708
709 if (nuser <= 0)
710 return;
711
712 *media=*tbytes / nuser;
713 return;
714 }
715
716 int getperiod_fromsarglog(const char *arqtt,struct periodstruct *period)
717 {
718 const char *str;
719 int day0, month0, year0, hour0, minute0;
720 int day1, month1, year1, hour1, minute1;
721 int i;
722
723 memset(period,0,sizeof(*period));
724
725 str=arqtt;
726 while((str=strstr(str,"sarg-"))!=NULL) {
727 str+=5;
728 if (!isdigit(str[0]) || !isdigit(str[1])) continue;
729 day0=(str[0]-'0')*10+(str[1]-'0');
730 if (day0<1 || day0>31) continue;
731 str+=2;
732 month0=(str[0]-'0')*10+(str[1]-'0')-1;
733 if (month0<0 || month0>11) continue;
734 str+=2;
735 year0=0;
736 for (i=0 ; isdigit(str[i]) && i<4 ; i++) year0=year0*10+(str[i]-'0');
737 if (i!=4) continue;
738 str+=4;
739 if (str[0]!='_') continue;
740 str++;
741
742 if (!isdigit(str[0]) || !isdigit(str[1])) continue;
743 hour0=(str[0]-'0')*10+(str[1]-'0');
744 str+=2;
745 if (!isdigit(str[0]) || !isdigit(str[1])) continue;
746 minute0=(str[0]-'0')*10+(str[1]-'0');
747 str+=2;
748
749 if (*str != '-') continue;
750 str++;
751
752 if (!isdigit(str[0]) || !isdigit(str[1])) continue;
753 day1=(str[0]-'0')*10+(str[1]-'0');
754 if (day1<1 || day1>31) continue;
755 str+=2;
756 month1=(str[0]-'0')*10+(str[1]-'0')-1;
757 if (month1<0 || month1>11) continue;
758 str+=2;
759 year1=0;
760 for (i=0 ; isdigit(str[i]) && i<4 ; i++) year1=year1*10+(str[i]-'0');
761 if (i!=4) continue;
762 str+=4;
763
764 if (str[0]!='_') continue;
765 str++;
766
767 if (!isdigit(str[0]) || !isdigit(str[1])) continue;
768 hour1=(str[0]-'0')*10+(str[1]-'0');
769 str+=2;
770 if (!isdigit(str[0]) || !isdigit(str[1])) continue;
771 minute1=(str[0]-'0')*10+(str[1]-'0');
772 str+=2;
773
774 period->start.tm_mday=day0;
775 period->start.tm_mon=month0;
776 period->start.tm_year=year0-1900;
777 period->start.tm_hour=hour0;
778 period->start.tm_min=minute0;
779 period->end.tm_mday=day1;
780 period->end.tm_mon=month1;
781 period->end.tm_year=year1-1900;
782 period->end.tm_hour=hour1;
783 period->end.tm_min=minute1;
784 return(0);
785 }
786 return(-1);
787 }
788
789 void getperiod_fromrange(struct periodstruct *period,int dfrom,int duntil)
790 {
791 memset(&period->start,0,sizeof(period->start));
792 period->start.tm_mday=dfrom%100;
793 period->start.tm_mon=(dfrom/100)%100-1;
794 period->start.tm_year=(dfrom/10000)-1900;
795
796 memset(&period->end,0,sizeof(period->end));
797 period->end.tm_mday=duntil%100;
798 period->end.tm_mon=(duntil/100)%100-1;
799 period->end.tm_year=(duntil/10000)-1900;
800 }
801
802 int getperiod_buildtext(struct periodstruct *period)
803 {
804 int i;
805 int range;
806 char text1[40], text2[40];
807
808 if(df[0]=='u') {
809 i=strftime(text1, sizeof(text1), "%Y %b %d", &period->start);
810 }else if(df[0]=='e') {
811 i=strftime(text1, sizeof(text1), "%d %b %Y", &period->start);
812 } else /*if(df[0]=='w')*/ {
813 IndexTree=INDEX_TREE_FILE;
814 i=strftime(text1, sizeof(text1), "%Y.%U", &period->start);
815 }
816 if (i == 0) return(-1);
817
818 range=(period->start.tm_year!=period->end.tm_year ||
819 period->start.tm_mon!=period->end.tm_mon ||
820 period->start.tm_mday!=period->end.tm_mday);
821 if (range) {
822 if(df[0]=='u') {
823 i=strftime(text2, sizeof(text2)-i, "%Y %b %d", &period->end);
824 } else if(df[0]=='e') {
825 i=strftime(text2, sizeof(text2)-i, "%d %b %Y", &period->end);
826 } else {
827 i=strftime(text2, sizeof(text2)-i, "%Y.%U", &period->end);
828 }
829 if (i == 0) return(-1);
830 }
831
832 if (range) {
833 snprintf(period->text,sizeof(period->text),"%s-%s",text1,text2);
834 snprintf(period->html,sizeof(period->html),"%s&mdash;%s",text1,text2);
835 } else {
836 strncpy(period->text,text1,sizeof(period->text)-1);
837 period->text[sizeof(period->text)-1]='\0';
838 strncpy(period->html,text1,sizeof(period->html)-1);
839 period->html[sizeof(period->html)-1]='\0';
840 }
841 return(0);
842 }
843
844 static void copy_images(void)
845 {
846 FILE *img_in, *img_ou;
847 char images[512];
848 char imgdir[MAXLEN];
849 char srcfile[MAXLEN];
850 char dstfile[MAXLEN];
851 DIR *dirp;
852 struct dirent *direntp;
853 char buffer[MAXLEN];
854 size_t nread;
855 struct stat info;
856
857 if (snprintf(images,sizeof(images),"%simages",outdir)>=sizeof(images)) {
858 debuga(_("Cannot copy images to target directory %simages\n"),outdir);
859 exit(EXIT_FAILURE);
860 }
861 if (access(images,R_OK)!=0) {
862 if (mkdir(images,0755)) {
863 debuga(_("Cannot create directory %s - %s\n"),images,strerror(errno));
864 exit(EXIT_FAILURE);
865 }
866 }
867
868 strcpy(imgdir,IMAGEDIR);
869 dirp = opendir(imgdir);
870 if(dirp==NULL) {
871 debuga(_("(util) Can't open directory %s: %s\n"),imgdir,strerror(errno));
872 return;
873 }
874 while ((direntp = readdir( dirp )) != NULL ){
875 if(direntp->d_name[0]=='.')
876 continue;
877 sprintf(srcfile,"%s/%s",imgdir,direntp->d_name);
878 if (stat(srcfile,&info)) {
879 debuga(_("Cannot stat \"%s\" - %s\n"),srcfile,strerror(errno));
880 continue;
881 }
882 if (S_ISREG(info.st_mode)) {
883 sprintf(dstfile,"%s/%s",images,direntp->d_name);
884 img_in = fopen(srcfile, "rb");
885 if(img_in!=NULL) {
886 img_ou = fopen(dstfile, "wb");
887 if(img_ou!=NULL) {
888 while ((nread = fread(buffer,1,sizeof(buffer),img_in))>0) {
889 if (fwrite(buffer,1,nread,img_ou)!=nread) {
890 debuga(_("Failed to copy image %s to %s\n"),srcfile,dstfile);
891 break;
892 }
893 }
894 fclose(img_ou);
895 } else
896 fprintf(stderr,"SARG: (util): %s %s: %s\n", _("Cannot open file")?_("Cannot open file"):"Can't open/create file", dstfile, strerror(errno));
897 fclose(img_in);
898 } else
899 fprintf(stderr,"SARG: (util): %s %s: %s\n", _("Cannot open file")?_("Cannot open file"):"Can't open file", srcfile, strerror(errno));
900 }
901 }
902 (void) closedir(dirp);
903
904 return;
905 }
906
907 int vrfydir(const struct periodstruct *per1, const char *addr, const char *site, const char *us, const char *form)
908 {
909 FILE *fp_ou;
910 int num=1, count=0;
911 char wdir[MAXLEN];
912 char dirname2[MAXLEN];
913 int y1, y2;
914 int m1, m2;
915 int d1, d2;
916 int wlen, wlen2;
917 time_t curtime;
918 struct tm *loctm;
919
920 strcpy(wdir,outdir);
921 wlen=strlen(wdir);
922 y1=per1->start.tm_year+1900;
923 y2=per1->end.tm_year+1900;
924 m1=per1->start.tm_mon+1;
925 m2=per1->end.tm_mon+1;
926 d1=per1->start.tm_mday;
927 d2=per1->end.tm_mday;
928 if(IndexTree == INDEX_TREE_DATE) {
929 wlen+=sprintf(wdir+wlen,"%04d",y1);
930 if(y1!=y2) wlen+=sprintf(wdir+wlen,"-%04d",y2);
931 if(access(wdir, R_OK) != 0)
932 my_mkdir(wdir);
933
934 wlen+=sprintf(wdir+wlen,"/%02d",m1);
935 if(m1 != m2) wlen+=sprintf(wdir+wlen,"-%02d",m2);
936 if(access(wdir, R_OK) != 0)
937 my_mkdir(wdir);
938
939 wlen+=sprintf(wdir+wlen,"/%02d",d1);
940 if(d1!=d2) wlen+=sprintf(wdir+wlen,"-%02d",d2);
941 } else {
942 if(df[0] == 'u') {
943 wlen=snprintf(wdir+wlen,sizeof(wdir)-wlen,"%04d%s%02d-%04d%s%02d",y1,
944 conv_month_name(m1),d1,y2,conv_month_name(m2),d2);
945 } else if(df[0] == 'e') {
946 wlen=snprintf(wdir+wlen,sizeof(wdir)-wlen,"%02d%s%04d-%02d%s%04d",d1,
947 conv_month_name(m1),y1,d2,conv_month_name(m2),y2);
948 } else if(df[0] == 'w') {
949 wlen2=strftime(wdir+wlen, sizeof(wdir)-wlen, "%Y.%U", &per1->start);
950 if (wlen2==0) return(-1);
951 wlen+=wlen2;
952 }
953 }
954
955 if(us[0] != '\0') {
956 struct userinfostruct *uinfo=userinfo_find_from_id(us);
957 if (uinfo) {
958 strcat(wdir,"-");
959 strcat(wdir,uinfo->filename);
960 }
961 }
962 if(addr[0] != '\0') {
963 strcat(wdir,"-");
964 strcat(wdir,addr);
965 }
966 if(site[0] != '\0') {
967 strcat(wdir,"-");
968 strcat(wdir,site);
969 }
970
971 strcpy(outdirname,wdir);
972
973 if(IndexTree != INDEX_TREE_DATE) {
974 if(!OverwriteReport) {
975 while(num) {
976 if(access(wdir,R_OK) == 0) {
977 sprintf(wdir,"%s.%d",outdirname,num);
978 num++;
979 count++;
980 } else
981 break;
982 }
983
984 if(count > 0) {
985 if(debug)
986 debuga(_("File %s already exists, moved to %s\n"),outdirname,wdir);
987 rename(outdirname,wdir);
988 }
989 } else {
990 if(access(outdirname,R_OK) == 0) {
991 unlinkdir(outdirname,1);
992 }
993 }
994 my_mkdir(outdirname);
995 } else {
996 strcpy(dirname2,wdir);
997 if(!OverwriteReport) {
998 while(num) {
999 if(access(wdir,R_OK) == 0) {
1000 sprintf(wdir,"%s.%d",dirname2,num);
1001 num++;
1002 count++;
1003 } else
1004 break;
1005 }
1006
1007 if(count > 0) {
1008 if(debug)
1009 debuga(_("File %s already exists, moved to %s\n"),dirname2,wdir);
1010 rename(dirname2,wdir);
1011 strcpy(dirname2,wdir);
1012 }
1013 } else {
1014 if(access(wdir,R_OK) == 0) {
1015 unlinkdir(wdir,1);
1016 }
1017 }
1018
1019 if(access(wdir, R_OK) != 0)
1020 my_mkdir(wdir);
1021 }
1022
1023 strcpy(dirname2,wdir);
1024
1025 sprintf(wdir,"%s/sarg-date",outdirname);
1026 if ((fp_ou = fopen(wdir, "wt")) == 0) {
1027 debuga(_("cannot open %s for writing\n"),wdir);
1028 perror("SARG:");
1029 exit(EXIT_FAILURE);
1030 }
1031 time(&curtime);
1032 //strftime(wdir,sizeof(wdir),"%a %b %d %H:%M:%S %Z %Y",localtime(&curtime));
1033 loctm=localtime(&curtime);
1034 strftime(wdir,sizeof(wdir),"%Y-%m-%d %H:%M:%S",loctm);
1035 if (fprintf(fp_ou,"%s %d\n",wdir,loctm->tm_isdst)<0) {
1036 debuga(_("Failed to write the date in %s\n"),wdir);
1037 perror("SARG:");
1038 exit(EXIT_FAILURE);
1039 }
1040 if (fclose(fp_ou)==EOF) {
1041 debuga(_("Failed to write the date in %s\n"),wdir);
1042 perror("SARG:");
1043 exit(EXIT_FAILURE);
1044 }
1045
1046 copy_images();
1047 return(0);
1048 }
1049
1050 void strip_latin(char *line)
1051 {
1052 int i,j;
1053 int skip;
1054
1055 j=0;
1056 skip=0;
1057 for (i=0;line[i];i++){
1058 if (skip){
1059 if (line[i]==';') skip=0;
1060 } else {
1061 if (line[i]=='&')
1062 skip=1;
1063 else
1064 line[j++]=line[i];
1065 }
1066 }
1067 line[j]='\0';
1068 return;
1069 }
1070
1071 void zdate(char *ftime,int ftimesize, const char *DateFormat)
1072 {
1073 time_t t;
1074 struct tm *local;
1075
1076 t = time(NULL);
1077 local = localtime(&t);
1078 if(strcmp(DateFormat,"u") == 0)
1079 strftime(ftime, ftimesize, "%b/%d/%Y %H:%M", local);
1080 if(strcmp(DateFormat,"e") == 0)
1081 strftime(ftime, ftimesize, "%d/%b/%Y-%H:%M", local);
1082 if(strcmp(DateFormat,"w") == 0)
1083 strftime(ftime, ftimesize, "%W-%H-%M", local);
1084 return;
1085 }
1086
1087
1088 char *fixtime(long long int elap)
1089 {
1090 int num = elap / 1000;
1091 int hor = 0;
1092 int min = 0;
1093 int sec = 0;
1094 static char buf[12];
1095
1096 hor=num / 3600;
1097 min=(num % 3600) / 60;
1098 sec=num % 60;
1099
1100 if(hor==0 && min==0 && sec==0)
1101 strcpy(buf,"0");
1102 else
1103 sprintf(buf,"%d:%02d:%02d",hor,min,sec);
1104
1105 return buf;
1106 }
1107
1108
1109 void date_from(char *date, int *dfrom, int *duntil)
1110 {
1111 int d0=0;
1112 int m0=0;
1113 int y0=0;
1114 int d1=0;
1115 int m1=0;
1116 int y1=0;
1117
1118 if (isdigit(date[0])) {
1119 int next=-1;
1120
1121 if (sscanf(date,"%d/%d/%d%n",&d0,&m0,&y0,&next)!=3 || y0<100 || m0<1 || m0>12 || d0<1 || d0>31 || next<0) {
1122 debuga(_("The date passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n"));
1123 exit(EXIT_FAILURE);
1124 }
1125 if (date[next]=='-') {
1126 if (sscanf(date+next+1,"%d/%d/%d",&d1,&m1,&y1)!=3 || y1<100 || m1<1 || m1>12 || d1<1 || d1>31) {
1127 debuga(_("The date range passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n"));
1128 exit(EXIT_FAILURE);
1129 }
1130 } else if (date[next]!='\0') {
1131 debuga(_("The date range passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n"));
1132 exit(EXIT_FAILURE);
1133 } else {
1134 d1=d0;
1135 m1=m0;
1136 y1=y0;
1137 }
1138 } else {
1139 int i;
1140 time_t Today,t1;
1141 struct tm *Date0,Date1;
1142
1143 if (time(&Today)==(time_t)-1) {
1144 debuga(_("Failed to get the current time\n"));
1145 exit(EXIT_FAILURE);
1146 }
1147 if (sscanf(date,"day-%d",&i)==1) {
1148 if (i<0) {
1149 debuga(_("Invalid number of days in -d parameter\n"));
1150 exit(EXIT_FAILURE);
1151 }
1152 Today-=i*24*60*60;
1153 Date0=localtime(&Today);
1154 if (Date0==NULL) {
1155 debuga(_("Cannot convert local time: %s\n"),strerror(errno));
1156 exit(EXIT_FAILURE);
1157 }
1158 y0=y1=Date0->tm_year+1900;
1159 m0=m1=Date0->tm_mon+1;
1160 d0=d1=Date0->tm_mday;
1161 } else if (sscanf(date,"week-%d",&i)==1) {
1162 /*
1163 There is no portable way to find the first day of the week even though the
1164 information is available in the locale. nl_langinfo has the unofficial
1165 parameters _NL_TIME_FIRST_WEEKDAY and _NL_TIME_WEEK_1STDAY but they are
1166 undocumented as is their return value and it is discouraged to use them.
1167 Beside, nl_langinfo isn't available on windows and the first day of the
1168 week isn't available at all on that system.
1169 */
1170 const int FirstWeekDay=1;
1171 time_t WeekBegin;
1172
1173 if (i<0) {
1174 debuga(_("Invalid number of weeks in -d parameter\n"));
1175 exit(EXIT_FAILURE);
1176 }
1177 Date0=localtime(&Today);
1178 if (Date0==NULL) {
1179 debuga(_("Cannot convert local time: %s\n"),strerror(errno));
1180 exit(EXIT_FAILURE);
1181 }
1182 WeekBegin=Today-((Date0->tm_wday-FirstWeekDay+7)%7)*24*60*60;
1183 WeekBegin-=i*7*24*60*60;
1184 Date0=localtime(&WeekBegin);
1185 if (Date0==NULL) {
1186 debuga(_("Cannot convert local time: %s\n"),strerror(errno));
1187 exit(EXIT_FAILURE);
1188 }
1189 y0=Date0->tm_year+1900;
1190 m0=Date0->tm_mon+1;
1191 d0=Date0->tm_mday;
1192 WeekBegin+=6*24*60*60;
1193 Date0=localtime(&WeekBegin);
1194 if (Date0==NULL) {
1195 debuga(_("Cannot convert local time: %s\n"),strerror(errno));
1196 exit(EXIT_FAILURE);
1197 }
1198 y1=Date0->tm_year+1900;
1199 m1=Date0->tm_mon+1;
1200 d1=Date0->tm_mday;
1201 } else if (sscanf(date,"month-%d",&i)==1) {
1202 if (i<0) {
1203 debuga(_("Invalid number of months in -d parameter\n"));
1204 exit(EXIT_FAILURE);
1205 }
1206 Date0=localtime(&Today);
1207 if (Date0==NULL) {
1208 debuga(_("Cannot convert local time: %s\n"),strerror(errno));
1209 exit(EXIT_FAILURE);
1210 }
1211 if (Date0->tm_mon<i%12) {
1212 y0=Date0->tm_year+1900-i/12-1;
1213 m0=(Date0->tm_mon+12-i%12)%12+1;
1214 d0=1;
1215 } else {
1216 y0=Date0->tm_year+1900-i/12;
1217 m0=Date0->tm_mon-i%12+1;
1218 d0=1;
1219 }
1220 memcpy(&Date1,Date0,sizeof(struct tm));
1221 Date1.tm_isdst=-1;
1222 Date1.tm_mday=1;
1223 if (m0<12) {
1224 Date1.tm_mon=m0;
1225 Date1.tm_year=y0-1900;
1226 } else {
1227 Date1.tm_mon=0;
1228 Date1.tm_year=y0-1900+1;
1229 }
1230 t1=mktime(&Date1);
1231 t1-=24*60*60;
1232 Date0=localtime(&t1);
1233 y1=Date0->tm_year+1900;
1234 m1=Date0->tm_mon+1;
1235 d1=Date0->tm_mday;
1236 } else {
1237 debuga(_("Invalid date range passed on command line\n"));
1238 exit(EXIT_FAILURE);
1239 }
1240 }
1241
1242 *dfrom=y0*10000+m0*100+d0;
1243 *duntil=y1*10000+m1*100+d1;
1244 sprintf(date,"%02d/%02d/%04d-%02d/%02d/%04d",d0,m0,y0,d1,m1,y1);
1245 return;
1246 }
1247
1248
1249 char *strlow(char *string)
1250 {
1251 char *s;
1252
1253 if (string)
1254 {
1255 for (s = string; *s; ++s)
1256 *s = tolower(*s);
1257 }
1258
1259 return string;
1260 }
1261
1262
1263
1264
1265 char *strup(char *string)
1266 {
1267 char *s;
1268
1269 if (string)
1270 {
1271 for (s = string; *s; ++s)
1272 *s = toupper(*s);
1273 }
1274
1275 return string;
1276 }
1277
1278
1279 void removetmp(const char *outdir)
1280 {
1281 FILE *fp_gen;
1282 char filename[256];
1283
1284 if(!RemoveTempFiles)
1285 return;
1286
1287 if(debug) {
1288 debuga(_("Purging temporary file sarg-general\n"));
1289 }
1290 if (snprintf(filename,sizeof(filename),"%s/sarg-general",outdir)>=sizeof(filename)) {
1291 debuga(_("(removetmp) directory too long to remove %s/sarg-period\n"),outdir);
1292 exit(EXIT_FAILURE);
1293 }
1294 if((fp_gen=fopen(filename,"w"))==NULL){
1295 debuga(_("(removetmp) Cannot open file %s\n"),filename);
1296 exit(EXIT_FAILURE);
1297 }
1298 totalger(fp_gen,filename);
1299 if (fclose(fp_gen)==EOF) {
1300 debuga(_("Failed to close %s after writing the total line - %s\n"),filename,strerror(errno));
1301 exit(EXIT_FAILURE);
1302 }
1303 }
1304
1305 void load_excludecodes(const char *ExcludeCodes)
1306 {
1307 FILE *fp_in;
1308 char data[80];
1309 int i;
1310 int Stored;
1311 long int MemSize;
1312
1313 if(ExcludeCodes[0] == '\0')
1314 return;
1315
1316 if((fp_in=fopen(ExcludeCodes,"r"))==NULL) {
1317 debuga(_("(util) Cannot open file %s (exclude_codes)\n"),ExcludeCodes);
1318 exit(EXIT_FAILURE);
1319 }
1320
1321 if (fseek(fp_in, 0, SEEK_END)==-1) {
1322 debuga(_("Failed to move till the end of the excluded codes file %s: %s\n"),ExcludeCodes,strerror(errno));
1323 exit(EXIT_FAILURE);
1324 }
1325 MemSize = ftell(fp_in);
1326 if (MemSize<0) {
1327 debuga(_("Cannot get the size of file %s\n"),ExcludeCodes);
1328 exit(EXIT_FAILURE);
1329 }
1330 if (fseek(fp_in, 0, SEEK_SET)==-1) {
1331 debuga(_("Failed to rewind the excluded codes file %s: %s\n"),ExcludeCodes,strerror(errno));
1332 exit(EXIT_FAILURE);
1333 }
1334
1335 MemSize+=1;
1336 if((excludecode=(char *) malloc(MemSize))==NULL) {
1337 debuga(_("malloc error (%ld)\n"),MemSize);
1338 exit(EXIT_FAILURE);
1339 }
1340 memset(excludecode,0,MemSize);
1341
1342 Stored=0;
1343 while(fgets(data,sizeof(data),fp_in)!=NULL) {
1344 if (data[0]=='#') continue;
1345 for (i=strlen(data)-1 ; i>=0 && (unsigned char)data[i]<=' ' ; i--) data[i]='\0';
1346 if (i<0) continue;
1347 if (Stored+i+2>=MemSize) {
1348 debuga(_("Too many codes to exclude in file %s\n"),ExcludeCodes);
1349 break;
1350 }
1351 strcat(excludecode,data);
1352 strcat(excludecode,";");
1353 Stored+=i+1;
1354 }
1355
1356 fclose(fp_in);
1357 return;
1358 }
1359
1360 void free_excludecodes(void)
1361 {
1362 if (excludecode) {
1363 free(excludecode);
1364 excludecode=NULL;
1365 }
1366 }
1367
1368 int vercode(const char *code)
1369 {
1370 char *cod;
1371 int clen;
1372
1373 if (excludecode && excludecode[0]!='\0') {
1374 clen=strlen(code);
1375 cod=excludecode;
1376 while (cod) {
1377 if (strncmp(code,cod,clen)==0 && cod[clen]==';')
1378 return 1;
1379 cod=strchr(cod,';');
1380 if (cod) cod++;
1381 }
1382 }
1383 return 0;
1384 }
1385
1386 void fixnone(char *str)
1387 {
1388 int i;
1389
1390 for (i=strlen(str)-1 ; i>=0 && (unsigned char)str[i]<=' ' ; i--);
1391 if(i==3 && strncmp(str,"none",4) == 0)
1392 str[0]='\0';
1393
1394 return;
1395 }
1396
1397 void fixendofline(char *str)
1398 {
1399 int i;
1400
1401 for (i=strlen(str)-1 ; i>=0 && (unsigned char)str[i]<=' ' ; i--) str[i]=0;
1402 }
1403
1404 #ifdef LEGACY_TESTVALIDUSERCHAR
1405 int testvaliduserchar(const char *user)
1406 {
1407 int x=0;
1408 int y=0;
1409
1410 for (y=0; y<strlen(UserInvalidChar); y++) {
1411 for (x=0; x<strlen(user); x++) {
1412 if(user[x] == UserInvalidChar[y])
1413 return 1;
1414 }
1415 }
1416 return 0;
1417 }
1418 #else
1419 int testvaliduserchar(const char *user)
1420 {
1421 char * p_UserInvalidChar = UserInvalidChar ;
1422 const char * p_user ;
1423
1424 while( *p_UserInvalidChar ) {
1425 p_user = user ;
1426 while ( *p_user ) {
1427 if( *p_UserInvalidChar == *p_user )
1428 return 1;
1429 p_user++ ;
1430 }
1431 p_UserInvalidChar++ ;
1432 }
1433 return 0;
1434 }
1435 #endif
1436
1437 int compar( const void *a, const void *b )
1438 {
1439 if( *(int *)a > *(int *)b ) return 1;
1440 if( *(int *)a < *(int *)b ) return -1;
1441 return 0;
1442 }
1443
1444 int getnumlist( char *buf, numlist *list, const int len, const int maxvalue )
1445 {
1446 int i, j, d, flag, r1, r2;
1447 char *pbuf, **bp, *strbufs[ 24 ];
1448
1449 bp = strbufs;
1450 strtok( buf, " \t" );
1451 for( *bp = strtok( NULL, "," ), list->len = 0; *bp; *bp = strtok( NULL, "," ) ) {
1452 if( ++bp >= &strbufs[ 24 ] )
1453 break;
1454 list->len++;
1455 }
1456 if( ! list->len )
1457 return -1;
1458 d = 0;
1459 for( i = 0; i < list->len; i++ ) {
1460 if( strchr( strbufs[ i ], '-' ) != 0 ) {
1461 pbuf = strbufs[ i ];
1462 strtok( pbuf, "-" );
1463 pbuf = strtok( NULL, "\0" );
1464 r1 = atoi( strbufs[ i ] );
1465 if( ( r2 = atoi( pbuf ) ) >= maxvalue || r1 >= r2 )
1466 return -1;
1467 if( i + d + ( r2 - r1 ) + 1 <= len ) {
1468 for( j = r1; j <= r2; j++ )
1469 list->list[ i + d++ ] = j;
1470 d--;
1471 }
1472 }
1473 else
1474 if( ( list->list[ i + d ] = atoi( strbufs[ i ] ) ) >= maxvalue )
1475 return 1;
1476 }
1477 list->len += d;
1478 qsort( list->list, list->len, sizeof( int ), compar );
1479 do {
1480 flag = 0;
1481 for( i = 0; i < list->len - 1; i++ )
1482 if( list->list[ i ] == list->list[ i + 1 ] ) {
1483 for( j = i + 1; j < list->len; j++ )
1484 list->list[ j - 1 ] = list->list[ j ];
1485 list->len--;
1486 flag = 1;
1487 break;
1488 }
1489 } while( flag );
1490 return 0;
1491 }
1492
1493
1494 char *get_size(const char *path, const char *file)
1495 {
1496 FILE *fp;
1497 static char response[255];
1498 char cmd[255];
1499 char *ptr;
1500
1501 if (snprintf(cmd,sizeof(cmd),"du -skh %s%s",path,file)>=sizeof(cmd)) {
1502 debuga(_("Cannot get disk space because the path %s%s is too long\n"),path,file);
1503 exit(EXIT_FAILURE);
1504 }
1505 if ((fp = popen(cmd, "r")) == NULL) {
1506 debuga(_("Cannot get disk space with command %s\n"),cmd);
1507 exit(EXIT_FAILURE);
1508 }
1509 if (!fgets(response, sizeof(response), fp)) {
1510 debuga(_("Cannot get disk size with command %s\n"),cmd);
1511 exit(EXIT_FAILURE);
1512 }
1513 ptr=strchr(response,'\t');
1514 if (ptr==NULL) {
1515 debuga(_("The command %s failed\n"),cmd);
1516 exit(EXIT_FAILURE);
1517 }
1518 pclose(fp);
1519 *ptr='\0';
1520
1521 return (response);
1522 }
1523
1524 void show_info(FILE *fp_ou)
1525 {
1526 char ftime[127];
1527
1528 if(!ShowSargInfo) return;
1529 zdate(ftime, sizeof(ftime), DateFormat);
1530 fprintf(fp_ou,"<div class=\"info\">%s <a href='%s'>%s-%s</a> %s %s</div>\n",_("Generated by"),URL,PGM,VERSION,_("on"),ftime);
1531 }
1532
1533 void show_sarg(FILE *fp_ou, int depth)
1534 {
1535 int i;
1536
1537 if(!ShowSargLogo) return;
1538 fputs("<div class=\"logo\"><a href=\"http://sarg.sourceforge.net\"><img src=\"",fp_ou);
1539 for (i=0 ; i<depth ; i++)
1540 fputs("../",fp_ou);
1541 fputs("images/sarg.png\" title=\"SARG, Squid Analysis Report Generator. Logo by Osamu Matsuzaki\" alt=\"Sarg\"></a>&nbsp;Squid Analysis Report Generator</div>\n",fp_ou);
1542 }
1543
1544 void write_logo_image(FILE *fp_ou)
1545 {
1546 if(LogoImage[0]!='\0')
1547 fprintf(fp_ou, "<div class=\"logo\"><img src=\"%s\" width=\"%s\" height=\"%s\" alt=\"Logo\">&nbsp;%s</div>\n",LogoImage,Width,Height,LogoText);
1548 }
1549
1550 void write_html_head(FILE *fp_ou, int depth, const char *page_title,int javascript)
1551 {
1552 int i;
1553
1554 fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n<html>\n",fp_ou);
1555 fprintf(fp_ou, "<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n",CharSet);
1556 if (page_title) fprintf(fp_ou,"<title>%s</title>\n",page_title);
1557 css(fp_ou);
1558 if ((javascript & HTML_JS_SORTTABLE)!=0 && SortTableJs[0]) {
1559 fputs("<script type=\"text/javascript\" src=\"",fp_ou);
1560 if (strncmp(SortTableJs,"../",3)==0) {
1561 for (i=0 ; i<depth ; i++) fputs("../",fp_ou);
1562 }
1563 fputs(SortTableJs,fp_ou);
1564 fputs("\"></script>\n",fp_ou);
1565 }
1566 fputs("</head>\n<body>\n",fp_ou);
1567 }
1568
1569 void write_html_header(FILE *fp_ou, int depth, const char *page_title,int javascript)
1570 {
1571 write_html_head(fp_ou,depth,page_title,javascript);
1572 write_logo_image(fp_ou);
1573 show_sarg(fp_ou, depth);
1574 fprintf(fp_ou,"<div class=\"title\"><table cellpadding=\"0\" cellspacing=\"0\">\n<tr><th class=\"title_c\">%s</th></tr>\n",Title);
1575 }
1576
1577 void close_html_header(FILE *fp_ou)
1578 {
1579 fputs("</table></div>\n",fp_ou);
1580 }
1581
1582 int write_html_trailer(FILE *fp_ou)
1583 {
1584 show_info(fp_ou);
1585 if (fputs("</body>\n</html>\n",fp_ou)==EOF) return(-1);
1586 return(0);
1587 }
1588
1589 void output_html_string(FILE *fp_ou,const char *str,int maxlen)
1590 {
1591 int i=0;
1592
1593 while (*str && (maxlen<=0 || i<maxlen)) {
1594 switch (*str) {
1595 case '&':
1596 fputs("&amp;",fp_ou);
1597 break;
1598 case '<':
1599 fputs("&lt;",fp_ou);
1600 break;
1601 case '>':
1602 fputs("&gt;",fp_ou);
1603 break;
1604 case '"':
1605 fputs("&quot;",fp_ou);
1606 break;
1607 case '\'':
1608 fputs("&#39;",fp_ou);
1609 break;
1610 default:
1611 fputc(*str,fp_ou);
1612 }
1613 str++;
1614 i++;
1615 }
1616 if (maxlen>0 && i>=maxlen)
1617 fputs("&hellip;",fp_ou);
1618 }
1619
1620 void output_html_url(FILE *fp_ou,const char *url)
1621 {
1622 while (*url) {
1623 if (*url=='&')
1624 fputs("&amp;",fp_ou);
1625 else
1626 fputc(*url,fp_ou);
1627 url++;
1628 }
1629 }
1630
1631 void url_hostname(const char *url,char *hostname,int hostsize)
1632 {
1633 int i;
1634
1635 hostsize--;
1636 for (i=0 ; i<hostsize && url[i] && url[i]!='/' ; i++)
1637 hostname[i]=url[i];
1638 hostname[i]='\0';
1639 }
1640
1641 void url_module(const char *url, char *w2)
1642 {
1643 int x, y;
1644 char w[255];
1645
1646 y=0;
1647 for(x=strlen(url)-1; x>=0; x--) {
1648 if(url[x] == '/' || y>=sizeof(w)-1) break;
1649 w[y++]=url[x];
1650 }
1651 if (x<0) {
1652 w2[0]='\0';
1653 return;
1654 }
1655
1656 x=0;
1657 for(y=y-1; y>=0; y--) {
1658 w2[x++]=w[y];
1659 }
1660 w2[x]='\0';
1661 }
1662
1663 void url_to_file(const char *url,char *file,int filesize)
1664 {
1665 int i,skip;
1666
1667 filesize--;
1668 skip=0;
1669 for(i=0; i<filesize && *url; url++) {
1670 if(isalnum(*url) || *url=='-' || *url=='_' || *url=='.' || *url=='%') {
1671 file[i++]=*url;
1672 skip=0;
1673 } else {
1674 if (!skip) file[i++]='_';
1675 skip=1;
1676 }
1677 }
1678 file[i]='\0';
1679 }
1680
1681 void version(void)
1682 {
1683 printf(_("SARG Version: %s\n"),VERSION);
1684 exit(EXIT_SUCCESS);
1685 }
1686
1687 char *get_param_value(const char *param,char *line)
1688 {
1689 int plen;
1690
1691 while (*line==' ' || *line=='\t') line++;
1692 plen=strlen(param);
1693 if (strncasecmp(line,param,plen)) return(NULL);
1694 if (line[plen]!=' ' && line[plen]!='\t') return(NULL);
1695 line+=plen;
1696 while (*line==' ' || *line=='\t') line++;
1697 return(line);
1698 }
1699
1700 void unlinkdir(const char *dir,int contentonly)
1701 {
1702 struct stat st;
1703 DIR *dirp;
1704 struct dirent *direntp;
1705 char dname[MAXLEN];
1706 int err;
1707
1708 dirp=opendir(dir);
1709 if (!dirp) return;
1710 while ((direntp = readdir(dirp)) != NULL) {
1711 if (direntp->d_name[0] == '.' && (direntp->d_name[1] == '\0' ||
1712 (direntp->d_name[1] == '.' && direntp->d_name[2] == '\0')))
1713 continue;
1714 if (snprintf(dname,sizeof(dname),"%s/%s",dir,direntp->d_name)>=sizeof(dname)) {
1715 debuga(_("directory name to delete too long: %s/%s\n"),dir,direntp->d_name);
1716 exit(EXIT_FAILURE);
1717 }
1718 #ifdef HAVE_LSTAT
1719 err=lstat(dname,&st);
1720 #else
1721 err=stat(dname,&st);
1722 #endif
1723 if (err) {
1724 debuga(_("cannot stat %s\n"),dname);
1725 exit(EXIT_FAILURE);
1726 }
1727 if (S_ISREG(st.st_mode)) {
1728 if (unlink(dname)) {
1729 debuga(_("cannot delete %s - %s\n"),dname,strerror(errno));
1730 exit(EXIT_FAILURE);
1731 }
1732 } else if (S_ISDIR(st.st_mode)) {
1733 unlinkdir(dname,0);
1734 } else {
1735 debuga(_("unknown path type %s\n"),dname);
1736 }
1737 }
1738 closedir(dirp);
1739
1740 if (!contentonly) {
1741 if (rmdir(dir)) {
1742 debuga(_("cannot delete %s - %s\n"),dir,strerror(errno));
1743 exit(EXIT_FAILURE);
1744 }
1745 }
1746 }
1747