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