]> git.ipfire.org Git - thirdparty/sarg.git/blame - util.c
Fix the date range exclusion while reading the dansguardian log
[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
67a93701
FM
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 */
1651void 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
48864d28 1665void url_module(const char *url, char *w2)
25697a35 1666{
9bd92830
FM
1667 int x, y;
1668 char w[255];
25697a35 1669
9bd92830
FM
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 }
25697a35 1679
9bd92830
FM
1680 x=0;
1681 for(y=y-1; y>=0; y--) {
1682 w2[x++]=w[y];
1683 }
1684 w2[x]='\0';
25697a35
GS
1685}
1686
e5b2c6f0
FM
1687void url_to_file(const char *url,char *file,int filesize)
1688{
9bd92830 1689 int i,skip;
e5b2c6f0 1690
9bd92830
FM
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';
e5b2c6f0 1703}
d6e703cc 1704
32e71fa4 1705void version(void)
25697a35 1706{
9bd92830
FM
1707 printf(_("SARG Version: %s\n"),VERSION);
1708 exit(EXIT_SUCCESS);
25697a35 1709}
5f3cfd1d
FM
1710
1711char *get_param_value(const char *param,char *line)
1712{
9bd92830 1713 int plen;
2357ef77 1714
9bd92830
FM
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);
5f3cfd1d 1722}
936c9905 1723
51465d08 1724void unlinkdir(const char *dir,int contentonly)
304a739d 1725{
9bd92830
FM
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' ||
007905af 1736 (direntp->d_name[1] == '.' && direntp->d_name[2] == '\0')))
9bd92830
FM
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 }
463f8e09 1742#ifdef HAVE_LSTAT
9bd92830 1743 err=lstat(dname,&st);
463f8e09 1744#else
9bd92830 1745 err=stat(dname,&st);
463f8e09 1746#endif
9bd92830
FM
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 }
51465d08 1770}
ac422f9b 1771
5207d9f8
FM
1772/*!
1773 Extract an url, IPv4 or IPv6 from a buffer. The IP addresses may end with a
1774 prefix size.
1775
1776 \param buf The buffer to parse.
1777 \param text A pointer to set to the beginning of the string pattern. No terminating zero is inserted.
1778 \param ipv4 A 4 bytes buffer to store the bytes of the IPv4 address.
1779 \param ipv6 A 8 short integers buffer to store the values of the IPv6 address.
1780 \param nbits The number of prefix bits for an IP address.
1781 \param next The content of the line after the extracted address.
1782
1783 \retval 3 The pattern is a IPv6 address.
1784 \retval 2 The pattern is a IPv4 address.
1785 \retval 1 The patter is a string.
1786 \retval 0 Empty pattern.
1787 */
7819e0d5 1788int extract_address_mask(const char *buf,const char **text,unsigned char *ipv4,unsigned short int *ipv6,int *nbits,const char **next)
5207d9f8
FM
1789{
1790 int i;
1791 int j;
1792 int ip_size;
1793 unsigned int value4, value6;
1794 unsigned short int addr[8];
1795 int addr_len;
0ec4b481 1796 int nibble6_len;
5207d9f8
FM
1797 int mask, max_mask;
1798 int pad_pos;
1799 int pad_len;
0ec4b481 1800 int bracket=false;
5207d9f8
FM
1801
1802 // skip leading spaces and tabs
1803 while (*buf && (*buf==' ' || *buf=='\t')) buf++;
1804
1805 // find out the nature of the pattern
1806 ip_size=0x60 | 0x04;
0ec4b481
FM
1807 if (*buf=='[') {
1808 bracket=true;
1809 ip_size=0x60;
1810 buf++;
1811 }
5207d9f8
FM
1812 value4=0U;
1813 value6=0U;
1814 addr_len=0;
0ec4b481 1815 nibble6_len=0;
5207d9f8 1816 pad_pos=-1;
84aefd39 1817 for (i=0 ; (unsigned char)buf[i]>' ' && buf[i]!='/' && buf[i]!='?' && (!bracket || buf[i]!=']') && ip_size ; i++) {
5207d9f8
FM
1818 if (ip_size & 0x04) {
1819 if (isdigit(buf[i])) {
1820 value4=value4*10+(buf[i]-'0');
1821 if (value4>0xFFU) ip_size&=~0x04;
1822 } else if (buf[i]=='.' && addr_len<4) {
1823 addr[addr_len++]=(unsigned short)(value4 & 0xFFU);
1824 value4=0U;
1825 } else {
1826 ip_size&=~0x04;
1827 }
1828 }
1829 if (ip_size & 0x60) {
1830 if (isdigit(buf[i])) {
1831 value6=(value6<<4)+(buf[i]-'0');
0ec4b481 1832 nibble6_len++;
5207d9f8
FM
1833 if (value6>0xFFFFU) ip_size&=~0x60;
1834 } else if (toupper(buf[i])>='A' && toupper(buf[i])<='F') {
1835 value6=(value6<<4)+(toupper(buf[i])-'A'+10);
0ec4b481 1836 nibble6_len++;
5207d9f8
FM
1837 if (value6>0xFFFFU) ip_size&=~0x60;
1838 } else if (buf[i]==':' && addr_len<8) {
0ec4b481
FM
1839 if (nibble6_len>0) {
1840 addr[addr_len++]=(unsigned short)(value6 & 0xFFFFU);
1841 nibble6_len=0;
1842 }
5207d9f8 1843 value6=0U;
0ec4b481
FM
1844 if (buf[i+1]==':') {
1845 pad_pos=addr_len;
1846 i++;
1847 }
5207d9f8
FM
1848 } else {
1849 ip_size&=~0x60;
1850 }
1851 }
1852 }
1853 if (i==0) return(0);
1854 if (ip_size & 0x04) {
1855 if (addr_len!=3)
1856 ip_size&=~0x04;
1857 else
1858 addr[addr_len++]=(unsigned short)(value4 & 0xFFU);
1859 }
1860 if (ip_size & 0x60) {
1861 if (pad_pos<0 && addr_len!=7) {
1862 ip_size&=~0x60;
1863 } else if (pad_pos>=0 && addr_len>=7)
1864 ip_size&=~0x60;
0ec4b481 1865 else if (nibble6_len>0)
5207d9f8
FM
1866 addr[addr_len++]=(unsigned short)(value6 & 0xFFFFU);
1867 }
1868 if (!ip_size) {
1869 *text=buf;
0ec4b481 1870 if (bracket) (*text)--;
5207d9f8 1871 while ((unsigned char)buf[i]>' ') i++;
7819e0d5 1872 if (next) *next=buf+i;
5207d9f8
FM
1873 return(1);
1874 }
1875 max_mask=(ip_size & 0x04) ? 4*8 : 8*16;
1876 if (buf[i]=='/') {
1877 i++;
1878 mask=atoi(buf+i);
1879 while (isdigit(buf[i])) i++;
1880 if (mask<0 || mask>max_mask) mask=max_mask;
1881 } else
1882 mask=max_mask;
0ec4b481 1883 if (ip_size & 0x60 && bracket && buf[i]==']') i++;
7819e0d5 1884 if (next) *next=buf+i;
5207d9f8
FM
1885 if (ip_size & 0x04) {
1886 if (nbits) *nbits=mask;
1887 for (i=0 ; i<addr_len ; i++)
1888 ipv4[i]=(unsigned char)addr[i];
1889 return(2);
1890 }
1891
1892 // IPv6 address
1893 if (nbits) *nbits=mask;
1894 i=0;
1895 j=0;
1896 if (pad_pos>=0) {
1897 while (i<pad_pos)
1898 ipv6[j++]=(unsigned short int)addr[i++];
1899 pad_len=8-addr_len;
0ec4b481 1900 while (j<pad_pos+pad_len)
5207d9f8
FM
1901 ipv6[j++]=0;
1902 }
1903 while (i<addr_len)
1904 ipv6[j++]=(unsigned short int)addr[i++];
1905 return(3);
1906}