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