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