]> git.ipfire.org Git - thirdparty/sarg.git/blame - util.c
Alias host names in URL and group identical names
[thirdparty/sarg.git] / util.c
CommitLineData
25697a35 1/*
94ff9470 2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
fbd133bb 3 * 1998, 2011
25697a35
GS
4 *
5 * SARG donations:
6 * please look at http://sarg.sourceforge.net/donations.php
1164c474
FM
7 * Support:
8 * http://sourceforge.net/projects/sarg/forums/forum/363374
25697a35
GS
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"
5f3cfd1d 31#include "include/defs.h"
25697a35 32
e6414a9d 33#if defined(HAVE_BACKTRACE)
ac422f9b 34#define USE_GETWORD_BACKTRACE 1
e6414a9d
FM
35#else
36#define USE_GETWORD_BACKTRACE 0
37#endif
38
25697a35 39static char mtab1[12][4]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
48864d28
FM
40
41//! The list of the HTTP codes to exclude from the report.
42static char *excludecode=NULL;
25697a35 43
e6414a9d
FM
44#if USE_GETWORD_BACKTRACE
45static void getword_backtrace(void)
46{
9bd92830
FM
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 }
e6414a9d
FM
61}
62#endif //USE_GETWORD_BACKTRACE
63
9c7c6346 64void getword_start(struct getwordstruct *gwarea, const char *line)
25697a35 65{
9bd92830
FM
66 gwarea->beginning=line;
67 gwarea->current=line;
68 gwarea->modified=0;
9c7c6346 69}
25697a35 70
9c7c6346 71void getword_restart(struct getwordstruct *gwarea)
25697a35 72{
9bd92830
FM
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;
9c7c6346 78}
25697a35 79
06b39c87 80int getword(char *word, int limit, struct getwordstruct *gwarea, char stop)
9c7c6346 81{
9bd92830 82 int x;
25697a35 83
9bd92830
FM
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';
e6414a9d 92#if USE_GETWORD_BACKTRACE
007905af 93 getword_backtrace();
e6414a9d 94#endif
9bd92830
FM
95 return(-1);
96 }
97 word[x] = gwarea->current[x];
98 }
25697a35 99
9bd92830
FM
100 word[x] = '\0';
101 if (gwarea->current[x]) ++x;
102 gwarea->current+=x;
103 return(0);
25697a35
GS
104}
105
06b39c87 106int getword_limit(char *word, int limit, struct getwordstruct *gwarea, char stop)
e5b2c6f0 107{
9bd92830 108 int x;
e5b2c6f0 109
9bd92830
FM
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);
e5b2c6f0
FM
119}
120
06b39c87 121int getword_multisep(char *word, int limit, struct getwordstruct *gwarea, char stop)
4bcb77cf 122{
9bd92830 123 int x;
4bcb77cf 124
9bd92830
FM
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';
e6414a9d 133#if USE_GETWORD_BACKTRACE
9bd92830 134 getword_backtrace();
e6414a9d 135#endif
9bd92830
FM
136 //exit(EXIT_FAILURE);
137 return(-1);
138 }
139 word[x] = gwarea->current[x];
140 }
4bcb77cf 141
9bd92830
FM
142 word[x] = '\0';
143 while (gwarea->current[x] && gwarea->current[x]==stop) ++x;
144 gwarea->current+=x;
145 return(0);
4bcb77cf
FM
146}
147
06b39c87 148int getword_skip(int limit, struct getwordstruct *gwarea, char stop)
076cbab8 149{
9bd92830 150 int x;
076cbab8 151
9bd92830
FM
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");
e6414a9d 159#if USE_GETWORD_BACKTRACE
9bd92830 160 getword_backtrace();
e6414a9d 161#endif
9bd92830
FM
162 return(-1);
163 }
164 }
076cbab8 165
9bd92830
FM
166 if (gwarea->current[x]) ++x;
167 gwarea->current+=x;
168 return(0);
076cbab8
FM
169}
170
06b39c87 171int getword_atoll(long long int *number, struct getwordstruct *gwarea, char stop)
25697a35 172{
9bd92830
FM
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");
e6414a9d 192#if USE_GETWORD_BACKTRACE
9bd92830 193 getword_backtrace();
e6414a9d 194#endif
9bd92830
FM
195 return(-1);
196 }
197 *number*=sign;
25697a35 198
9bd92830
FM
199 if (gwarea->current[x]) ++x;
200 gwarea->current+=x;
201 return(0);
0a4e18e1 202}
25697a35 203
25697a35 204
06b39c87 205int getword_ptr(char *orig_line,char **word, struct getwordstruct *gwarea, char stop)
e5b2c6f0 206{
9bd92830
FM
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);
e5b2c6f0
FM
231}
232
48864d28 233#define MAXLLL 30 //!< Maximum number of digits in long long (a guess).
25697a35
GS
234long long int my_atoll (const char *nptr)
235{
9bd92830
FM
236 long long int returnval=0LL;
237 int max_digits = MAXLLL ;
25697a35 238
9bd92830
FM
239 // Soak up all the white space
240 while (isspace( *nptr )) {
241 nptr++;
242 }
25697a35 243
9bd92830
FM
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
25697a35 247
9bd92830
FM
248 while (--max_digits && isdigit( *nptr ))
249 {
250 returnval = ( returnval * 10 ) + ( *nptr++ - '0' ) ;
251 }
25697a35 252
9bd92830 253 return returnval;
0a4e18e1 254}
25697a35 255
e6414a9d 256int is_absolute(const char *path)
6798f0a7 257{
9bd92830 258 if (*path=='/') return(1);
6798f0a7 259#ifdef WINDOWS
9bd92830 260 if (isalpha(path[0]) && path[1]==':') return(1);
6798f0a7 261#endif
9bd92830 262 return(0);
6798f0a7 263}
25697a35 264
32e71fa4 265void my_mkdir(const char *name)
25697a35 266{
9bd92830
FM
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';
affa72c5
FM
285 if (access(w0, R_OK) != 0) {
286 if (mkdir(w0,0755)) {
287 debuga(_("Cannot create directory %s - %s\n"),w0,strerror(errno));
9bd92830
FM
288 debuga(_("process aborted.\n"));
289 exit(EXIT_FAILURE);
290 }
291 }
292 }
293 if (name[i] != '/') chars++;
294 w0[i] = name[i];
295 }
296
affa72c5
FM
297 if (access(name, R_OK) != 0) {
298 if (mkdir(name,0755)) {
299 debuga(_("Cannot create directory %s - %s\n"),name,strerror(errno));
9bd92830
FM
300 debuga(_("process aborted.\n"));
301 exit(EXIT_FAILURE);
302 }
303 }
25697a35
GS
304}
305
306
e5b2c6f0 307void my_lltoa(unsigned long long int n, char *s, int ssize, int len)
25697a35 308{
9bd92830
FM
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 }
25697a35
GS
338}
339
fa6552b0 340int month2num(const char *month)
25697a35 341{
9bd92830 342 int m;
25697a35 343
9bd92830
FM
344 for(m=0 ; m<12 && strcmp(mtab1[m],month) != 0; m++);
345 return(m);
fa6552b0 346}
25697a35 347
fa6552b0
FM
348int builddia(int day, int month, int year)
349{
9bd92830 350 return(year*10000+month*100+day);
25697a35
GS
351}
352
353
32e71fa4 354void buildymd(const char *dia, const char *mes, const char *ano, char *wdata)
25697a35 355{
9bd92830 356 int nmes;
25697a35 357
9bd92830
FM
358 nmes=month2num(mes);
359 sprintf(wdata,"%04d%02d%02d",atoi(ano),nmes+1,atoi(dia));
25697a35
GS
360}
361
362
fa6552b0 363int conv_month(const char *month)
25697a35 364{
9bd92830 365 int x;
25697a35 366
9bd92830
FM
367 for(x=0; x<12 && strncmp(mtab1[x],month,3)!=0; x++);
368 return(x+1);
25697a35
GS
369}
370
371
fa6552b0 372const char *conv_month_name(int month)
25697a35 373{
9bd92830 374 static char str[4];
25697a35 375
9bd92830
FM
376 if (month<1 || month>12) {
377 snprintf(str,sizeof(str),"%03d",month);
378 return(str);
379 }
380 return(mtab1[month-1]);
25697a35
GS
381}
382
383
4bcb77cf 384void name_month(char *month,int month_len)
491b862f 385{
9bd92830
FM
386 int x, z=atoi(month)-1;
387 char m[255];
388 char w[20];
389 struct getwordstruct gwarea;
491b862f 390
9bd92830
FM
391 strcpy(m,_("January,February,March,April,May,June,July,August,September,October,November,December"));
392 getword_start(&gwarea,m);
491b862f 393
9bd92830
FM
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 }
491b862f
GS
403}
404
405
d2fe0c32 406void debuga(const char *msg,...)
25697a35 407{
9bd92830 408 va_list ap;
25697a35 409
9bd92830
FM
410 fputs(_("SARG: "),stderr);
411 va_start(ap,msg);
412 vfprintf(stderr,msg,ap);
413 va_end(ap);
25697a35
GS
414}
415
416
32e71fa4 417void debugaz(const char *head, const char *msg)
25697a35 418{
9bd92830 419 fprintf(stderr, "SARG: (util) %s=%s\n",head, msg);
25697a35
GS
420}
421
422
25697a35 423char *fixnum(long long int value, int n)
25697a35 424{
1b81f396 425#define MAXLEN_FIXNUM 256
9bd92830
FM
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;
25697a35
GS
513}
514
515
d6e703cc 516char *fixnum2(long long int value, int n)
d6e703cc 517{
32e71fa4 518#define MAXLEN_FIXNUM2 1024
9bd92830
FM
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;
2357ef77 525
9bd92830
FM
526 my_lltoa(value, num, sizeof(num), 0);
527 bzero(buf, MAXLEN_FIXNUM2*2);
d6e703cc 528
9bd92830
FM
529 pbuf = buf;
530 pret = ret;
531 k = 0;
d6e703cc 532
9bd92830
FM
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 }
d6e703cc 544
9bd92830 545 pret[0]='\0';
d6e703cc 546
9bd92830
FM
547 for ( i = strlen(pbuf) - 1, j = 0 ; i > -1; i--, j++)
548 pret[j] = pbuf[i];
d6e703cc 549
9bd92830 550 pret[j] = '\0';
d6e703cc 551
9bd92830 552 return pret;
d6e703cc
FM
553}
554
555
25697a35
GS
556char *buildtime(long long int elap)
557{
9bd92830
FM
558 int num = elap / 1000;
559 int hor = 0;
560 int min = 0;
561 int sec = 0;
562 static char buf[12];
25697a35 563
9bd92830 564 buf[0]='\0';
25697a35 565
9bd92830
FM
566 hor=num / 3600;
567 min=(num % 3600) / 60;
568 sec=num % 60;
569 sprintf(buf,"%02d:%02d:%02d",hor,min,sec);
25697a35 570
9bd92830 571 return(buf);
25697a35
GS
572}
573
574
15d3cb5c
FM
575/*!
576Get 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
581bytes long.
582
583\retval 0 No error.
584\retval -1 File not found.
585*/
586int obtdate(const char *dirname, const char *name, char *data)
25697a35 587{
9bd92830
FM
588 FILE *fp_in;
589 char wdir[MAXLEN];
25697a35 590
9bd92830
FM
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';
15d3cb5c 596 return(-1);
9bd92830
FM
597 }
598 }
25697a35 599
9bd92830
FM
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);
25697a35 606
15d3cb5c 607 return(0);
25697a35
GS
608}
609
610
a1de61fe 611void formatdate(char *date,int date_size,int year,int month,int day,int hour,int minute,int second,int dst)
9e41ca7e 612{
9bd92830
FM
613 struct tm ltm;
614 time_t unixtime;
615 struct tm *fulltm;
9e41ca7e 616
9bd92830
FM
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);
9e41ca7e
FM
629}
630
631
fa6552b0 632void computedate(int year,int month,int day,struct tm *t)
9426efec 633{
9bd92830
FM
634 memset(t,0,sizeof(*t));
635 t->tm_year=year-1900;
636 t->tm_mon=month-1;
637 t->tm_mday=day;
9426efec
FM
638}
639
640
d25d4e6a 641int obtuser(const char *dirname, const char *name)
25697a35 642{
9bd92830
FM
643 FILE *fp_in;
644 char wdir[MAXLEN];
645 char tuser[20];
646 int nuser;
25697a35 647
9bd92830
FM
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 }
25697a35 655
9bd92830
FM
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);
25697a35 662
9bd92830 663 return(nuser);
25697a35
GS
664}
665
666
ea275279 667void obttotal(const char *dirname, const char *name, int nuser, long long int *tbytes, long long int *media)
25697a35 668{
9bd92830
FM
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;
25697a35
GS
725}
726
fa6552b0 727int getperiod_fromsarglog(const char *arqtt,struct periodstruct *period)
25697a35 728{
9bd92830
FM
729 const char *str;
730 int day0, month0, year0, hour0, minute0;
731 int day1, month1, year1, hour1, minute1;
9bd92830
FM
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');
cbe0740f 741 if (day0<1 || day0>31) continue;
9bd92830 742 str+=2;
cbe0740f
FM
743 month0=(str[0]-'0')*10+(str[1]-'0')-1;
744 if (month0<0 || month0>11) continue;
ddd6dbdc 745 str+=2;
9bd92830
FM
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');
cbe0740f 765 if (day1<1 || day1>31) continue;
9bd92830 766 str+=2;
cbe0740f
FM
767 month1=(str[0]-'0')*10+(str[1]-'0')-1;
768 if (month1<0 || month1>11) continue;
ddd6dbdc 769 str+=2;
9bd92830
FM
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);
fa6552b0 798}
48864d28 799
42b117e3
FM
800void getperiod_fromrange(struct periodstruct *period,int dfrom,int duntil)
801{
9bd92830
FM
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;
42b117e3 806
9bd92830
FM
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;
42b117e3
FM
811}
812
fa6552b0
FM
813int getperiod_buildtext(struct periodstruct *period)
814{
9bd92830
FM
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 ||
007905af
FM
830 period->start.tm_mon!=period->end.tm_mon ||
831 period->start.tm_mday!=period->end.tm_mday);
9bd92830
FM
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);
25697a35
GS
853}
854
06ced858 855static void copy_images(void)
25697a35 856{
9bd92830
FM
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) {
affa72c5
FM
873 if (mkdir(images,0755)) {
874 debuga(_("Cannot create directory %s - %s\n"),images,strerror(errno));
875 exit(EXIT_FAILURE);
876 }
9bd92830
FM
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;
06ced858
FM
916}
917
fa6552b0 918int vrfydir(const struct periodstruct *per1, const char *addr, const char *site, const char *us, const char *form)
06ced858 919{
9bd92830
FM
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,
007905af 955 conv_month_name(m1),d1,y2,conv_month_name(m2),d2);
9bd92830
FM
956 } else if(df[0] == 'e') {
957 wlen=snprintf(wdir+wlen,sizeof(wdir)-wlen,"%02d%s%04d-%02d%s%04d",d1,
007905af 958 conv_month_name(m1),y1,d2,conv_month_name(m2),y2);
9bd92830
FM
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);
25697a35
GS
1059}
1060
25697a35
GS
1061void strip_latin(char *line)
1062{
9bd92830
FM
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;
25697a35
GS
1080}
1081
120d768c 1082void zdate(char *ftime,int ftimesize, const char *DateFormat)
25697a35 1083{
9bd92830
FM
1084 time_t t;
1085 struct tm *local;
25697a35 1086
9bd92830
FM
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;
25697a35
GS
1096}
1097
1098
324ba7f3 1099char *fixtime(long long int elap)
25697a35 1100{
9bd92830
FM
1101 int num = elap / 1000;
1102 int hor = 0;
1103 int min = 0;
1104 int sec = 0;
1105 static char buf[12];
25697a35 1106
9bd92830
FM
1107 hor=num / 3600;
1108 min=(num % 3600) / 60;
1109 sec=num % 60;
25697a35 1110
9bd92830
FM
1111 if(hor==0 && min==0 && sec==0)
1112 strcpy(buf,"0");
1113 else
1114 sprintf(buf,"%d:%02d:%02d",hor,min,sec);
25697a35 1115
9bd92830 1116 return buf;
25697a35
GS
1117}
1118
1119
42b117e3 1120void date_from(char *date, int *dfrom, int *duntil)
25697a35 1121{
9bd92830
FM
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;
25697a35
GS
1257}
1258
1259
1260char *strlow(char *string)
1261{
9bd92830 1262 char *s;
25697a35 1263
9bd92830
FM
1264 if (string)
1265 {
1266 for (s = string; *s; ++s)
1267 *s = tolower(*s);
1268 }
25697a35 1269
9bd92830 1270 return string;
25697a35
GS
1271}
1272
1273
1274
1275
1276char *strup(char *string)
1277{
9bd92830 1278 char *s;
25697a35 1279
9bd92830
FM
1280 if (string)
1281 {
1282 for (s = string; *s; ++s)
1283 *s = toupper(*s);
1284 }
25697a35 1285
9bd92830 1286 return string;
25697a35
GS
1287}
1288
1289
32e71fa4 1290void removetmp(const char *outdir)
25697a35 1291{
9dc20988
FM
1292 FILE *fp_gen;
1293 char filename[256];
9bd92830
FM
1294
1295 if(!RemoveTempFiles)
1296 return;
1297
1298 if(debug) {
1299 debuga(_("Purging temporary file sarg-general\n"));
1300 }
9dc20988 1301 if (snprintf(filename,sizeof(filename),"%s/sarg-general",outdir)>=sizeof(filename)) {
9bd92830
FM
1302 debuga(_("(removetmp) directory too long to remove %s/sarg-period\n"),outdir);
1303 exit(EXIT_FAILURE);
1304 }
9dc20988
FM
1305 if((fp_gen=fopen(filename,"w"))==NULL){
1306 debuga(_("(removetmp) Cannot open file %s\n"),filename);
9bd92830
FM
1307 exit(EXIT_FAILURE);
1308 }
9dc20988
FM
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));
9bd92830
FM
1312 exit(EXIT_FAILURE);
1313 }
25697a35
GS
1314}
1315
48864d28 1316void load_excludecodes(const char *ExcludeCodes)
25697a35 1317{
9bd92830
FM
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;
25697a35
GS
1369}
1370
48864d28
FM
1371void free_excludecodes(void)
1372{
9bd92830
FM
1373 if (excludecode) {
1374 free(excludecode);
1375 excludecode=NULL;
1376 }
48864d28
FM
1377}
1378
32e71fa4 1379int vercode(const char *code)
25697a35 1380{
9bd92830
FM
1381 char *cod;
1382 int clen;
48864d28 1383
9bd92830
FM
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;
25697a35
GS
1395}
1396
1397void fixnone(char *str)
1398{
9bd92830 1399 int i;
32e71fa4 1400
9bd92830
FM
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';
25697a35 1404
9bd92830 1405 return;
25697a35
GS
1406}
1407
2357ef77
FM
1408void fixendofline(char *str)
1409{
9bd92830 1410 int i;
2357ef77 1411
9bd92830 1412 for (i=strlen(str)-1 ; i>=0 && (unsigned char)str[i]<=' ' ; i--) str[i]=0;
2357ef77
FM
1413}
1414
25697a35 1415#ifdef LEGACY_TESTVALIDUSERCHAR
32e71fa4 1416int testvaliduserchar(const char *user)
25697a35 1417{
9bd92830
FM
1418 int x=0;
1419 int y=0;
25697a35 1420
9bd92830
FM
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;
25697a35
GS
1428}
1429#else
32e71fa4 1430int testvaliduserchar(const char *user)
25697a35 1431{
9bd92830
FM
1432 char * p_UserInvalidChar = UserInvalidChar ;
1433 const char * p_user ;
25697a35 1434
9bd92830
FM
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;
25697a35
GS
1445}
1446#endif
1447
1448int compar( const void *a, const void *b )
9bd92830
FM
1449{
1450 if( *(int *)a > *(int *)b ) return 1;
1451 if( *(int *)a < *(int *)b ) return -1;
1452 return 0;
25697a35
GS
1453}
1454
1455int getnumlist( char *buf, numlist *list, const int len, const int maxvalue )
48864d28 1456{
9bd92830
FM
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;
25697a35
GS
1502}
1503
1504
32e71fa4 1505char *get_size(const char *path, const char *file)
491b862f 1506{
9bd92830
FM
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);
491b862f
GS
1533}
1534
dfb337be
FM
1535void show_info(FILE *fp_ou)
1536{
9bd92830 1537 char ftime[127];
dfb337be 1538
9bd92830
FM
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);
dfb337be
FM
1542}
1543
c0ec9cc7 1544void show_sarg(FILE *fp_ou, int depth)
dfb337be 1545{
9bd92830 1546 int i;
c0ec9cc7 1547
9bd92830
FM
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);
dfb337be
FM
1553}
1554
1555void write_logo_image(FILE *fp_ou)
1556{
9bd92830
FM
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);
dfb337be 1559}
491b862f 1560
2e96438d 1561void write_html_head(FILE *fp_ou, int depth, const char *page_title,int javascript)
491b862f 1562{
9bd92830 1563 int i;
2e96438d 1564
9bd92830
FM
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);
7f2382f6
FM
1578}
1579
2e96438d 1580void write_html_header(FILE *fp_ou, int depth, const char *page_title,int javascript)
7f2382f6 1581{
9bd92830
FM
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);
c0ec9cc7
FM
1586}
1587
1588void close_html_header(FILE *fp_ou)
1589{
9bd92830 1590 fputs("</table></div>\n",fp_ou);
c0ec9cc7
FM
1591}
1592
fa6552b0 1593int write_html_trailer(FILE *fp_ou)
c0ec9cc7 1594{
9bd92830
FM
1595 show_info(fp_ou);
1596 if (fputs("</body>\n</html>\n",fp_ou)==EOF) return(-1);
1597 return(0);
dfb337be
FM
1598}
1599
ac422f9b 1600void output_html_string(FILE *fp_ou,const char *str,int maxlen)
dfb337be 1601{
9bd92830
FM
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);
ac422f9b
FM
1629}
1630
1631void output_html_url(FILE *fp_ou,const char *url)
1632{
9bd92830
FM
1633 while (*url) {
1634 if (*url=='&')
1635 fputs("&amp;",fp_ou);
1636 else
1637 fputc(*url,fp_ou);
1638 url++;
1639 }
491b862f
GS
1640}
1641
48864d28 1642void url_module(const char *url, char *w2)
25697a35 1643{
9bd92830
FM
1644 int x, y;
1645 char w[255];
25697a35 1646
9bd92830
FM
1647 y=0;
1648 for(x=strlen(url)-1; x>=0; x--) {
1649 if(url[x] == '/' || y>=sizeof(w)-1) break;
1650 w[y++]=url[x];
1651 }
1652 if (x<0) {
1653 w2[0]='\0';
1654 return;
1655 }
25697a35 1656
9bd92830
FM
1657 x=0;
1658 for(y=y-1; y>=0; y--) {
1659 w2[x++]=w[y];
1660 }
1661 w2[x]='\0';
25697a35
GS
1662}
1663
e5b2c6f0
FM
1664void url_to_file(const char *url,char *file,int filesize)
1665{
9bd92830 1666 int i,skip;
e5b2c6f0 1667
9bd92830
FM
1668 filesize--;
1669 skip=0;
1670 for(i=0; i<filesize && *url; url++) {
1671 if(isalnum(*url) || *url=='-' || *url=='_' || *url=='.' || *url=='%') {
1672 file[i++]=*url;
1673 skip=0;
1674 } else {
1675 if (!skip) file[i++]='_';
1676 skip=1;
1677 }
1678 }
1679 file[i]='\0';
e5b2c6f0 1680}
d6e703cc 1681
32e71fa4 1682void version(void)
25697a35 1683{
9bd92830
FM
1684 printf(_("SARG Version: %s\n"),VERSION);
1685 exit(EXIT_SUCCESS);
25697a35 1686}
5f3cfd1d
FM
1687
1688char *get_param_value(const char *param,char *line)
1689{
9bd92830 1690 int plen;
2357ef77 1691
9bd92830
FM
1692 while (*line==' ' || *line=='\t') line++;
1693 plen=strlen(param);
1694 if (strncasecmp(line,param,plen)) return(NULL);
1695 if (line[plen]!=' ' && line[plen]!='\t') return(NULL);
1696 line+=plen;
1697 while (*line==' ' || *line=='\t') line++;
1698 return(line);
5f3cfd1d 1699}
936c9905 1700
51465d08 1701void unlinkdir(const char *dir,int contentonly)
304a739d 1702{
9bd92830
FM
1703 struct stat st;
1704 DIR *dirp;
1705 struct dirent *direntp;
1706 char dname[MAXLEN];
1707 int err;
1708
1709 dirp=opendir(dir);
1710 if (!dirp) return;
1711 while ((direntp = readdir(dirp)) != NULL) {
1712 if (direntp->d_name[0] == '.' && (direntp->d_name[1] == '\0' ||
007905af 1713 (direntp->d_name[1] == '.' && direntp->d_name[2] == '\0')))
9bd92830
FM
1714 continue;
1715 if (snprintf(dname,sizeof(dname),"%s/%s",dir,direntp->d_name)>=sizeof(dname)) {
1716 debuga(_("directory name to delete too long: %s/%s\n"),dir,direntp->d_name);
1717 exit(EXIT_FAILURE);
1718 }
463f8e09 1719#ifdef HAVE_LSTAT
9bd92830 1720 err=lstat(dname,&st);
463f8e09 1721#else
9bd92830 1722 err=stat(dname,&st);
463f8e09 1723#endif
9bd92830
FM
1724 if (err) {
1725 debuga(_("cannot stat %s\n"),dname);
1726 exit(EXIT_FAILURE);
1727 }
1728 if (S_ISREG(st.st_mode)) {
1729 if (unlink(dname)) {
1730 debuga(_("cannot delete %s - %s\n"),dname,strerror(errno));
1731 exit(EXIT_FAILURE);
1732 }
1733 } else if (S_ISDIR(st.st_mode)) {
1734 unlinkdir(dname,0);
1735 } else {
1736 debuga(_("unknown path type %s\n"),dname);
1737 }
1738 }
1739 closedir(dirp);
1740
1741 if (!contentonly) {
1742 if (rmdir(dir)) {
1743 debuga(_("cannot delete %s - %s\n"),dir,strerror(errno));
1744 exit(EXIT_FAILURE);
1745 }
1746 }
51465d08 1747}
ac422f9b 1748