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