]> git.ipfire.org Git - thirdparty/sarg.git/blob - util.c
a69968caba4d7786f32405753e1b18c868d6852e
[thirdparty/sarg.git] / util.c
1 /*
2 * AUTHOR: Pedro Lineu Orso pedro.orso@gmail.com
3 * 1998, 2008
4 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
5 *
6 * SARG donations:
7 * please look at http://sarg.sourceforge.net/donations.php
8 * ---------------------------------------------------------------------
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
23 *
24 */
25
26 // #define LEGACY_MY_ATOLL
27 // #define LEGACY_TESTVALIDUSERCHAR
28
29 #include "include/conf.h"
30 #include "include/defs.h"
31
32 static char mtab1[12][4]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
33
34 //! The list of the HTTP codes to exclude from the report.
35 static char *excludecode=NULL;
36
37 /*void fgetword(char *word, char *line, int stop)
38 {
39 //VARIANT N1
40 int x;
41
42 for (x=0; line[x] && (line[x] != stop); x++) word[x] = line[x];
43 word[x] = '\0';
44
45 //VARIANT N2
46 char *tchar;
47 int difflen;
48
49 tchar = strchr(line, stop);
50 if (tchar == NULL) strcpy(word, line);
51 else
52 {
53 difflen = tchar - line;
54 strncpy(word, line, difflen);
55 word[difflen] = '\0';
56 }
57 }*/
58
59 int getword(char *word, int limit, char *line, int stop)
60 {
61 int x = 0,y;
62
63 /*if(strlen(line) < 3) {
64 word[0]='\0';
65 return(0);
66 }*/
67
68 for(x=0;((line[x]) && (line[x] != stop ));x++) {
69 if(x>=limit) {
70 printf("SARG: getword loop detected after %d bytes.\n",x);
71 printf("SARG: Record=\"%s\"\n",line);
72 printf("SARG: searching for \'x%x\'\n",stop);
73 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
74 if (limit>0) word[limit-1]='\0';
75 //exit(1);
76 return(-1);
77 }
78 word[x] = line[x];
79 }
80
81 word[x] = '\0';
82 if (line[x]) ++x;
83 y=0;
84
85 while((line[y++] = line[x++]));
86 return(0);
87 }
88
89 int getword_multisep(char *word, int limit, char *line, int stop)
90 {
91 int x = 0,y;
92
93 for(x=0;((line[x]) && (line[x] != stop ));x++) {
94 if(x>=limit) {
95 printf("SARG: getword_multisep loop detected.\n");
96 printf("SARG: Record=\"%s\"\n",line);
97 printf("SARG: searching for \'x%x\'\n",stop);
98 printf("SARG: searching for \'x%x\'\n",stop);
99 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
100 if (limit>0) word[limit-1]='\0';
101 //exit(1);
102 return(-1);
103 }
104 word[x] = line[x];
105 }
106
107 word[x] = '\0';
108 while (line[x] && line[x]==stop) ++x;
109 y=0;
110
111 while((line[y++] = line[x++]));
112 return(0);
113 }
114
115 int getword3(char *word, int limit, char *line, int stop)
116 {
117 int x = 0, y = 0;
118
119 for(x=0; x<limit && (line[x] && (line[x] != stop)) ; x++) word[x] = line[x];
120 if(x>=limit) {
121 printf("SARG: getword3 loop detected after %d bytes.\n",x);
122 printf("SARG: Buffer=\"%s\"\n",line);
123 printf("SARG: searching for \'x%x\'\n",stop);
124 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
125 //exit(1);
126 return(-1);
127 }
128 word[x] = '\0';
129 if(line[x]) ++x;
130 while((line[y++] = line[x++]));
131 return(0);
132 }
133
134
135 #ifdef LEGACY_MY_ATOLL
136
137 // BMG (bguillory@email.com)
138 // 3 August 1999
139 long long int my_atoll (const char *nptr)
140 #define MAXLLL 30 //maximum number of digits in long long (a guess)
141 {
142 int offset=0, x;
143 long long int returnval=0;
144 char one_digit[2];
145
146 one_digit[1]='\0';
147
148 // Soak up all the white space
149 while (isspace(nptr[offset])) {
150 offset++;
151 } //while
152
153 //For each character left to right
154 //change the character to a single digit
155 //multiply what we had before by 10 and add the new digit
156 for(x=offset; x<=MAXLLL+offset && isdigit(nptr[x]); x++) {
157 sprintf(one_digit, "%c", nptr[x]); //I don't know how else to do this
158 returnval = (returnval * 10) + atoi(one_digit);
159 } //for
160
161 return returnval;
162
163 } //my_atoll
164
165 #else
166
167 #define MAXLLL 30 //!< Maximum number of digits in long long (a guess).
168 long long int my_atoll (const char *nptr)
169 {
170 long long int returnval=0;
171 const char * t = nptr ;
172 int max_digits = MAXLLL ;
173
174 // Soak up all the white space
175 while (isspace( *t )) {
176 t++;
177 } //while
178
179 //For each character left to right
180 //change the character to a single digit
181 //multiply what we had before by 10 and add the new digit
182
183 for( ; --max_digits && isdigit( *t ) ; t++ )
184 {
185 returnval = ( returnval * 10 ) + ( *t - '0' ) ;
186 }
187
188 return returnval;
189
190 } //my_atoll
191
192 #endif
193
194
195 void my_mkdir(const char *name)
196 {
197 char w0[255];
198 char w1[255];
199 char w2[255];
200
201 if(strncmp(name,".",1) == 0 || strncmp(name,"/",1) != 0) {
202 fprintf(stderr,"SARG: Invalid path (%s). Please, use absolute paths only.\n",name);
203 fprintf(stderr,"SARG: process aborted.\n");
204 exit(1);
205 }
206
207 strcpy(w0,name);
208 strcpy(w2,"/");
209 if (getword_multisep(w1,sizeof(w1),w0,'/')<0) {
210 printf("SARG: Maybe you have a broken record or garbage in the directory name %s.\n",name);
211 exit(1);
212 }
213 while(strchr(w0,'/')) {
214 if (getword_multisep(w1,sizeof(w1),w0,'/')<0) {
215 printf("SARG: Maybe you have a broken record or garbage in the directory name %s.\n",name);
216 exit(1);
217 }
218 strcat(w2,w1);
219 if(access(w2, R_OK) != 0) {
220 if(mkdir(w2,0755)) {
221 fprintf(stderr,"SARG: mkdir %s %s\n",w2,strerror(errno));
222 fprintf(stderr,"SARG: process aborted.\n");
223 exit(1);
224 }
225 }
226 strcat(w2,"/");
227 }
228 strcat(w2,w0);
229 if(access(w2, R_OK) != 0) {
230 if(mkdir(w2,0755)) {
231 fprintf(stderr,"SARG: mkdir %s %s\n",w2,strerror(errno));
232 fprintf(stderr,"SARG: process aborted.\n");
233 exit(1);
234 }
235 }
236 }
237
238
239 void my_lltoa(unsigned long long int n, char s[], int len)
240 {
241 int i = 0;
242 int x = 0;
243 char ww[50];
244 do {
245 s[i++] = (n % 10) + '0';
246 } while ((n /= 10) > 0);
247 s[i] = '\0';
248 {
249 int c,i,j;
250 for (i = 0, j = strlen(s)-1; i<j; i++, j--)
251 {
252 c = s[i];
253 s[i] = s[j];
254 s[j] = c;
255 }
256 }
257
258 if(len) {
259 bzero(ww,sizeof(ww));
260 i=len-strlen(s)-1;
261 for(x=0; x<=i; x++)
262 ww[x]='0';
263 i=strlen(s);
264 strncat(ww,s,i>sizeof(ww)?sizeof(ww):i);
265 strcpy(s,ww);
266 }
267
268 }
269
270
271 void builddia(char *dia, const char *mes, const char *ano, const char *df, char *wdata)
272 {
273 char ndia[11];
274 int nmes;
275
276 if(strlen(dia) < 1) return;
277
278 for(nmes=0; nmes<12; nmes++) {
279 if(strcmp(mtab1[nmes],mes) == 0) {
280 break;
281 }
282 }
283 nmes++;
284
285 snprintf(wdata,9,"%s%02d%s",ano,nmes,dia);
286
287 if(df[0]!='u')
288 snprintf(ndia,sizeof(ndia),"%s/%02d/%s",dia,nmes,ano);
289 else
290 snprintf(ndia,sizeof(ndia),"%02d/%s/%s",nmes,dia,ano);
291
292 strcpy(dia,ndia);
293
294 }
295
296
297 void buildymd(const char *dia, const char *mes, const char *ano, char *wdata)
298 {
299 int nmes;
300
301 for(nmes=0; nmes<12; nmes++) {
302 if(strcmp(mtab1[nmes],mes) == 0)
303 break;
304 }
305
306 sprintf(wdata,"%s%02d%s",ano,nmes+1,dia);
307
308 }
309
310
311 void conv_month(char *month)
312 {
313 int x;
314
315 for(x=0; x<12 && strcmp(mtab1[x],month)!=0; x++);
316 sprintf(month,"%02d",x+1);
317
318 }
319
320
321 void conv_month_name(char *month)
322 {
323 int x;
324
325 x=atoi(month);
326 if (x>=1 && x<=12)
327 strcpy(month,mtab1[x-1]);
328 }
329
330
331 void name_month(char *month,int month_len)
332 {
333 int x, z=atoi(month)-1;
334 char m[255];
335 char w[20];
336
337 strcpy(m,text[133]);
338
339 for(x=0; x<z; x++)
340 if (getword_multisep(w,sizeof(w),m,',')<0) {
341 printf("SARG: Maybe you have a broken record or garbage in the names of the months.\n");
342 exit(1);
343 }
344 if (getword_multisep(month,month_len,m,',')<0) {
345 printf("SARG: Maybe you have a broken record or garbage in the name of the months.\n");
346 exit(1);
347 }
348 }
349
350
351 void fixper(char *tbuf, char *period, const char *duntil)
352 {
353
354 char warea[50];
355 char dia[5], mes[5], ano[5];
356 int x;
357
358 warea[0]='\0';
359
360 strncpy(dia,duntil+6,2);
361 dia[2]='\0';
362 strncpy(mes,duntil+4,2);
363 mes[2]='\0';
364 strncpy(ano,duntil,4);
365 ano[4]='\0';
366
367 x=atoi(mes);
368 if (x>=1 && x<=12)
369 strcpy(mes,mtab1[x-1]);
370
371 if(strcmp(df,"e") == 0)
372 sprintf(warea,"%s%s%s",dia,mes,ano);
373 if(strcmp(df,"u") == 0)
374 sprintf(warea,"%s%s%s",mes,dia,ano);
375
376 strcat(period,warea);
377 }
378
379
380 void debuga(const char *msg,...)
381 {
382 va_list ap;
383
384 fputs("SARG: ",stderr);
385 va_start(ap,msg);
386 vfprintf(stderr,msg,ap);
387 va_end(ap);
388 fputc('\n',stderr);
389 }
390
391
392 void debugaz(const char *head, const char *msg)
393 {
394 fprintf(stderr, "SARG: (util) %s=%s\n",head, msg);
395
396 }
397
398
399 void fixip(char *ip)
400 {
401 int i;
402 char sep='_';
403 char search=0;
404 int nrepl=0;
405
406 for (i=0; ip[i]; i++) {
407 if (ip[i]=='.') {
408 search='.';
409 sep='_';
410 break;
411 }
412 if (ip[i]=='_') {
413 search='_';
414 sep='.';
415 break;
416 }
417 }
418 for (; ip[i]; i++) {
419 if (ip[i]==search) {
420 ip[i]=sep;
421 nrepl++;
422 if (nrepl>=3) break;
423 }
424 }
425 }
426
427
428 char *fixnum(long long int value, int n)
429 {
430 #define MAXLEN_FIXNUM 1024
431 char num[MAXLEN_FIXNUM];
432 char buf[MAXLEN_FIXNUM * 2];
433 char *pbuf;
434 static char ret[MAXLEN_FIXNUM * 2];
435 char *pret;
436 register int i, j, k;
437 static char abbrev[30];
438
439 my_lltoa(value, num, 0);
440
441 if(strcmp(DisplayedValues,"abbreviation") == 0) {
442 if(strlen(num) <= 3)
443 sprintf(abbrev,"%s",num);
444 if(strlen(num) == 4 || strlen(num) == 7 || strlen(num) == 10 || strlen(num) == 13) {
445 snprintf(abbrev,2,"%s",num);
446 strncat(abbrev,".",1);
447 strncat(abbrev,num+1,2);
448 if(!n) return(abbrev);
449 if(strlen(num) == 4)
450 strncat(abbrev,"K",1);
451 else if(strlen(num) == 7)
452 strncat(abbrev,"M",1);
453 else if(strlen(num) == 10)
454 strncat(abbrev,"G",1);
455 else if(strlen(num) == 13)
456 strncat(abbrev,"T",1);
457 }
458 if(strlen(num) == 5 || strlen(num) == 8 || strlen(num) == 11 || strlen(num) == 14) {
459 snprintf(abbrev,3,"%s",num);
460 strncat(abbrev,".",1);
461 strncat(abbrev,num+2,2);
462 if(!n) return(abbrev);
463 if(strlen(num) == 5)
464 strncat(abbrev,"K",1);
465 else if(strlen(num) == 8)
466 strncat(abbrev,"M",1);
467 else if(strlen(num) == 11)
468 strncat(abbrev,"G",1);
469 else if(strlen(num) == 14)
470 strncat(abbrev,"T",1);
471 }
472 if(strlen(num) == 6 || strlen(num) == 9 || strlen(num) == 12 || strlen(num) == 15) {
473 snprintf(abbrev,4,"%s",num);
474 strncat(abbrev,".",1);
475 strncat(abbrev,num+3,2);
476 if(!n) return(abbrev);
477 if(strlen(num) == 6)
478 strncat(abbrev,"K",1);
479 else if(strlen(num) == 9)
480 strncat(abbrev,"M",1);
481 else if(strlen(num) == 12)
482 strncat(abbrev,"G",1);
483 else if(strlen(num) == 15)
484 strncat(abbrev,"T",1);
485 }
486
487 return(abbrev);
488 }
489
490 bzero(buf, MAXLEN_FIXNUM*2);
491
492 pbuf = buf;
493 pret = ret;
494 k = 0;
495
496 for ( i = strlen(num) - 1, j = 0 ; i > -1; i--) {
497 if ( k == 2 && i != 0 ) {
498 k = 0;
499 pbuf[j++] = num[i];
500 if(strcmp(UseComma,"yes") == 0)
501 pbuf[j++] = ',';
502 else pbuf[j++] = '.';
503 continue;
504 }
505 pbuf[j] = num[i];
506 j++;
507 k++;
508 }
509
510 pret[0]='\0';
511
512 for ( i = strlen(pbuf) - 1, j = 0 ; i > -1; i--, j++)
513 pret[j] = pbuf[i];
514
515 pret[j] = '\0';
516
517 return pret;
518 }
519
520
521 char *fixnum2(long long int value, int n)
522 {
523 #define MAXLEN_FIXNUM2 1024
524 char num[MAXLEN_FIXNUM2];
525 char buf[MAXLEN_FIXNUM2 * 2];
526 char *pbuf;
527 static char ret[MAXLEN_FIXNUM2 * 2];
528 char *pret;
529 register int i, j, k;
530
531 my_lltoa(value, num, 0);
532 bzero(buf, MAXLEN_FIXNUM2*2);
533
534 pbuf = buf;
535 pret = ret;
536 k = 0;
537
538 for ( i = strlen(num) - 1, j = 0 ; i > -1; i--) {
539 if ( k == 2 && i != 0 ) {
540 k = 0;
541 pbuf[j++] = num[i];
542 if(strcmp(UseComma,"yes") == 0)
543 pbuf[j++] = ',';
544 else pbuf[j++] = '.';
545 continue;
546 }
547 pbuf[j] = num[i];
548 j++;
549 k++;
550 }
551
552 pret[0]='\0';
553
554 for ( i = strlen(pbuf) - 1, j = 0 ; i > -1; i--, j++)
555 pret[j] = pbuf[i];
556
557 pret[j] = '\0';
558
559 return pret;
560 }
561
562
563
564 void buildhref(char * href)
565 {
566 char whref[MAXLEN];
567
568 if(strcmp(href,"./") == 0){
569 href[0]='\0';
570 strcat(href,"<a href='");
571 return;
572 }
573
574 href[strlen(href)-1]='\0';
575 sprintf(whref,"%s",strrchr(href,'/'));
576
577 strcpy(href,"<a href='");
578 strcat(href,whref);
579 strcat(href,"/");
580
581 return;
582
583 }
584
585
586 char *buildtime(long long int elap)
587 {
588
589 int num = elap / 1000;
590 int hor = 0;
591 int min = 0;
592 int sec = 0;
593 static char buf[12];
594
595 buf[0]='\0';
596
597 hor=num / 3600;
598 min=(num % 3600) / 60;
599 sec=num % 60;
600 sprintf(buf,"%02d:%02d:%02d",hor,min,sec);
601
602 return(buf);
603
604 }
605
606
607 void obtdate(const char *dirname, const char *name, char *data)
608 {
609
610 FILE *fp_in;
611 char wdir[MAXLEN];
612
613 sprintf(wdir,"%s%s/sarg-date",dirname,name);
614 if ((fp_in = fopen(wdir, "r")) == 0) {
615 sprintf(wdir,"%s%s/date",dirname,name);
616 if ((fp_in = fopen(wdir, "r")) == 0) {
617 data[0]='\0';
618 return;
619 }
620 }
621
622 fgets(data,80,fp_in);
623 fclose(fp_in);
624 data[strlen(data)-1]='\0';
625
626 return;
627
628 }
629
630
631 void obtuser(const char *dirname, const char *name, char *tuser)
632 {
633
634 FILE *fp_in;
635 char wdir[MAXLEN];
636
637 sprintf(wdir,"%s%s/sarg-users",dirname,name);
638 if((fp_in=fopen(wdir,"r"))==NULL) {
639 sprintf(wdir,"%s%s/users",dirname,name);
640 if((fp_in=fopen(wdir,"r"))==NULL) {
641 tuser[0]='\0';
642 return;
643 }
644 }
645
646 fgets(tuser,20,fp_in);
647 tuser[strlen(tuser)-1]='\0';
648 fclose(fp_in);
649
650 return;
651
652 }
653
654
655 void obttotal(const char *dirname, const char *name, char *tbytes, char *tuser, char *media)
656 {
657
658 FILE *fp_in;
659 char wdir[MAXLEN];
660 long long int med=0;
661 long long int wtuser=0;
662 long long int twork;
663
664 sprintf(wdir,"%s%s/sarg-general",dirname,name);
665 if ((fp_in = fopen(wdir, "r")) == 0) {
666 sprintf(wdir,"%s%s/general",dirname,name);
667 if ((fp_in = fopen(wdir, "r")) == 0) {
668 tbytes=0;
669 return;
670 }
671 }
672
673 while(fgets(buf,sizeof(buf),fp_in)!=NULL) {
674 if (getword_multisep(warea,sizeof(warea),buf,' ')<0) {
675 printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",wdir);
676 exit(1);
677 }
678 if(strcmp(warea,"TOTAL") != 0)
679 continue;
680 if (getword_multisep(warea,sizeof(warea),buf,' ')<0) {
681 printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",wdir);
682 exit(1);
683 }
684 if (getword_multisep(warea,sizeof(warea),buf,' ')<0) {
685 printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",wdir);
686 exit(1);
687 }
688 twork=my_atoll(warea);
689 strcpy(tbytes,fixnum(twork,1));
690 }
691 fclose(fp_in);
692
693 wtuser=my_atoll(tuser);
694 if(wtuser == 0) {
695 strcpy(media,"0");
696 return;
697 }
698
699 med=my_atoll(warea) / wtuser;
700 strcpy(media,fixnum(med,1));
701
702 return;
703
704 }
705
706
707 void gperiod(const char *dirname, const char *period)
708 {
709
710 FILE *fp_ou;
711 char wdirname[MAXLEN];
712
713 strcpy(wdirname,dirname);
714 strcat(wdirname,"/");
715 strcat(wdirname,"sarg-period");
716
717 if((fp_ou=fopen(wdirname,"w"))==NULL){
718 fprintf(stderr, "SARG: (report) %s: %s\n",text[45],wdirname);
719 exit(1);
720 }
721
722 fputs(period,fp_ou);
723 fclose(fp_ou);
724
725 if(debug)
726 debuga("%s",(char *)text[50]);
727
728 return;
729
730 }
731
732 void vrfydir(const char *dir, const char *per1, const char *addr, const char *site, const char *us, const char *form)
733 {
734 FILE *img_in, *img_ou;
735 int num=1, count=0;
736 int c;
737 char wdir[MAXLEN];
738 char per2[MAXLEN];
739 char dirname2[MAXLEN];
740 char images[512];
741 DIR *dirp;
742 struct dirent *direntp;
743 int cstatus;
744 char y1[5], y2[5];
745 char d1[3], d2[3];
746 char m1[4], m2[4];
747
748 if(strcmp(IndexTree,"date") == 0) {
749 bzero(y1,5);
750 bzero(y2,5);
751 bzero(d1,3);
752 bzero(d2,3);
753 bzero(m1,4);
754 bzero(m2,4);
755 if(strncmp(df,"u",1) == 0) {
756 strncpy(y1,period,4);
757 strncpy(y2,period+10,4);
758 strncpy(m1,period+4,3);
759 strncpy(m2,period+14,3);
760 strncpy(d1,period+7,2);
761 strncpy(d2,period+17,2);
762 } else if(strncmp(df,"e",1) == 0) {
763 strncpy(d1,period+0,2);
764 strncpy(d2,period+10,2);
765 strncpy(m1,period+2,3);
766 strncpy(m2,period+12,3);
767 strncpy(y1,period+5,4);
768 strncpy(y2,period+15,4);
769 }
770 conv_month(m1);
771 conv_month(m2);
772
773 sprintf(wdir,"%s%s",outdir,y1);
774 if(strcmp(y1,y2) != 0) {
775 strncat(wdir,"-",1);
776 strncat(wdir,y2,strlen(y2));
777 }
778 if(access(wdir, R_OK) != 0)
779 my_mkdir(wdir);
780
781 strncat(wdir,"/",1);
782 strncat(wdir,m1,strlen(m1));
783 if(strcmp(m1,m2) != 0) {
784 strncat(wdir,"-",1);
785 strncat(wdir,m2,strlen(m2));
786 }
787 if(access(wdir, R_OK) != 0)
788 my_mkdir(wdir);
789
790 strncat(wdir,"/",1);
791 strncat(wdir,d1,strlen(d1));
792 if(strcmp(d1,d2) != 0) {
793 strncat(wdir,"-",1);
794 strncat(wdir,d2,strlen(d2));
795 }
796 } else
797 strcpy(wdir,dir);
798
799 if(strlen(us) > 0) {
800 strcat(wdir,"-");
801 strcat(wdir,us);
802 }
803 if(strlen(addr) > 0) {
804 strcat(wdir,"-");
805 strcat(wdir,addr);
806 }
807 if(strlen(site) > 0) {
808 strcat(wdir,"-");
809 strcat(wdir,site);
810 }
811
812 if(strcmp(dirname,wdir) != 0)
813 strcpy(dirname,wdir);
814
815 if(strcmp(IndexTree,"date") != 0) {
816 strcpy(dirname2,dirname);
817 if(strcmp(OverwriteReport,"no") == 0) {
818 while(num) {
819 if(access(wdir,R_OK) == 0) {
820 sprintf(wdir,"%s.%d",dirname,num);
821 sprintf(per2,"%s.%d",per1,num);
822 num++;
823 count++;
824 } else
825 break;
826 }
827
828 if(count > 0) {
829 if(debug)
830 fprintf(stderr, "SARG: %s: %s %s %s\n",text[51],dirname2,text[52],wdir);
831 rename(dirname2,wdir);
832 }
833 } else {
834 if(access(dir,R_OK) == 0) {
835 sprintf(csort,"rm -r %s",dir);
836 system(csort);
837 }
838 }
839 my_mkdir(dirname);
840 } else {
841 strcpy(dirname2,wdir);
842 if(strcmp(OverwriteReport,"no") == 0) {
843 while(num) {
844 if(access(wdir,R_OK) == 0) {
845 sprintf(wdir,"%s.%d",dirname2,num);
846 sprintf(per2,"%s.%d",per1,num);
847 num++;
848 count++;
849 } else
850 break;
851 }
852
853 if(count > 0) {
854 if(debug)
855 fprintf(stderr, "SARG: %s: %s %s %s\n",text[51],dirname2,text[52],wdir);
856 rename(dirname2,wdir);
857 strcpy(dirname2,wdir);
858 }
859 } else {
860 if(access(wdir,R_OK) == 0) {
861 sprintf(csort,"rm -r %s",wdir);
862 system(csort);
863 }
864 }
865
866 if(access(wdir, R_OK) != 0)
867 my_mkdir(wdir);
868 }
869
870 strcpy(dirname2,wdir);
871 sprintf(images,"%simages",outdir);
872 mkdir(images,0755);
873
874 sprintf(wdir,"date \"+%%a %%b %%d %%H:%%M:%%S %%Z %%Y\" >%s/sarg-date",dirname);
875 cstatus=system(wdir);
876 if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
877 fprintf(stderr, "SARG: command return status %d\n",WEXITSTATUS(cstatus));
878 fprintf(stderr, "SARG: command: %s\n",wdir);
879 exit(1);
880 }
881
882 sprintf(per2,"%s/images",SYSCONFDIR);
883
884 dirp = opendir(per2);
885 if(dirp==NULL) {
886 fprintf(stderr, "SARG: (util) %s %s: %s\n","Can't open directory", per2,strerror(errno));
887 return;
888 }
889 while ((direntp = readdir( dirp )) != NULL ){
890 if(strncmp(direntp->d_name,".",1) == 0)
891 continue;
892 sprintf(val10,"%s/%s",per2,direntp->d_name);
893 sprintf(val11,"%s/%s",images,direntp->d_name);
894 img_in = fopen(val10, "rb");
895 if(img_in!=NULL) {
896 img_ou = fopen(val11, "wb");
897 if(img_ou!=NULL) {
898 while ((c = fgetc(img_in))!=EOF) {
899 fputc(c,img_ou);
900 }
901 fclose(img_ou);
902 } else
903 fprintf(stderr,"SARG: (util): %s %s: %s\n", text[45]?text[45]:"Can't open/create file", val11, strerror(errno));
904 fclose(img_in);
905 } else
906 fprintf(stderr,"SARG: (util): %s %s: %s\n", text[45]?text[45]:"Can't open file", val10, strerror(errno));
907 }
908 (void) rewinddir(dirp);
909 (void) closedir(dirp);
910
911 return;
912
913
914 }
915
916
917 void strip_latin(char *line)
918 {
919 char buf[255];
920 char warea[255];
921
922 while(strstr(line,"&") != 0){
923 if (getword_multisep(warea,sizeof(warea),line,'&')<0) {
924 printf("SARG: Maybe you have a broken record or garbage in a line to strip from HTML entities.\n");
925 exit(1);
926 }
927 strncat(warea,line,1);
928 if (getword_multisep(buf,sizeof(buf),line,';')<0) {
929 printf("SARG: Maybe you have a broken record or garbage in a line to strip from HTML entities.\n");
930 exit(1);
931 }
932 strcat(warea,line);
933 strcpy(line,warea);
934 }
935
936 return;
937
938 }
939
940 void zdate(char *ftime, const char *DateFormat)
941 {
942
943 time_t t;
944 struct tm *local;
945
946 t = time(NULL);
947 local = localtime(&t);
948 if(strcmp(DateFormat,"u") == 0)
949 strftime(ftime, 127, "%b/%d/%Y %H:%M", local);
950 if(strcmp(DateFormat,"e") == 0)
951 strftime(ftime, 127, "%d/%b/%Y-%H:%M", local);
952 if(strcmp(DateFormat,"w") == 0)
953 strftime(ftime, 127, "%V-%H-%M", local);
954
955 return;
956 }
957
958
959 char *fixtime(long int elap)
960 {
961
962 int num = elap / 1000;
963 int hor = 0;
964 int min = 0;
965 int sec = 0;
966 static char buf[12];
967
968 if(strcmp(datetimeby,"bytes") == 0) {
969 strcpy(buf,fixnum(elap,1));
970 return buf;
971 }
972
973 if(num<1) {
974 sprintf(buf,"00:00:%02ld",elap);
975 return buf;
976 }
977
978 hor=num / 3600;
979 min=(num % 3600) / 60;
980 sec=num % 60;
981
982 if(hor==0 && min==0 && sec==0)
983 strcpy(buf,"0");
984 else
985 sprintf(buf,"%01d:%02d:%02d",hor,min,sec);
986
987 return buf;
988
989 }
990
991
992 void date_from(char *date, char *dfrom, char *duntil)
993 {
994
995 char diaf[10];
996 char mesf[10];
997 char anof[10];
998 char diau[10];
999 char mesu[10];
1000 char anou[10];
1001 static char wdate[50];
1002
1003
1004 strcpy(wdate,date);
1005 if(strchr(wdate,'-') == NULL) {
1006 strcat(wdate,"-");
1007 strcat(wdate,date);
1008 strcpy(date,wdate);
1009 }
1010
1011 if (getword(diaf,sizeof(diaf),wdate,'/')<0 || getword(mesf,sizeof(mesf),wdate,'/')<0 || getword(anof,sizeof(anof),wdate,'-')<0 ||
1012 getword(diau,sizeof(diau),wdate,'/')<0 || getword(mesu,sizeof(mesu),wdate,'/')<0 || getword(anou,sizeof(anou),wdate,0)<0) {
1013 printf("SARG: Maybe you have a broken record or garbage in a date.\n");
1014 exit(1);
1015 }
1016
1017 sprintf(dfrom,"%s%s%s",anof,mesf,diaf);
1018 sprintf(duntil,"%s%s%s",anou,mesu,diau);
1019 return;
1020 }
1021
1022
1023 char *strlow(char *string)
1024 {
1025 char *s;
1026
1027 if (string)
1028 {
1029 for (s = string; *s; ++s)
1030 *s = tolower(*s);
1031 }
1032
1033 return string;
1034 }
1035
1036
1037
1038
1039 char *strup(char *string)
1040 {
1041 char *s;
1042
1043 if (string)
1044 {
1045 for (s = string; *s; ++s)
1046 *s = toupper(*s);
1047 }
1048
1049 return string;
1050 }
1051
1052
1053 void subs(char *str, int size, char *from, char *to)
1054 {
1055 char *tmp;
1056 int i;
1057 int ss, st, sf;
1058 int len;
1059 int shift;
1060
1061 tmp = strstr(str, from);
1062 if(tmp == NULL)
1063 return;
1064
1065 ss = strlen(str);
1066 sf = strlen(from);
1067 st = strlen(to);
1068 shift=st-sf;
1069
1070 if (shift>0) {
1071 if (ss+shift>=size){
1072 fprintf(stderr,"SARG: Cannot replace %s by %s in %s and fit within %d bytes\n",from,to,str,size);
1073 exit(1);
1074 }
1075 for (i=strlen(tmp) ; i>=sf ; i--)
1076 tmp[i+shift]=tmp[i];
1077 } else if (shift<0) {
1078 len=strlen(tmp);
1079 for (i=sf ; i<=len ; i++)
1080 tmp[i+shift]=tmp[i];
1081 }
1082 memcpy(tmp, to, st);
1083 return;
1084 }
1085
1086
1087 void removetmp(const char *outdir)
1088 {
1089
1090 FILE *fp_in;
1091 char warea[256];
1092
1093 if(strcmp(RemoveTempFiles,"yes") != 0)
1094 return;
1095
1096 if(debug) {
1097 debuga("%s: sarg-general, sarg-period",text[82]);
1098 }
1099 if (snprintf(warea,sizeof(warea),"%s/sarg-general",outdir)>=sizeof(warea)) {
1100 fprintf(stderr, "SARG: (removetmp) directory too long to remove: %s/sarg-period\n",outdir);
1101 exit(1);
1102 }
1103 if((fp_in=fopen(warea,"r"))==NULL){
1104 fprintf(stderr, "===SARG: (removetmp) %s: %s\n",text[45],warea);
1105 exit(1);
1106 }
1107 while(fgets(buf,sizeof(buf),fp_in)!=NULL) {
1108 if(strncmp(buf,"TOTAL",5) == 0)
1109 break;
1110 }
1111 fclose(fp_in);
1112 if((fp_in=fopen(warea,"w"))==NULL){
1113 fprintf(stderr, "SARG: (removetmp) %s: %s\n",text[45],warea);
1114 exit(1);
1115 }
1116 fputs(buf,fp_in);
1117 fclose(fp_in);
1118 if (snprintf(warea,sizeof(warea),"%s/sarg-period",outdir)>=sizeof(warea)) {
1119 fprintf(stderr, "SARG: (removetmp) directory too long to remove: %s/sarg-period\n",outdir);
1120 exit(1);
1121 }
1122 unlink(warea);
1123
1124 return;
1125 }
1126
1127 void load_excludecodes(const char *ExcludeCodes)
1128 {
1129
1130 FILE *fp_in;
1131 char data[80];
1132 int i;
1133
1134 if(ExcludeCodes[0] == '\0')
1135 return;
1136
1137 if((excludecode=(char *) malloc(1024))==NULL) {
1138 fprintf(stderr, "SARG: %s (1024):\n",text[59]);
1139 exit(1);
1140 }
1141 bzero(excludecode,1024);
1142
1143 if((fp_in=fopen(ExcludeCodes,"r"))==NULL) {
1144 fprintf(stderr, "SARG: (util) Cannot open file: %s (exclude_codes)\n",ExcludeCodes);
1145 exit(1);
1146 }
1147
1148 while(fgets(data,sizeof(data),fp_in)!=NULL) {
1149 for (i=strlen(data)-1 ; i>=0 && (unsigned char)data[i]<=' ' ; i--) data[i]=0;
1150 if (i<0) continue;
1151 strcat(excludecode,data);
1152 strcat(excludecode,";");
1153 }
1154
1155 fclose(fp_in);
1156 return;
1157
1158 }
1159
1160 void free_excludecodes(void)
1161 {
1162 if (excludecode) {
1163 free(excludecode);
1164 excludecode=NULL;
1165 }
1166 }
1167
1168 int vercode(const char *code)
1169 {
1170 char *cod;
1171 int clen;
1172
1173 if (excludecode && excludecode[0]!=0) {
1174 clen=strlen(code);
1175 for (cod=excludecode ; cod ; cod=strchr(cod+1,';')) {
1176 if (strncmp(code,cod,clen)==0 && cod[clen]==';')
1177 return 1;
1178 }
1179 }
1180 return 0;
1181 }
1182
1183 void fixnone(char *str)
1184 {
1185 int i;
1186
1187 for (i=strlen(str)-1 ; i>=0 && (unsigned char)str[i]<=' ' ; i--);
1188 if(i==3 && strncmp(str,"none",4) == 0)
1189 str[0]='\0';
1190
1191 return;
1192 }
1193
1194 #ifdef LEGACY_TESTVALIDUSERCHAR
1195 int testvaliduserchar(const char *user)
1196 {
1197
1198 int x=0;
1199 int y=0;
1200
1201 for (y=0; y<strlen(UserInvalidChar); y++) {
1202 for (x=0; x<strlen(user); x++) {
1203 if(user[x] == UserInvalidChar[y])
1204 return 1;
1205 }
1206 }
1207 return 0;
1208 }
1209 #else
1210 int testvaliduserchar(const char *user)
1211 {
1212
1213 char * p_UserInvalidChar = UserInvalidChar ;
1214 const char * p_user ;
1215
1216 while( *p_UserInvalidChar ) {
1217 p_user = user ;
1218 while ( *p_user ) {
1219 if( *p_UserInvalidChar == *p_user )
1220 return 1;
1221 p_user++ ;
1222 }
1223 p_UserInvalidChar++ ;
1224 }
1225 return 0;
1226 }
1227 #endif
1228
1229 int compar( const void *a, const void *b )
1230 { if( *(int *)a > *(int *)b ) return 1;
1231 if( *(int *)a < *(int *)b ) return -1;
1232 return 0;
1233 }
1234
1235 int getnumlist( char *buf, numlist *list, const int len, const int maxvalue )
1236 {
1237 int i, j, d, flag, r1, r2;
1238 char *pbuf, **bp, *strbufs[ 24 ];
1239
1240 bp = strbufs;
1241 strtok( buf, " \t" );
1242 for( *bp = strtok( NULL, "," ), list->len = 0; *bp; *bp = strtok( NULL, "," ) ) {
1243 if( ++bp >= &strbufs[ 24 ] )
1244 break;
1245 list->len++;
1246 }
1247 if( ! list->len )
1248 return -1;
1249 d = 0;
1250 for( i = 0; i < list->len; i++ ) {
1251 if( strchr( strbufs[ i ], '-' ) != 0 ) {
1252 pbuf = strbufs[ i ];
1253 strtok( pbuf, "-" );
1254 pbuf = strtok( NULL, "\0" );
1255 r1 = atoi( strbufs[ i ] );
1256 if( ( r2 = atoi( pbuf ) ) >= maxvalue || r1 >= r2 )
1257 return -1;
1258 if( i + d + ( r2 - r1 ) + 1 <= len ) {
1259 for( j = r1; j <= r2; j++ )
1260 list->list[ i + d++ ] = j;
1261 d--;
1262 }
1263 }
1264 else
1265 if( ( list->list[ i + d ] = atoi( strbufs[ i ] ) ) >= maxvalue )
1266 return 1;
1267 }
1268 list->len += d;
1269 qsort( list->list, list->len, sizeof( int ), compar );
1270 do {
1271 flag = 0;
1272 for( i = 0; i < list->len - 1; i++ )
1273 if( list->list[ i ] == list->list[ i + 1 ] ) {
1274 for( j = i + 1; j < list->len; j++ )
1275 list->list[ j - 1 ] = list->list[ j ];
1276 list->len--;
1277 flag = 1;
1278 break;
1279 }
1280 } while( flag );
1281 return 0;
1282 }
1283
1284
1285 void show_info(FILE *fp_ou)
1286 {
1287 char ftime[127];
1288
1289 if(strcmp(ShowSargInfo,"yes") != 0) return;
1290 zdate(ftime, DateFormat);
1291 fprintf(fp_ou,"<center><table><tr><td><br><br></td><td class=\"info\">%s <a href='%s'><font class=\"info\">%s-%s</font></a> %s %s</td></tr></table></center>\n",text[108],URL,PGM,VERSION,text[109],ftime);
1292 }
1293
1294 void show_sarg(FILE *fp_ou, const char *ind)
1295 {
1296 if(strcmp(ShowSargLogo,"yes") == 0) fprintf(fp_ou,"<center><table cellpadding=0 cellspacing=0>\n<tr><th class=\"logo\"><a href=\"http://sarg.sourceforge.net\"><img src=\"%s/images/sarg.png\" border=\"0\" align=\"absmiddle\" title=\"SARG, Squid Analysis Report Generator. Logo by Osamu Matsuzaki\"></a>&nbsp;<font class=\"logo\">Squid Analysis Report Generator</font></th></tr>\n<tr><th class=\"title\">&nbsp</th></tr>\n<table>\n",ind);
1297 }
1298
1299 char *get_size(const char *path, const char *file)
1300 {
1301 FILE *fp;
1302 char response[255];
1303 char cmd[255];
1304
1305 if (snprintf(cmd,sizeof(cmd),"du -skh %s%s",path,file)>=sizeof(cmd)) {
1306 printf("SARG: Cannot get disk space because the path %s%s is too long.\n",path,file);
1307 exit(1);
1308 }
1309 fp = popen(cmd, "r");
1310 fgets(response, sizeof(response), fp);
1311 if (getword_multisep(val5,sizeof(val5),response,'\t')<0) {
1312 printf("SARG: Maybe the command %s failed.\n",cmd);
1313 exit(1);
1314 }
1315 pclose(fp);
1316
1317 return (val5);
1318 }
1319
1320
1321 void write_html_header(FILE *fp_ou, const char * ind)
1322 {
1323 fprintf(fp_ou, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n</head>\n",CharSet);
1324 css(fp_ou);
1325 fprintf(fp_ou,"<body style=\"font-family:%s;font-size:%s;background-color:%s;background-image:url(%s)\">\n",FontFace,TitleFontSize,BgColor,BgImage);
1326 if(strlen(LogoImage) > 0) fprintf(fp_ou, "<center><table cellpadding=\"0\" cellspacing=\"0\">\n<tr><th class=\"logo\"><img src='%s' border=0 align=absmiddle width=%s height=%s>&nbsp;%s</th></tr>\n<tr><td height=\"5\"></td></tr>\n</table>\n",LogoImage,Width,Height,LogoText);
1327 show_sarg(fp_ou, ind);
1328 fprintf(fp_ou,"<center><table cellpadding=\"0\" cellspacing=\"0\">\n<tr><th class=\"title\">%s</th></tr>\n</table></center>\n<center><table cellpadding=\"1\" cellspacing=\"2\">\n<tr><td></td><td></td></tr>\n",Title);
1329 }
1330
1331 void baddata(void)
1332 {
1333 printf("SARG: ------------------------------------------------------------------------------\n");
1334 printf("SARG: MALICIUS CODE DETECTED.\n");
1335 printf("SARG: I think someone is trying to execute arbitrary code in your system using sarg.\n");
1336 printf("SARG: please review your access.log and/or your useragent.log file.\n");
1337 printf("SARG: process stoped. No actions taken.\n");
1338 printf("SARG: ------------------------------------------------------------------------------\n");
1339
1340 system("rm -rf /tmp/sarg");
1341 sprintf(tmp4,"rm -rf %s",dirname);
1342 system(tmp4);
1343 system("rm -rf /tmp/sarg");
1344
1345 exit(1);
1346 }
1347
1348
1349 void url_module(const char *url, char *w2)
1350 {
1351 int x, y;
1352 char w[255];
1353
1354 y=0;
1355 for(x=strlen(url)-1; x>=0; x--) {
1356 if(url[x] == '/' || y>=sizeof(w)-1) break;
1357 w[y++]=url[x];
1358 }
1359
1360 x=0;
1361 for(y=y-1; y>=0; y--) {
1362 w2[x++]=w[y];
1363 }
1364 w2[x]=0;
1365 }
1366
1367
1368 void write_html_trailer(FILE *fp_ou)
1369 {
1370 fputs("</table></center>\n",fp_ou);
1371 zdate(ftime, DateFormat);
1372 show_info(fp_ou);
1373 fputs("</body>\n</html>\n",fp_ou);
1374 }
1375
1376 void version(void)
1377 {
1378 printf("SARG Version: %s\n",VERSION);
1379 exit(0);
1380 }
1381
1382 char *get_param_value(const char *param,char *line)
1383 {
1384 int plen;
1385
1386 while (*line==' ' || *line=='\t') line++;
1387 plen=strlen(param);
1388 if (strncasecmp(line,param,plen)) return(NULL);
1389 if (line[plen]!=' ' && line[plen]!='\t') return(NULL);
1390 line+=plen;
1391 while (*line==' ' || *line=='\t') line++;
1392 return(line);
1393 }
1394
1395 void read_usertab(const char *UserTabFile)
1396 {
1397 FILE *fp_usr;
1398 unsigned int nreg;
1399 char buf[MAXLEN];
1400 char bufy[MAXLEN];
1401 int z2;
1402 int z1;
1403 int i;
1404
1405 if (UserTabFile[0] != '\0') {
1406 if(debug) {
1407 debuga("%s: %s",text[86],UserTabFile);
1408 }
1409 if((fp_usr=fopen(UserTabFile,"r"))==NULL) {
1410 fprintf(stderr, "SARG: (log) %s: %s - %s\n",text[45],UserTabFile,strerror(errno));
1411 exit(1);
1412 }
1413 fseek(fp_usr, 0, SEEK_END);
1414 nreg = ftell(fp_usr)+100;
1415 fseek(fp_usr, 0, SEEK_SET);
1416 if((userfile=(char *) malloc(nreg))==NULL){
1417 fprintf(stderr, "SARG ERROR: %s",text[87]);
1418 exit(1);
1419 }
1420 strcpy(userfile,"\t");
1421 z2=1;
1422 while(fgets(buf,sizeof(buf),fp_usr)!=NULL) {
1423 if (buf[0]=='#') continue;
1424 for (i=strlen(buf)-1 ; i>=0 && (unsigned char)buf[i]<=' ' ; i--) buf[i]=0;
1425 if (getword_multisep(bufy,sizeof(bufy),buf,' ')<0) {
1426 printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",UserTabFile);
1427 exit(1);
1428 }
1429 if (z2+strlen(bufy)+strlen(buf)+3>=nreg) {
1430 printf("SARG: The list of the users is too long in your %s file.\n",UserTabFile);
1431 exit(1);
1432 }
1433 for(z1=0; bufy[z1]; z1++)
1434 userfile[z2++]=bufy[z1];
1435 userfile[z2++]='\n';
1436 for(z1=0; buf[z1]; z1++)
1437 userfile[z2++]=buf[z1];
1438 userfile[z2++]='\t';
1439 }
1440 userfile[z2]=0;
1441 fclose(fp_usr);
1442 }
1443 }
1444
1445 void get_usertab_name(const char *user,char *name,int namelen)
1446 {
1447 char warea[MAXLEN];
1448 char *str;
1449
1450 namelen--;
1451 if(UserTabFile[0] == '\0') {
1452 strncpy(name,user,namelen);
1453 name[namelen]=0;
1454 } else {
1455 sprintf(warea,"\t%s\n",user);
1456 if((str=(char *) strstr(userfile,warea)) == (char *) NULL ) {
1457 strncpy(name,user,namelen);
1458 name[namelen]=0;
1459 } else {
1460 str=strchr(str+1,'\n');
1461 str++;
1462 for(z1=0; *str != '\t' && z1<namelen ; z1++) {
1463 name[z1]=*str++;
1464 }
1465 name[z1]=0;
1466 }
1467 }
1468 }
1469
1470 int is_download_suffix(const char *url)
1471 {
1472 int urllen;
1473 int i;
1474 char suffix[10];
1475 const char *str;
1476 int suflen;
1477
1478 if(DownloadSuffix[0]==0) return(0);
1479
1480 urllen=strlen(url)-1;
1481 for (i=0 ; i<sizeof(suffix)-1 && i<urllen ; i++) {
1482 if (url[urllen-i]=='.') {
1483 if (i==0) return(0); //detect a single trailing dot
1484 strcpy(suffix,url+urllen-i+1);
1485 suflen=strlen(suffix);
1486 for (str=DownloadSuffix ; str ; str=strchr(str,',')) {
1487 if (*str==',') str++;
1488 if(strncasecmp(str,suffix,suflen)==0 && (str[suflen]==',' || str[suflen]==0))
1489 return(1);
1490 }
1491 return(0);
1492 }
1493 }
1494 return(0);
1495 }
1496