]> git.ipfire.org Git - thirdparty/sarg.git/blob - util.c
Store the period internaly and get rid of the sarg-period file.
[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 1024
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(strcmp(DisplayedValues,"abbreviation") == 0) {
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
580 void buildhref(char * href)
581 {
582 char whref[MAXLEN];
583
584 if(strcmp(href,"./") == 0){
585 href[0]='\0';
586 strcat(href,"<a href='");
587 return;
588 }
589
590 href[strlen(href)-1]='\0';
591 sprintf(whref,"%s",strrchr(href,'/'));
592
593 strcpy(href,"<a href='");
594 strcat(href,whref);
595 strcat(href,"/");
596
597 return;
598
599 }
600
601
602 char *buildtime(long long int elap)
603 {
604
605 int num = elap / 1000;
606 int hor = 0;
607 int min = 0;
608 int sec = 0;
609 static char buf[12];
610
611 buf[0]='\0';
612
613 hor=num / 3600;
614 min=(num % 3600) / 60;
615 sec=num % 60;
616 sprintf(buf,"%02d:%02d:%02d",hor,min,sec);
617
618 return(buf);
619
620 }
621
622
623 void obtdate(const char *dirname, const char *name, char *data)
624 {
625
626 FILE *fp_in;
627 char wdir[MAXLEN];
628
629 sprintf(wdir,"%s%s/sarg-date",dirname,name);
630 if ((fp_in = fopen(wdir, "rt")) == 0) {
631 sprintf(wdir,"%s%s/date",dirname,name);
632 if ((fp_in = fopen(wdir, "rt")) == 0) {
633 data[0]='\0';
634 return;
635 }
636 }
637
638 if (!fgets(data,80,fp_in)) {
639 debuga(_("Failed to read the date in %s\n"),wdir);
640 exit(EXIT_FAILURE);
641 }
642 fclose(fp_in);
643 fixendofline(data);
644
645 return;
646
647 }
648
649
650 void formatdate(char *date,int date_size,int year,int month,int day,int hour,int minute,int second,int dst)
651 {
652 struct tm ltm;
653 time_t unixtime;
654 struct tm *fulltm;
655
656 memset(&ltm,0,sizeof(ltm));
657 if (year>=1900) ltm.tm_year=year-1900;
658 if (month>=1 && month<=12) ltm.tm_mon=month-1;
659 if (day>=1 && day<=31) ltm.tm_mday=day;
660 if (hour>=0 && hour<24) ltm.tm_hour=hour;
661 if (minute>=0 && minute<60) ltm.tm_min=minute;
662 if (second>=0 && second<60) ltm.tm_sec=second;
663 ltm.tm_isdst=dst;
664 unixtime=mktime(&ltm); //fill the missing entries
665 fulltm=localtime(&unixtime);
666 //strftime(date,date_size,"%a %b %d %H:%M:%S %Z %Y",fulltm);
667 strftime(date,date_size,"%c",fulltm);
668 }
669
670
671 void computedate(int year,int month,int day,struct tm *t)
672 {
673 memset(t,0,sizeof(*t));
674 t->tm_year=year-1900;
675 t->tm_mon=month-1;
676 t->tm_mday=day;
677 }
678
679
680 int obtuser(const char *dirname, const char *name)
681 {
682
683 FILE *fp_in;
684 char wdir[MAXLEN];
685 char tuser[20];
686 int nuser;
687
688 sprintf(wdir,"%s%s/sarg-users",dirname,name);
689 if((fp_in=fopen(wdir,"r"))==NULL) {
690 sprintf(wdir,"%s%s/users",dirname,name);
691 if((fp_in=fopen(wdir,"r"))==NULL) {
692 return(0);
693 }
694 }
695
696 if (!fgets(tuser,sizeof(tuser),fp_in)) {
697 debuga(_("Failed to read the number of users in %s\n"),wdir);
698 exit(EXIT_FAILURE);
699 }
700 fclose(fp_in);
701 nuser=atoi(tuser);
702
703 return(nuser);
704 }
705
706
707 void obttotal(const char *dirname, const char *name, char *tbytes, int nuser, char *media)
708 {
709 FILE *fp_in;
710 char *buf;
711 char wdir[MAXLEN];
712 char user[MAX_USER_LEN];
713 char sep;
714 long long int med=0;
715 long long int twork=0;
716 struct getwordstruct gwarea;
717 longline line;
718
719 twork=0;
720 tbytes[0]='\0';
721 media[0]='\0';
722
723 sprintf(wdir,"%s%s/sarg-general",dirname,name);
724 if ((fp_in = fopen(wdir, "r")) == 0) {
725 sprintf(wdir,"%s%s/general",dirname,name);
726 if ((fp_in = fopen(wdir, "r")) == 0) {
727 return;
728 }
729 }
730
731 if ((line=longline_create())==NULL) {
732 debuga(_("Not enough memory to read the file %s\n"),wdir);
733 exit(EXIT_FAILURE);
734 }
735
736 while((buf=longline_read(fp_in,line))!=NULL) {
737 if (strncmp(buf,"TOTAL\t",6) == 0)
738 sep='\t'; //new file
739 else if (strncmp(buf,"TOTAL ",6) == 0)
740 sep=' '; //old file
741 else
742 continue;
743 getword_start(&gwarea,buf);
744 if (getword(user,sizeof(user),&gwarea,sep)<0) {
745 debuga(_("There is a invalid user in file %s\n"),wdir);
746 exit(EXIT_FAILURE);
747 }
748 if(strcmp(user,"TOTAL") != 0)
749 continue;
750 if (getword_skip(MAXLEN,&gwarea,sep)<0) {
751 debuga(_("There a broken total number of access in file %s\n"),wdir);
752 exit(EXIT_FAILURE);
753 }
754 if (getword_atoll(&twork,&gwarea,sep)<0) {
755 debuga(_("There is a broken number of bytes in file %s\n"),wdir);
756 exit(EXIT_FAILURE);
757 }
758 strcpy(tbytes,fixnum(twork,1));
759 break;
760 }
761 fclose(fp_in);
762 longline_destroy(&line);
763
764 if(nuser <= 0) {
765 strcpy(media,"0");
766 return;
767 }
768
769 med=twork / nuser;
770 strcpy(media,fixnum(med,1));
771
772 return;
773 }
774
775 int getperiod_fromsarglog(const char *arqtt,struct periodstruct *period)
776 {
777 const char *str;
778 int day0, month0, year0, hour0, minute0;
779 int day1, month1, year1, hour1, minute1;
780 char month[4];
781 int i;
782
783 memset(period,0,sizeof(*period));
784
785 str=arqtt;
786 while((str=strstr(str,"sarg-"))!=NULL) {
787 str+=5;
788 if (!isdigit(str[0]) || !isdigit(str[1])) continue;
789 day0=(str[0]-'0')*10+(str[1]-'0');
790 str+=2;
791 strncpy(month,str,3);
792 month[3]=0;
793 month0=month2num(month);
794 if (month0>=12) continue;
795 str+=3;
796 year0=0;
797 for (i=0 ; isdigit(str[i]) && i<4 ; i++) year0=year0*10+(str[i]-'0');
798 if (i!=4) continue;
799 str+=4;
800
801 if (!isdigit(str[0]) || !isdigit(str[1])) continue;
802 hour0=(str[0]-'0')*10+(str[1]-'0');
803 str+=2;
804 if (!isdigit(str[0]) || !isdigit(str[1])) continue;
805 minute0=(str[0]-'0')*10+(str[1]-'0');
806 str+=2;
807
808 if (*str != '_') continue;
809
810 if (!isdigit(str[0]) || !isdigit(str[1])) continue;
811 day1=(str[0]-'0')*10+(str[1]-'0');
812 str+=2;
813 strncpy(month,str,3);
814 month[3]=0;
815 month1=month2num(month);
816 if (month1>=12) continue;
817 str+=3;
818 year1=0;
819 for (i=0 ; isdigit(str[i]) && i<4 ; i++) year1=year1*10+(str[i]-'0');
820 if (i!=4) continue;
821
822 if (!isdigit(str[0]) || !isdigit(str[1])) continue;
823 hour1=(str[0]-'0')*10+(str[1]-'0');
824 str+=2;
825 if (!isdigit(str[0]) || !isdigit(str[1])) continue;
826 minute1=(str[0]-'0')*10+(str[1]-'0');
827 str+=2;
828
829 period->start.tm_mday=day0;
830 period->start.tm_mon=month0;
831 period->start.tm_year=year0-1900;
832 period->start.tm_hour=hour0;
833 period->start.tm_min=minute0;
834 period->end.tm_mday=day1;
835 period->end.tm_mon=month1;
836 period->end.tm_year=year1-1900;
837 period->end.tm_hour=hour1;
838 period->end.tm_min=minute1;
839 return(0);
840 }
841 return(-1);
842 }
843
844 int getperiod_buildtext(struct periodstruct *period)
845 {
846 int i;
847
848 if(df[0]=='u')
849 i=strftime(period->text, sizeof(period->text), "%Y %b %d", &period->start);
850 else if(df[0]=='e')
851 i=strftime(period->text, sizeof(period->text), "%d %b %Y", &period->start);
852 else /*if(df[0]=='w')*/ {
853 IndexTree=INDEX_TREE_FILE;
854 i=strftime(period->text, sizeof(period->text), "%Y.%U", &period->start);
855 }
856
857 if (period->start.tm_year!=period->end.tm_year ||
858 period->start.tm_mon!=period->end.tm_mon ||
859 period->start.tm_mday!=period->end.tm_mday) {
860 period->text[i++]='-';
861 if(df[0]=='u')
862 i=strftime(period->text+i, sizeof(period->text)-i, "%Y %b %d", &period->end);
863 else if(df[0]=='e')
864 i=strftime(period->text+i, sizeof(period->text)-i, "%d %b %Y", &period->end);
865 else
866 i=strftime(period->text+i, sizeof(period->text)-i, "%Y.%U", &period->end);
867 if (i == 0) return(-1);
868 }
869 return(0);
870 }
871
872 static void copy_images(void)
873 {
874 FILE *img_in, *img_ou;
875 char images[512];
876 char imgdir[MAXLEN];
877 char srcfile[MAXLEN];
878 char dstfile[MAXLEN];
879 DIR *dirp;
880 struct dirent *direntp;
881 char buffer[MAXLEN];
882 size_t nread;
883 struct stat info;
884
885 if (snprintf(images,sizeof(images),"%simages",outdir)>=sizeof(images)) {
886 debuga(_("Cannot copy images to target directory %simages\n"),outdir);
887 exit(EXIT_FAILURE);
888 }
889 if (access(images,R_OK)!=0) {
890 mkdir(images,0755);
891 }
892
893 strcpy(imgdir,IMAGEDIR);
894 dirp = opendir(imgdir);
895 if(dirp==NULL) {
896 debuga(_("(util) Can't open directory %s: %s\n"),imgdir,strerror(errno));
897 return;
898 }
899 while ((direntp = readdir( dirp )) != NULL ){
900 if(direntp->d_name[0]=='.')
901 continue;
902 sprintf(srcfile,"%s/%s",imgdir,direntp->d_name);
903 if (stat(srcfile,&info)) {
904 debuga(_("Cannot stat \"%s\" - %s\n"),srcfile,strerror(errno));
905 continue;
906 }
907 if (S_ISREG(info.st_mode)) {
908 sprintf(dstfile,"%s/%s",images,direntp->d_name);
909 img_in = fopen(srcfile, "rb");
910 if(img_in!=NULL) {
911 img_ou = fopen(dstfile, "wb");
912 if(img_ou!=NULL) {
913 while ((nread = fread(buffer,1,sizeof(buffer),img_in))>0) {
914 if (fwrite(buffer,1,nread,img_ou)!=nread) {
915 debuga(_("Failed to copy image %s to %s\n"),srcfile,dstfile);
916 break;
917 }
918 }
919 fclose(img_ou);
920 } else
921 fprintf(stderr,"SARG: (util): %s %s: %s\n", _("Cannot open file")?_("Cannot open file"):"Can't open/create file", dstfile, strerror(errno));
922 fclose(img_in);
923 } else
924 fprintf(stderr,"SARG: (util): %s %s: %s\n", _("Cannot open file")?_("Cannot open file"):"Can't open file", srcfile, strerror(errno));
925 }
926 }
927 (void) closedir(dirp);
928
929 return;
930 }
931
932 int vrfydir(const struct periodstruct *per1, const char *addr, const char *site, const char *us, const char *form)
933 {
934 FILE *fp_ou;
935 int num=1, count=0;
936 char wdir[MAXLEN];
937 char dirname2[MAXLEN];
938 int y1, y2;
939 int m1, m2;
940 int d1, d2;
941 int wlen, wlen2;
942 time_t curtime;
943 struct tm *loctm;
944
945 strcpy(wdir,outdir);
946 wlen=strlen(wdir);
947 y1=per1->start.tm_year+1900;
948 y2=per1->end.tm_year+1900;
949 m1=per1->start.tm_mon+1;
950 m2=per1->end.tm_mon+1;
951 d1=per1->start.tm_mday;
952 d2=per1->end.tm_mday;
953 if(IndexTree == INDEX_TREE_DATE) {
954 wlen+=sprintf(wdir+wlen,"%04d",y1);
955 if(y1!=y2) wlen+=sprintf(wdir+wlen,"-%04d",y2);
956 if(access(wdir, R_OK) != 0)
957 my_mkdir(wdir);
958
959 wlen+=sprintf(wdir+wlen,"/%02d",m1);
960 if(m1 != m2) wlen+=sprintf(wdir+wlen,"-%02d",m2);
961 if(access(wdir, R_OK) != 0)
962 my_mkdir(wdir);
963
964 wlen+=sprintf(wdir+wlen,"/%02d",d1);
965 if(d1!=d2) wlen+=sprintf(wdir+wlen,"-%02d",d2);
966 } else {
967 if(df[0] == 'u') {
968 wlen=snprintf(wdir+wlen,sizeof(wdir)-wlen,"%04d%s%02d-%04d%s%02d",y1,
969 conv_month_name(m1),d1,y2,conv_month_name(m2),d2);
970 } else if(df[0] == 'e') {
971 wlen=snprintf(wdir+wlen,sizeof(wdir)-wlen,"%02d%s%04d-%02d%s%04d",d1,
972 conv_month_name(m1),y1,d2,conv_month_name(m2),y2);
973 } else if(df[0] == 'w') {
974 wlen2=strftime(wdir+wlen, sizeof(wdir)-wlen, "%Y.%U", &per1->start);
975 if (wlen2==0) return(-1);
976 wlen+=wlen2;
977 }
978 }
979
980 if(us[0] != '\0') {
981 strcat(wdir,"-");
982 strcat(wdir,us);
983 }
984 if(addr[0] != '\0') {
985 strcat(wdir,"-");
986 strcat(wdir,addr);
987 }
988 if(site[0] != '\0') {
989 strcat(wdir,"-");
990 strcat(wdir,site);
991 }
992
993 strcpy(outdirname,wdir);
994
995 if(IndexTree != INDEX_TREE_DATE) {
996 if(!OverwriteReport) {
997 while(num) {
998 if(access(wdir,R_OK) == 0) {
999 sprintf(wdir,"%s.%d",outdirname,num);
1000 num++;
1001 count++;
1002 } else
1003 break;
1004 }
1005
1006 if(count > 0) {
1007 if(debug)
1008 debuga(_("File %s already exists, moved to %s\n"),outdirname,wdir);
1009 rename(outdirname,wdir);
1010 }
1011 } else {
1012 if(access(outdirname,R_OK) == 0) {
1013 unlinkdir(outdirname,1);
1014 }
1015 }
1016 my_mkdir(outdirname);
1017 } else {
1018 strcpy(dirname2,wdir);
1019 if(!OverwriteReport) {
1020 while(num) {
1021 if(access(wdir,R_OK) == 0) {
1022 sprintf(wdir,"%s.%d",dirname2,num);
1023 num++;
1024 count++;
1025 } else
1026 break;
1027 }
1028
1029 if(count > 0) {
1030 if(debug)
1031 debuga(_("File %s already exists, moved to %s\n"),dirname2,wdir);
1032 rename(dirname2,wdir);
1033 strcpy(dirname2,wdir);
1034 }
1035 } else {
1036 if(access(wdir,R_OK) == 0) {
1037 unlinkdir(wdir,1);
1038 }
1039 }
1040
1041 if(access(wdir, R_OK) != 0)
1042 my_mkdir(wdir);
1043 }
1044
1045 strcpy(dirname2,wdir);
1046
1047 sprintf(wdir,"%s/sarg-date",outdirname);
1048 if ((fp_ou = fopen(wdir, "wt")) == 0) {
1049 debuga(_("cannot open %s for writing\n"),wdir);
1050 perror("SARG:");
1051 exit(EXIT_FAILURE);
1052 }
1053 time(&curtime);
1054 //strftime(wdir,sizeof(wdir),"%a %b %d %H:%M:%S %Z %Y",localtime(&curtime));
1055 loctm=localtime(&curtime);
1056 strftime(wdir,sizeof(wdir),"%Y-%m-%d %H:%M:%S",loctm);
1057 if (fprintf(fp_ou,"%s %d\n",wdir,loctm->tm_isdst)<0) {
1058 debuga(_("failed to write the date in %s\n"),wdir);
1059 perror("SARG:");
1060 exit(EXIT_FAILURE);
1061 }
1062 if (fclose(fp_ou)==EOF) {
1063 debuga(_("failed to write the date in %s\n"),wdir);
1064 perror("SARG:");
1065 exit(EXIT_FAILURE);
1066 }
1067
1068 copy_images();
1069 return(0);
1070 }
1071
1072 void strip_latin(char *line)
1073 {
1074 int i,j;
1075 int skip;
1076
1077 j=0;
1078 skip=0;
1079 for (i=0;line[i];i++){
1080 if (skip){
1081 if (line[i]==';') skip=0;
1082 } else {
1083 if (line[i]=='&')
1084 skip=1;
1085 else
1086 line[j++]=line[i];
1087 }
1088 }
1089 line[j]='\0';
1090 return;
1091
1092 }
1093
1094 void zdate(char *ftime,int ftimesize, const char *DateFormat)
1095 {
1096
1097 time_t t;
1098 struct tm *local;
1099
1100 t = time(NULL);
1101 local = localtime(&t);
1102 if(strcmp(DateFormat,"u") == 0)
1103 strftime(ftime, ftimesize, "%b/%d/%Y %H:%M", local);
1104 if(strcmp(DateFormat,"e") == 0)
1105 strftime(ftime, ftimesize, "%d/%b/%Y-%H:%M", local);
1106 if(strcmp(DateFormat,"w") == 0)
1107 strftime(ftime, ftimesize, "%V-%H-%M", local);
1108 return;
1109 }
1110
1111
1112 char *fixtime(long int elap)
1113 {
1114
1115 int num = elap / 1000;
1116 int hor = 0;
1117 int min = 0;
1118 int sec = 0;
1119 static char buf[12];
1120
1121 if(strcmp(datetimeby,"bytes") == 0) {
1122 strcpy(buf,fixnum(elap,1));
1123 return buf;
1124 }
1125
1126 if(num<1) {
1127 sprintf(buf,"00:00:%02ld",elap);
1128 return buf;
1129 }
1130
1131 hor=num / 3600;
1132 min=(num % 3600) / 60;
1133 sec=num % 60;
1134
1135 if(hor==0 && min==0 && sec==0)
1136 strcpy(buf,"0");
1137 else
1138 sprintf(buf,"%01d:%02d:%02d",hor,min,sec);
1139
1140 return buf;
1141
1142 }
1143
1144
1145 void date_from(char *date, char *dfrom, char *duntil)
1146 {
1147
1148 int diaf;
1149 int mesf;
1150 int anof;
1151 int diau;
1152 int mesu;
1153 int anou;
1154 char wdate[50];
1155
1156 strncpy(wdate,date,sizeof(wdate)-1);
1157 wdate[sizeof(wdate)-1]='\0';
1158 if(strchr(wdate,'-') == NULL) {
1159 if (strlen(wdate)*2+1>=sizeof(wdate)) {
1160 debuga(_("Invalid date range passed as argument\n"));
1161 exit(EXIT_FAILURE);
1162 }
1163 strcat(wdate,"-");
1164 strcat(wdate,date);
1165 strcpy(date,wdate);
1166 }
1167
1168 if (sscanf(wdate,"%d/%d/%d-%d/%d/%d",&diaf,&mesf,&anof,&diau,&mesu,&anou)!=6) {
1169 debuga(_("The date range passed as argument is not formated as dd/mm/yyyy-dd/mm/yyyy\n"));
1170 exit(EXIT_FAILURE);
1171 }
1172
1173 sprintf(dfrom,"%04d%02d%02d",anof,mesf,diaf);
1174 sprintf(duntil,"%04d%02d%02d",anou,mesu,diau);
1175 return;
1176 }
1177
1178
1179 char *strlow(char *string)
1180 {
1181 char *s;
1182
1183 if (string)
1184 {
1185 for (s = string; *s; ++s)
1186 *s = tolower(*s);
1187 }
1188
1189 return string;
1190 }
1191
1192
1193
1194
1195 char *strup(char *string)
1196 {
1197 char *s;
1198
1199 if (string)
1200 {
1201 for (s = string; *s; ++s)
1202 *s = toupper(*s);
1203 }
1204
1205 return string;
1206 }
1207
1208
1209 void removetmp(const char *outdir)
1210 {
1211
1212 FILE *fp_in;
1213 char warea[256];
1214 char buf[MAXLEN];
1215
1216 if(!RemoveTempFiles)
1217 return;
1218
1219 if(debug) {
1220 debuga(_("Removing temporary files sarg-general, sarg-period\n"));
1221 }
1222 if (snprintf(warea,sizeof(warea),"%s/sarg-general",outdir)>=sizeof(warea)) {
1223 debuga(_("(removetmp) directory too long to remove %s/sarg-period\n"),outdir);
1224 exit(EXIT_FAILURE);
1225 }
1226 if((fp_in=fopen(warea,"r"))==NULL){
1227 debuga(_("(removetmp) Cannot open file %s\n"),warea);
1228 exit(EXIT_FAILURE);
1229 }
1230 while(fgets(buf,sizeof(buf),fp_in)!=NULL) {
1231 if(strncmp(buf,"TOTAL",5) == 0 && (buf[6]=='\t' || buf[6]==' '))
1232 break;
1233 }
1234 fclose(fp_in);
1235
1236 if((fp_in=fopen(warea,"w"))==NULL){
1237 debuga(_("(removetmp) Cannot open file %s\n"),warea);
1238 exit(EXIT_FAILURE);
1239 }
1240 if (fputs(buf,fp_in)==EOF) {
1241 debuga(_("Failed to write the total line in %s - %s\n"),warea,strerror(errno));
1242 exit(EXIT_FAILURE);
1243 }
1244 if (fclose(fp_in)==EOF) {
1245 debuga(_("Failed to close %s after writing the total line - %s\n"),warea,strerror(errno));
1246 exit(EXIT_FAILURE);
1247 }
1248
1249 return;
1250 }
1251
1252 void load_excludecodes(const char *ExcludeCodes)
1253 {
1254
1255 FILE *fp_in;
1256 char data[80];
1257 int i;
1258
1259 if(ExcludeCodes[0] == '\0')
1260 return;
1261
1262 if((excludecode=(char *) malloc(1024))==NULL) {
1263 debuga(_("malloc error (1024)\n"));
1264 exit(EXIT_FAILURE);
1265 }
1266 bzero(excludecode,1024);
1267
1268 if((fp_in=fopen(ExcludeCodes,"r"))==NULL) {
1269 debuga(_("(util) Cannot open file %s (exclude_codes)\n"),ExcludeCodes);
1270 exit(EXIT_FAILURE);
1271 }
1272
1273 while(fgets(data,sizeof(data),fp_in)!=NULL) {
1274 for (i=strlen(data)-1 ; i>=0 && (unsigned char)data[i]<=' ' ; i--) data[i]=0;
1275 if (i<0) continue;
1276 strcat(excludecode,data);
1277 strcat(excludecode,";");
1278 }
1279
1280 fclose(fp_in);
1281 return;
1282
1283 }
1284
1285 void free_excludecodes(void)
1286 {
1287 if (excludecode) {
1288 free(excludecode);
1289 excludecode=NULL;
1290 }
1291 }
1292
1293 int vercode(const char *code)
1294 {
1295 char *cod;
1296 int clen;
1297
1298 if (excludecode && excludecode[0]!=0) {
1299 clen=strlen(code);
1300 for (cod=excludecode ; cod ; cod=strchr(cod+1,';')) {
1301 if (strncmp(code,cod,clen)==0 && cod[clen]==';')
1302 return 1;
1303 }
1304 }
1305 return 0;
1306 }
1307
1308 void fixnone(char *str)
1309 {
1310 int i;
1311
1312 for (i=strlen(str)-1 ; i>=0 && (unsigned char)str[i]<=' ' ; i--);
1313 if(i==3 && strncmp(str,"none",4) == 0)
1314 str[0]='\0';
1315
1316 return;
1317 }
1318
1319 void fixendofline(char *str)
1320 {
1321 int i;
1322
1323 for (i=strlen(str)-1 ; i>=0 && (unsigned char)str[i]<=' ' ; i--) str[i]=0;
1324 }
1325
1326 #ifdef LEGACY_TESTVALIDUSERCHAR
1327 int testvaliduserchar(const char *user)
1328 {
1329
1330 int x=0;
1331 int y=0;
1332
1333 for (y=0; y<strlen(UserInvalidChar); y++) {
1334 for (x=0; x<strlen(user); x++) {
1335 if(user[x] == UserInvalidChar[y])
1336 return 1;
1337 }
1338 }
1339 return 0;
1340 }
1341 #else
1342 int testvaliduserchar(const char *user)
1343 {
1344
1345 char * p_UserInvalidChar = UserInvalidChar ;
1346 const char * p_user ;
1347
1348 while( *p_UserInvalidChar ) {
1349 p_user = user ;
1350 while ( *p_user ) {
1351 if( *p_UserInvalidChar == *p_user )
1352 return 1;
1353 p_user++ ;
1354 }
1355 p_UserInvalidChar++ ;
1356 }
1357 return 0;
1358 }
1359 #endif
1360
1361 int compar( const void *a, const void *b )
1362 { if( *(int *)a > *(int *)b ) return 1;
1363 if( *(int *)a < *(int *)b ) return -1;
1364 return 0;
1365 }
1366
1367 int getnumlist( char *buf, numlist *list, const int len, const int maxvalue )
1368 {
1369 int i, j, d, flag, r1, r2;
1370 char *pbuf, **bp, *strbufs[ 24 ];
1371
1372 bp = strbufs;
1373 strtok( buf, " \t" );
1374 for( *bp = strtok( NULL, "," ), list->len = 0; *bp; *bp = strtok( NULL, "," ) ) {
1375 if( ++bp >= &strbufs[ 24 ] )
1376 break;
1377 list->len++;
1378 }
1379 if( ! list->len )
1380 return -1;
1381 d = 0;
1382 for( i = 0; i < list->len; i++ ) {
1383 if( strchr( strbufs[ i ], '-' ) != 0 ) {
1384 pbuf = strbufs[ i ];
1385 strtok( pbuf, "-" );
1386 pbuf = strtok( NULL, "\0" );
1387 r1 = atoi( strbufs[ i ] );
1388 if( ( r2 = atoi( pbuf ) ) >= maxvalue || r1 >= r2 )
1389 return -1;
1390 if( i + d + ( r2 - r1 ) + 1 <= len ) {
1391 for( j = r1; j <= r2; j++ )
1392 list->list[ i + d++ ] = j;
1393 d--;
1394 }
1395 }
1396 else
1397 if( ( list->list[ i + d ] = atoi( strbufs[ i ] ) ) >= maxvalue )
1398 return 1;
1399 }
1400 list->len += d;
1401 qsort( list->list, list->len, sizeof( int ), compar );
1402 do {
1403 flag = 0;
1404 for( i = 0; i < list->len - 1; i++ )
1405 if( list->list[ i ] == list->list[ i + 1 ] ) {
1406 for( j = i + 1; j < list->len; j++ )
1407 list->list[ j - 1 ] = list->list[ j ];
1408 list->len--;
1409 flag = 1;
1410 break;
1411 }
1412 } while( flag );
1413 return 0;
1414 }
1415
1416
1417 char *get_size(const char *path, const char *file)
1418 {
1419 FILE *fp;
1420 static char response[255];
1421 char cmd[255];
1422 char *ptr;
1423
1424 if (snprintf(cmd,sizeof(cmd),"du -skh %s%s",path,file)>=sizeof(cmd)) {
1425 debuga(_("Cannot get disk space because the path %s%s is too long\n"),path,file);
1426 exit(EXIT_FAILURE);
1427 }
1428 if ((fp = popen(cmd, "r")) == NULL) {
1429 debuga(_("Cannot get disk space with command %s\n"),cmd);
1430 exit(EXIT_FAILURE);
1431 }
1432 if (!fgets(response, sizeof(response), fp)) {
1433 debuga(_("Cannot get disk size with command %s\n"),cmd);
1434 exit(EXIT_FAILURE);
1435 }
1436 ptr=strchr(response,'\t');
1437 if (ptr==NULL) {
1438 debuga(_("The command %s failed\n"),cmd);
1439 exit(EXIT_FAILURE);
1440 }
1441 pclose(fp);
1442 *ptr='\0';
1443
1444 return (response);
1445 }
1446
1447 void show_info(FILE *fp_ou)
1448 {
1449 char ftime[127];
1450
1451 if(!ShowSargInfo) return;
1452 zdate(ftime, sizeof(ftime), DateFormat);
1453 fprintf(fp_ou,"<div class=\"info\">%s <a href='%s'>%s-%s</a> %s %s</div>\n",_("Generated by"),URL,PGM,VERSION,_("on"),ftime);
1454 }
1455
1456 void show_sarg(FILE *fp_ou, int depth)
1457 {
1458 int i;
1459
1460 if(!ShowSargLogo) return;
1461 fputs("<div class=\"logo\"><a href=\"http://sarg.sourceforge.net\"><img src=\"",fp_ou);
1462 for (i=0 ; i<depth ; i++)
1463 fputs("../",fp_ou);
1464 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);
1465 }
1466
1467 void write_logo_image(FILE *fp_ou)
1468 {
1469 if(LogoImage[0]!='\0')
1470 fprintf(fp_ou, "<div class=\"logo\"><img src=\"%s\" width=\"%s\" height=\"%s\" alt=\"Logo\">&nbsp;%s</div>\n",LogoImage,Width,Height,LogoText);
1471 }
1472
1473 void write_html_header(FILE *fp_ou, int depth, const char *page_title)
1474 {
1475 //fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n",fp_ou);
1476 fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n<html>\n",fp_ou);
1477 fprintf(fp_ou, "<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n",CharSet);
1478 if (page_title) fprintf(fp_ou,"<title>%s</title>\n",page_title);
1479 css(fp_ou);
1480 fprintf(fp_ou,"</head>\n<body style=\"font-family:%s;font-size:%s;background-color:%s;background-image:url(%s)\">\n",FontFace,TitleFontSize,BgColor,BgImage);
1481 write_logo_image(fp_ou);
1482 show_sarg(fp_ou, depth);
1483 fprintf(fp_ou,"<div class=\"title\"><table cellpadding=\"0\" cellspacing=\"0\">\n<tr><th class=\"title_c\">%s</th></tr>\n",Title);
1484 }
1485
1486 void close_html_header(FILE *fp_ou)
1487 {
1488 fputs("</table></div>\n",fp_ou);
1489 }
1490
1491 int write_html_trailer(FILE *fp_ou)
1492 {
1493 show_info(fp_ou);
1494 if (fputs("</body>\n</html>\n",fp_ou)==EOF) return(-1);
1495 return(0);
1496 }
1497
1498 void output_html_string(FILE *fp_ou,const char *str,int maxlen)
1499 {
1500 int i=0;
1501
1502 while (*str && (maxlen<=0 || i<maxlen)) {
1503 switch (*str) {
1504 case '&':
1505 fputs("&amp;",fp_ou);
1506 break;
1507 case '<':
1508 fputs("&lt;",fp_ou);
1509 break;
1510 case '>':
1511 fputs("&gt;",fp_ou);
1512 break;
1513 case '"':
1514 fputs("&quot;",fp_ou);
1515 break;
1516 case '\'':
1517 fputs("&#39;",fp_ou);
1518 break;
1519 default:
1520 fputc(*str,fp_ou);
1521 }
1522 str++;
1523 i++;
1524 }
1525 if (maxlen>0 && i>=maxlen)
1526 fputs("&hellip;",fp_ou);
1527 }
1528
1529 void output_html_url(FILE *fp_ou,const char *url)
1530 {
1531 while (*url) {
1532 if (*url=='&')
1533 fputs("&amp;",fp_ou);
1534 else
1535 fputc(*url,fp_ou);
1536 url++;
1537 }
1538 }
1539
1540 void baddata(void)
1541 {
1542 char dir[1024];
1543
1544 printf("SARG: ------------------------------------------------------------------------------\n");
1545 printf(_("SARG: MALICIUS CODE DETECTED.\n"));
1546 printf(_("SARG: I think someone is trying to execute arbitrary code in your system using sarg.\n"));
1547 printf(_("SARG: please review your access.log and/or your useragent.log file.\n"));
1548 printf(_("SARG: process stoped. No actions taken.\n"));
1549 printf("SARG: ------------------------------------------------------------------------------\n");
1550
1551 if (snprintf(dir,sizeof(dir),"%s/sarg",tmp)>=sizeof(dir)) {
1552 debuga(_("temporary directory too long: %s/sarg\n"),tmp);
1553 exit(EXIT_FAILURE);
1554 }
1555 unlinkdir(dir,0);
1556 unlinkdir(outdirname,0);
1557
1558 exit(EXIT_FAILURE);
1559 }
1560
1561 void url_hostname(const char *url,char *hostname,int hostsize)
1562 {
1563 int i;
1564
1565 hostsize--;
1566 for (i=0 ; i<hostsize && url[i] && url[i]!='/' ; i++)
1567 hostname[i]=url[i];
1568 hostname[i]='\0';
1569 }
1570
1571 void url_module(const char *url, char *w2)
1572 {
1573 int x, y;
1574 char w[255];
1575
1576 y=0;
1577 for(x=strlen(url)-1; x>=0; x--) {
1578 if(url[x] == '/' || y>=sizeof(w)-1) break;
1579 w[y++]=url[x];
1580 }
1581 if (x<0) {
1582 w2[0]='\0';
1583 return;
1584 }
1585
1586 x=0;
1587 for(y=y-1; y>=0; y--) {
1588 w2[x++]=w[y];
1589 }
1590 w2[x]='\0';
1591 }
1592
1593 void url_to_file(const char *url,char *file,int filesize)
1594 {
1595 int i,skip;
1596
1597 filesize--;
1598 skip=0;
1599 for(i=0; i<filesize && *url; url++) {
1600 if(*url=='?' || *url=='-' || *url=='.' || *url==':' || *url=='/' || *url=='\\' ||
1601 *url=='*' || *url=='\'' || *url=='\"' || *url=='$') {
1602 if (!skip) file[i++]='_';
1603 skip=1;
1604 } else {
1605 file[i++]=*url;
1606 skip=0;
1607 }
1608 }
1609 file[i]='\0';
1610 }
1611
1612 void version(void)
1613 {
1614 printf(_("SARG Version: %s\n"),VERSION);
1615 exit(EXIT_SUCCESS);
1616 }
1617
1618 char *get_param_value(const char *param,char *line)
1619 {
1620 int plen;
1621
1622 while (*line==' ' || *line=='\t') line++;
1623 plen=strlen(param);
1624 if (strncasecmp(line,param,plen)) return(NULL);
1625 if (line[plen]!=' ' && line[plen]!='\t') return(NULL);
1626 line+=plen;
1627 while (*line==' ' || *line=='\t') line++;
1628 return(line);
1629 }
1630
1631 void unlinkdir(const char *dir,int contentonly)
1632 {
1633 struct stat st;
1634 DIR *dirp;
1635 struct dirent *direntp;
1636 char dname[MAXLEN];
1637 int err;
1638
1639 dirp=opendir(dir);
1640 if (!dirp) return;
1641 while ((direntp = readdir(dirp)) != NULL) {
1642 if (direntp->d_name[0] == '.' && (direntp->d_name[1] == '\0' ||
1643 (direntp->d_name[1] == '.' && direntp->d_name[2] == '\0')))
1644 continue;
1645 if (snprintf(dname,sizeof(dname),"%s/%s",dir,direntp->d_name)>=sizeof(dname)) {
1646 debuga(_("directory name to delete too long: %s/%s\n"),dir,direntp->d_name);
1647 exit(EXIT_FAILURE);
1648 }
1649 #ifdef HAVE_LSTAT
1650 err=lstat(dname,&st);
1651 #else
1652 err=stat(dname,&st);
1653 #endif
1654 if (err) {
1655 debuga(_("cannot stat %s\n"),dname);
1656 exit(EXIT_FAILURE);
1657 }
1658 if (S_ISREG(st.st_mode)) {
1659 if (unlink(dname)) {
1660 debuga(_("cannot delete %s - %s\n"),dname,strerror(errno));
1661 exit(EXIT_FAILURE);
1662 }
1663 } else if (S_ISDIR(st.st_mode)) {
1664 unlinkdir(dname,0);
1665 } else {
1666 debuga(_("unknown path type %s\n"),dname);
1667 }
1668 }
1669 closedir(dirp);
1670
1671 if (!contentonly) {
1672 if (rmdir(dir)) {
1673 debuga(_("cannot delete %s - %s\n"),dir,strerror(errno));
1674 exit(EXIT_FAILURE);
1675 }
1676 }
1677 }
1678