]> git.ipfire.org Git - thirdparty/sarg.git/blame - util.c
Update the ChangeLog
[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)) {
4bcb77cf 296 fprintf(stderr,"SARG: Invalid path (%s). Please, use absolute paths only.\n",name);
25697a35
GS
297 fprintf(stderr,"SARG: process aborted.\n");
298 exit(1);
299 }
300
a1de61fe
FM
301 chars=0;
302 for (i=0 ; name[i] ; i++) {
303 if (i>=sizeof(w0)) {
304 fprintf(stderr,"SARG: 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)) {
311 fprintf(stderr,"SARG: mkdir %s %s\n",w0,strerror(errno));
312 fprintf(stderr,"SARG: process aborted.\n");
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)) {
323 fprintf(stderr,"SARG: mkdir %s %s\n",name,strerror(errno));
25697a35
GS
324 fprintf(stderr,"SARG: process aborted.\n");
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) {
10210234 340 debuga(_("The requested number length 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
FM
684 if (!fgets(data,80,fp_in)) {
685 fprintf(stderr,"Failed to read the date in %s\n",wdir);
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
d25d4e6a 717int obtuser(const char *dirname, const char *name)
25697a35
GS
718{
719
720 FILE *fp_in;
721 char wdir[MAXLEN];
d25d4e6a
FM
722 char tuser[20];
723 int nuser;
25697a35 724
d6e703cc 725 sprintf(wdir,"%s%s/sarg-users",dirname,name);
2357ef77 726 if((fp_in=fopen(wdir,"r"))==NULL) {
d6e703cc 727 sprintf(wdir,"%s%s/users",dirname,name);
2357ef77 728 if((fp_in=fopen(wdir,"r"))==NULL) {
d25d4e6a 729 return(0);
d6e703cc 730 }
25697a35
GS
731 }
732
d25d4e6a 733 if (!fgets(tuser,sizeof(tuser),fp_in)) {
10210234 734 debuga(_("Failed to read the number of users in %s\n"),wdir);
05b90947
FM
735 exit(1);
736 }
25697a35 737 fclose(fp_in);
d25d4e6a 738 nuser=atoi(tuser);
25697a35 739
d25d4e6a 740 return(nuser);
25697a35
GS
741}
742
743
d25d4e6a 744void obttotal(const char *dirname, const char *name, char *tbytes, int nuser, char *media)
25697a35 745{
25697a35 746 FILE *fp_in;
2240dcea 747 char *buf;
25697a35 748 char wdir[MAXLEN];
2240dcea 749 char user[MAX_USER_LEN];
0511cf2d 750 char sep;
25697a35 751 long long int med=0;
fabbc7cc 752 long long int twork=0;
9c7c6346 753 struct getwordstruct gwarea;
2240dcea 754 struct longlinestruct line;
25697a35 755
0511cf2d
FM
756 twork=0;
757 tbytes[0]='\0';
758 media[0]='\0';
25697a35 759
d6e703cc 760 sprintf(wdir,"%s%s/sarg-general",dirname,name);
25697a35 761 if ((fp_in = fopen(wdir, "r")) == 0) {
d6e703cc
FM
762 sprintf(wdir,"%s%s/general",dirname,name);
763 if ((fp_in = fopen(wdir, "r")) == 0) {
d6e703cc
FM
764 return;
765 }
25697a35
GS
766 }
767
2240dcea 768 if (longline_prepare(&line)<0) {
10210234 769 debuga(_("Not enough memory to read the file %s\n"),wdir);
2240dcea
FM
770 exit(1);
771 }
772
773 while((buf=longline_read(fp_in,&line))!=NULL) {
0511cf2d
FM
774 if (strncmp(buf,"TOTAL\t",6) == 0)
775 sep='\t'; //new file
776 else if (strncmp(buf,"TOTAL ",6) == 0)
777 sep=' '; //old file
778 else
779 continue;
9c7c6346 780 getword_start(&gwarea,buf);
2240dcea 781 if (getword(user,sizeof(user),&gwarea,sep)<0) {
10210234 782 debuga(_("There is a invalid user in file %s\n"),wdir);
4bcb77cf
FM
783 exit(1);
784 }
ab6fadd0 785 if(strcmp(user,"TOTAL") != 0)
25697a35 786 continue;
0511cf2d 787 if (getword_skip(MAXLEN,&gwarea,sep)<0) {
10210234 788 debuga(_("There a broken total number of access in file %s\n"),wdir);
4bcb77cf
FM
789 exit(1);
790 }
0511cf2d 791 if (getword_atoll(&twork,&gwarea,sep)<0) {
10210234 792 debuga(_("There is a broken number of bytes in file %s\n"),wdir);
4bcb77cf
FM
793 exit(1);
794 }
48864d28 795 strcpy(tbytes,fixnum(twork,1));
6e792ade 796 break;
25697a35
GS
797 }
798 fclose(fp_in);
2240dcea 799 longline_free(&line);
25697a35 800
d25d4e6a 801 if(nuser <= 0) {
48864d28 802 strcpy(media,"0");
25697a35
GS
803 return;
804 }
48864d28 805
d25d4e6a 806 med=twork / nuser;
48864d28 807 strcpy(media,fixnum(med,1));
25697a35
GS
808
809 return;
25697a35
GS
810}
811
812
48864d28 813void gperiod(const char *dirname, const char *period)
25697a35 814{
48864d28 815
25697a35 816 FILE *fp_ou;
25697a35
GS
817 char wdirname[MAXLEN];
818
819 strcpy(wdirname,dirname);
0a4e18e1 820 strcat(wdirname,"/sarg-period");
25697a35
GS
821
822 if((fp_ou=fopen(wdirname,"w"))==NULL){
c36c7384 823 fprintf(stderr, "SARG: (report) %s: %s\n",_("Cannot open file"),wdirname);
25697a35
GS
824 exit(1);
825 }
48864d28 826
d6e703cc 827 fputs(period,fp_ou);
25697a35
GS
828 fclose(fp_ou);
829
830 if(debug)
10210234 831 debuga(_("Making period file\n"));
48864d28 832
25697a35 833 return;
2357ef77 834
25697a35
GS
835}
836
06ced858 837static void copy_images(void)
25697a35
GS
838{
839 FILE *img_in, *img_ou;
06ced858
FM
840 char images[512];
841 char imgdir[MAXLEN];
842 char srcfile[MAXLEN];
843 char dstfile[MAXLEN];
844 DIR *dirp;
845 struct dirent *direntp;
846 char buffer[MAXLEN];
847 size_t nread;
848 struct stat info;
849
850 if (snprintf(images,sizeof(images),"%simages",outdir)>=sizeof(images)) {
10210234 851 debuga(_("Cannot copy images to target directory %simages\n"),outdir);
06ced858
FM
852 exit(1);
853 }
854 if (access(images,R_OK)!=0) {
855 mkdir(images,0755);
856 }
857
858 strcpy(imgdir,IMAGEDIR);
859 dirp = opendir(imgdir);
860 if(dirp==NULL) {
10210234 861 debuga(_("(util) Can't open directory %s: %s\n"),imgdir,strerror(errno));
06ced858
FM
862 return;
863 }
864 while ((direntp = readdir( dirp )) != NULL ){
865 if(direntp->d_name[0]=='.')
866 continue;
867 sprintf(srcfile,"%s/%s",imgdir,direntp->d_name);
868 if (stat(srcfile,&info)) {
10210234 869 debuga(_("Cannot stat \"%s\" - %s\n"),srcfile,strerror(errno));
06ced858
FM
870 continue;
871 }
872 if (S_ISREG(info.st_mode)) {
873 sprintf(dstfile,"%s/%s",images,direntp->d_name);
874 img_in = fopen(srcfile, "rb");
875 if(img_in!=NULL) {
876 img_ou = fopen(dstfile, "wb");
877 if(img_ou!=NULL) {
878 while ((nread = fread(buffer,1,sizeof(buffer),img_in))>0) {
b5f13803 879 if (fwrite(buffer,1,nread,img_ou)!=nread) {
10210234 880 debuga(_("Failed to copy image %s to %s\n"),srcfile,dstfile);
b5f13803
FM
881 break;
882 }
06ced858
FM
883 }
884 fclose(img_ou);
885 } else
c36c7384 886 fprintf(stderr,"SARG: (util): %s %s: %s\n", _("Cannot open file")?_("Cannot open file"):"Can't open/create file", dstfile, strerror(errno));
06ced858
FM
887 fclose(img_in);
888 } else
c36c7384 889 fprintf(stderr,"SARG: (util): %s %s: %s\n", _("Cannot open file")?_("Cannot open file"):"Can't open file", srcfile, strerror(errno));
06ced858
FM
890 }
891 }
892 (void) closedir(dirp);
893
894 return;
895}
896
897void vrfydir(const char *per1, const char *addr, const char *site, const char *us, const char *form)
898{
6798f0a7 899 FILE *fp_ou;
25697a35 900 int num=1, count=0;
25697a35
GS
901 char wdir[MAXLEN];
902 char per2[MAXLEN];
903 char dirname2[MAXLEN];
32e71fa4
FM
904 char y1[5], y2[5];
905 char d1[3], d2[3];
e6414a9d 906 char m1[8], m2[8];
6798f0a7 907 time_t curtime;
a1de61fe 908 struct tm *loctm;
25697a35 909
0349fa24 910 if(IndexTree == INDEX_TREE_DATE) {
e6414a9d
FM
911 bzero(y1,sizeof(y1));
912 bzero(y2,sizeof(y2));
913 bzero(d1,sizeof(d1));
914 bzero(d2,sizeof(d2));
915 bzero(m1,sizeof(m1));
916 bzero(m2,sizeof(m2));
491b862f 917 if(strncmp(df,"u",1) == 0) {
d6e703cc
FM
918 strncpy(y1,period,4);
919 strncpy(y2,period+10,4);
920 strncpy(m1,period+4,3);
921 strncpy(m2,period+14,3);
922 strncpy(d1,period+7,2);
923 strncpy(d2,period+17,2);
491b862f 924 } else if(strncmp(df,"e",1) == 0) {
d6e703cc
FM
925 strncpy(d1,period+0,2);
926 strncpy(d2,period+10,2);
927 strncpy(m1,period+2,3);
928 strncpy(m2,period+12,3);
929 strncpy(y1,period+5,4);
930 strncpy(y2,period+15,4);
491b862f
GS
931 }
932 conv_month(m1);
933 conv_month(m2);
934
935 sprintf(wdir,"%s%s",outdir,y1);
936 if(strcmp(y1,y2) != 0) {
e6414a9d
FM
937 strcat(wdir,"-");
938 strcat(wdir,y2);
491b862f
GS
939 }
940 if(access(wdir, R_OK) != 0)
941 my_mkdir(wdir);
2357ef77 942
e6414a9d
FM
943 strcat(wdir,"/");
944 strcat(wdir,m1);
491b862f 945 if(strcmp(m1,m2) != 0) {
e6414a9d
FM
946 strcat(wdir,"-");
947 strcat(wdir,m2);
491b862f
GS
948 }
949 if(access(wdir, R_OK) != 0)
950 my_mkdir(wdir);
2357ef77 951
e6414a9d
FM
952 strcat(wdir,"/");
953 strcat(wdir,d1);
491b862f 954 if(strcmp(d1,d2) != 0) {
e6414a9d
FM
955 strcat(wdir,"-");
956 strcat(wdir,d2);
491b862f 957 }
e6414a9d
FM
958 } else {
959 sprintf(wdir, "%s%s", outdir, per1);
960 }
25697a35 961
e6414a9d 962 if(us[0] != '\0') {
25697a35
GS
963 strcat(wdir,"-");
964 strcat(wdir,us);
965 }
e6414a9d 966 if(addr[0] != '\0') {
25697a35
GS
967 strcat(wdir,"-");
968 strcat(wdir,addr);
969 }
e6414a9d 970 if(site[0] != '\0') {
25697a35
GS
971 strcat(wdir,"-");
972 strcat(wdir,site);
973 }
974
51465d08 975 strcpy(dirname,wdir);
25697a35 976
0349fa24 977 if(IndexTree != INDEX_TREE_DATE) {
e6414a9d 978 if(!OverwriteReport) {
491b862f
GS
979 while(num) {
980 if(access(wdir,R_OK) == 0) {
981 sprintf(wdir,"%s.%d",dirname,num);
982 sprintf(per2,"%s.%d",per1,num);
983 num++;
984 count++;
985 } else
986 break;
987 }
25697a35 988
491b862f
GS
989 if(count > 0) {
990 if(debug)
c36c7384 991 fprintf(stderr, "SARG: %s: %s %s %s\n",_("File"),dirname,_("already exists, moved to"),wdir);
e6414a9d 992 rename(dirname,wdir);
491b862f
GS
993 }
994 } else {
51465d08
FM
995 if(access(dirname,R_OK) == 0) {
996 unlinkdir(dirname,1);
491b862f 997 }
25697a35 998 }
491b862f 999 my_mkdir(dirname);
25697a35 1000 } else {
491b862f 1001 strcpy(dirname2,wdir);
e6414a9d 1002 if(!OverwriteReport) {
491b862f
GS
1003 while(num) {
1004 if(access(wdir,R_OK) == 0) {
1005 sprintf(wdir,"%s.%d",dirname2,num);
1006 sprintf(per2,"%s.%d",per1,num);
1007 num++;
1008 count++;
1009 } else
1010 break;
1011 }
48864d28 1012
491b862f
GS
1013 if(count > 0) {
1014 if(debug)
c36c7384 1015 fprintf(stderr, "SARG: %s: %s %s %s\n",_("File"),dirname2,_("already exists, moved to"),wdir);
491b862f
GS
1016 rename(dirname2,wdir);
1017 strcpy(dirname2,wdir);
1018 }
1019 } else {
1020 if(access(wdir,R_OK) == 0) {
51465d08 1021 unlinkdir(wdir,1);
491b862f 1022 }
25697a35 1023 }
48864d28 1024
491b862f
GS
1025 if(access(wdir, R_OK) != 0)
1026 my_mkdir(wdir);
25697a35
GS
1027 }
1028
25697a35 1029 strcpy(dirname2,wdir);
25697a35 1030
6798f0a7
FM
1031 sprintf(wdir,"%s/sarg-date",dirname);
1032 if ((fp_ou = fopen(wdir, "wt")) == 0) {
1033 fprintf(stderr, "SARG: cannot open %s for writing\n",wdir);
1034 perror("SARG:");
456d78a5
FM
1035 exit(1);
1036 }
6798f0a7 1037 time(&curtime);
fd4dbc54 1038 //strftime(wdir,sizeof(wdir),"%a %b %d %H:%M:%S %Z %Y",localtime(&curtime));
a1de61fe
FM
1039 loctm=localtime(&curtime);
1040 strftime(wdir,sizeof(wdir),"%Y-%m-%d %H:%M:%S",loctm);
1041 fprintf(fp_ou,"%s %d\n",wdir,loctm->tm_isdst);
6798f0a7 1042 fclose(fp_ou);
25697a35 1043
06ced858 1044 copy_images();
25697a35
GS
1045}
1046
25697a35
GS
1047void strip_latin(char *line)
1048{
9c7c6346
FM
1049 int i,j;
1050 int skip;
1051
1052 j=0;
1053 skip=0;
1054 for (i=0;line[i];i++){
1055 if (skip){
1056 if (line[i]==';') skip=0;
1057 } else {
1058 if (line[i]=='&')
1059 skip=1;
1060 else
1061 line[j++]=line[i];
4bcb77cf 1062 }
25697a35 1063 }
9c7c6346 1064 line[j]='\0';
25697a35
GS
1065 return;
1066
1067}
1068
120d768c 1069void zdate(char *ftime,int ftimesize, const char *DateFormat)
25697a35
GS
1070{
1071
1072 time_t t;
1073 struct tm *local;
1074
1075 t = time(NULL);
1076 local = localtime(&t);
1077 if(strcmp(DateFormat,"u") == 0)
120d768c 1078 strftime(ftime, ftimesize, "%b/%d/%Y %H:%M", local);
25697a35 1079 if(strcmp(DateFormat,"e") == 0)
120d768c 1080 strftime(ftime, ftimesize, "%d/%b/%Y-%H:%M", local);
25697a35 1081 if(strcmp(DateFormat,"w") == 0)
120d768c 1082 strftime(ftime, ftimesize, "%V-%H-%M", local);
25697a35
GS
1083 return;
1084}
1085
1086
1087char *fixtime(long int elap)
1088{
1089
1090 int num = elap / 1000;
1091 int hor = 0;
1092 int min = 0;
1093 int sec = 0;
1094 static char buf[12];
1095
1096 if(strcmp(datetimeby,"bytes") == 0) {
48864d28 1097 strcpy(buf,fixnum(elap,1));
25697a35
GS
1098 return buf;
1099 }
1100
25697a35
GS
1101 if(num<1) {
1102 sprintf(buf,"00:00:%02ld",elap);
1103 return buf;
1104 }
1105
1106 hor=num / 3600;
1107 min=(num % 3600) / 60;
1108 sec=num % 60;
1109
48864d28 1110 if(hor==0 && min==0 && sec==0)
25697a35 1111 strcpy(buf,"0");
48864d28
FM
1112 else
1113 sprintf(buf,"%01d:%02d:%02d",hor,min,sec);
25697a35
GS
1114
1115 return buf;
1116
1117}
1118
1119
1120void date_from(char *date, char *dfrom, char *duntil)
1121{
1122
9c7c6346
FM
1123 int diaf;
1124 int mesf;
1125 int anof;
1126 int diau;
1127 int mesu;
1128 int anou;
1129 char wdate[50];
25697a35 1130
9c7c6346
FM
1131 strncpy(wdate,date,sizeof(wdate)-1);
1132 wdate[sizeof(wdate)-1]='\0';
48864d28 1133 if(strchr(wdate,'-') == NULL) {
9c7c6346 1134 if (strlen(wdate)*2+1>=sizeof(wdate)) {
10210234 1135 debuga(_("Invalid date range passed as argument\n"));
9c7c6346
FM
1136 exit(1);
1137 }
25697a35
GS
1138 strcat(wdate,"-");
1139 strcat(wdate,date);
1140 strcpy(date,wdate);
1141 }
1142
9c7c6346 1143 if (sscanf(wdate,"%d/%d/%d-%d/%d/%d",&diaf,&mesf,&anof,&diau,&mesu,&anou)!=6) {
10210234 1144 debuga(_("The date range passed as argument is not formated as dd/mm/yyyy-dd/mm/yyyy\n"));
4bcb77cf
FM
1145 exit(1);
1146 }
25697a35 1147
9c7c6346
FM
1148 sprintf(dfrom,"%04d%02d%02d",anof,mesf,diaf);
1149 sprintf(duntil,"%04d%02d%02d",anou,mesu,diau);
25697a35
GS
1150 return;
1151}
1152
1153
1154char *strlow(char *string)
1155{
32e71fa4 1156 char *s;
25697a35 1157
32e71fa4
FM
1158 if (string)
1159 {
1160 for (s = string; *s; ++s)
1161 *s = tolower(*s);
1162 }
25697a35 1163
32e71fa4 1164 return string;
25697a35
GS
1165}
1166
1167
1168
1169
1170char *strup(char *string)
1171{
32e71fa4 1172 char *s;
25697a35 1173
32e71fa4
FM
1174 if (string)
1175 {
1176 for (s = string; *s; ++s)
1177 *s = toupper(*s);
1178 }
25697a35 1179
32e71fa4 1180 return string;
25697a35
GS
1181}
1182
1183
32e71fa4 1184void removetmp(const char *outdir)
25697a35
GS
1185{
1186
1187 FILE *fp_in;
1188 char warea[256];
1189
e6414a9d 1190 if(!RemoveTempFiles)
25697a35 1191 return;
48864d28 1192
32e71fa4 1193 if(debug) {
10210234 1194 debuga("%s: sarg-general, sarg-period",_("Removing temporary files\n"));
32e71fa4 1195 }
48864d28 1196 if (snprintf(warea,sizeof(warea),"%s/sarg-general",outdir)>=sizeof(warea)) {
10210234 1197 debuga(_("(removetmp) directory too long to remove: %s/sarg-period\n"),outdir);
48864d28
FM
1198 exit(1);
1199 }
32e71fa4 1200 if((fp_in=fopen(warea,"r"))==NULL){
c36c7384 1201 fprintf(stderr, "===SARG: (removetmp) %s: %s\n",_("Cannot open file"),warea);
32e71fa4
FM
1202 exit(1);
1203 }
1204 while(fgets(buf,sizeof(buf),fp_in)!=NULL) {
2240dcea 1205 if(strncmp(buf,"TOTAL",5) == 0 && (buf[6]=='\t' || buf[6]==' '))
32e71fa4
FM
1206 break;
1207 }
1208 fclose(fp_in);
1209 if((fp_in=fopen(warea,"w"))==NULL){
c36c7384 1210 fprintf(stderr, "SARG: (removetmp) %s: %s\n",_("Cannot open file"),warea);
32e71fa4 1211 exit(1);
25697a35 1212 }
32e71fa4
FM
1213 fputs(buf,fp_in);
1214 fclose(fp_in);
1215 if (snprintf(warea,sizeof(warea),"%s/sarg-period",outdir)>=sizeof(warea)) {
10210234 1216 debuga(_("(removetmp) directory too long to remove: %s/sarg-period\n"),outdir);
32e71fa4
FM
1217 exit(1);
1218 }
1219 unlink(warea);
48864d28 1220
25697a35
GS
1221 return;
1222}
1223
48864d28 1224void load_excludecodes(const char *ExcludeCodes)
25697a35
GS
1225{
1226
1227 FILE *fp_in;
1228 char data[80];
48864d28
FM
1229 int i;
1230
1231 if(ExcludeCodes[0] == '\0')
1232 return;
1233
1234 if((excludecode=(char *) malloc(1024))==NULL) {
c36c7384 1235 fprintf(stderr, "SARG: %s (1024):\n",_("malloc error"));
48864d28
FM
1236 exit(1);
1237 }
1238 bzero(excludecode,1024);
25697a35
GS
1239
1240 if((fp_in=fopen(ExcludeCodes,"r"))==NULL) {
10210234 1241 debuga(_("(util) Cannot open file: %s (exclude_codes)\n"),ExcludeCodes);
25697a35
GS
1242 exit(1);
1243 }
1244
32e71fa4 1245 while(fgets(data,sizeof(data),fp_in)!=NULL) {
48864d28
FM
1246 for (i=strlen(data)-1 ; i>=0 && (unsigned char)data[i]<=' ' ; i--) data[i]=0;
1247 if (i<0) continue;
25697a35
GS
1248 strcat(excludecode,data);
1249 strcat(excludecode,";");
25697a35
GS
1250 }
1251
1252 fclose(fp_in);
1253 return;
1254
1255}
1256
48864d28
FM
1257void free_excludecodes(void)
1258{
1259 if (excludecode) {
1260 free(excludecode);
1261 excludecode=NULL;
1262 }
1263}
1264
32e71fa4 1265int vercode(const char *code)
25697a35 1266{
48864d28
FM
1267 char *cod;
1268 int clen;
1269
1270 if (excludecode && excludecode[0]!=0) {
1271 clen=strlen(code);
1272 for (cod=excludecode ; cod ; cod=strchr(cod+1,';')) {
1273 if (strncmp(code,cod,clen)==0 && cod[clen]==';')
1274 return 1;
4bcb77cf 1275 }
25697a35
GS
1276 }
1277 return 0;
1278}
1279
1280void fixnone(char *str)
1281{
48864d28 1282 int i;
32e71fa4 1283
48864d28
FM
1284 for (i=strlen(str)-1 ; i>=0 && (unsigned char)str[i]<=' ' ; i--);
1285 if(i==3 && strncmp(str,"none",4) == 0)
25697a35
GS
1286 str[0]='\0';
1287
1288 return;
1289}
1290
2357ef77
FM
1291void fixendofline(char *str)
1292{
1293 int i;
1294
1295 for (i=strlen(str)-1 ; i>=0 && (unsigned char)str[i]<=' ' ; i--) str[i]=0;
1296}
1297
25697a35 1298#ifdef LEGACY_TESTVALIDUSERCHAR
32e71fa4 1299int testvaliduserchar(const char *user)
25697a35
GS
1300{
1301
1302 int x=0;
1303 int y=0;
1304
1305 for (y=0; y<strlen(UserInvalidChar); y++) {
1306 for (x=0; x<strlen(user); x++) {
1307 if(user[x] == UserInvalidChar[y])
1308 return 1;
1309 }
1310 }
1311 return 0;
1312}
1313#else
32e71fa4 1314int testvaliduserchar(const char *user)
25697a35
GS
1315{
1316
1317 char * p_UserInvalidChar = UserInvalidChar ;
32e71fa4 1318 const char * p_user ;
25697a35
GS
1319
1320 while( *p_UserInvalidChar ) {
1321 p_user = user ;
1322 while ( *p_user ) {
1323 if( *p_UserInvalidChar == *p_user )
1324 return 1;
1325 p_user++ ;
1326 }
1327 p_UserInvalidChar++ ;
1328 }
1329 return 0;
1330}
1331#endif
1332
1333int compar( const void *a, const void *b )
1334{ if( *(int *)a > *(int *)b ) return 1;
1335 if( *(int *)a < *(int *)b ) return -1;
1336 return 0;
1337}
1338
1339int getnumlist( char *buf, numlist *list, const int len, const int maxvalue )
48864d28
FM
1340{
1341 int i, j, d, flag, r1, r2;
1342 char *pbuf, **bp, *strbufs[ 24 ];
1343
1344 bp = strbufs;
1345 strtok( buf, " \t" );
1346 for( *bp = strtok( NULL, "," ), list->len = 0; *bp; *bp = strtok( NULL, "," ) ) {
1347 if( ++bp >= &strbufs[ 24 ] )
1348 break;
1349 list->len++;
25697a35 1350 }
48864d28
FM
1351 if( ! list->len )
1352 return -1;
1353 d = 0;
1354 for( i = 0; i < list->len; i++ ) {
1355 if( strchr( strbufs[ i ], '-' ) != 0 ) {
1356 pbuf = strbufs[ i ];
1357 strtok( pbuf, "-" );
1358 pbuf = strtok( NULL, "\0" );
1359 r1 = atoi( strbufs[ i ] );
1360 if( ( r2 = atoi( pbuf ) ) >= maxvalue || r1 >= r2 )
1361 return -1;
1362 if( i + d + ( r2 - r1 ) + 1 <= len ) {
1363 for( j = r1; j <= r2; j++ )
1364 list->list[ i + d++ ] = j;
1365 d--;
25697a35
GS
1366 }
1367 }
48864d28
FM
1368 else
1369 if( ( list->list[ i + d ] = atoi( strbufs[ i ] ) ) >= maxvalue )
1370 return 1;
25697a35 1371 }
48864d28
FM
1372 list->len += d;
1373 qsort( list->list, list->len, sizeof( int ), compar );
1374 do {
1375 flag = 0;
1376 for( i = 0; i < list->len - 1; i++ )
1377 if( list->list[ i ] == list->list[ i + 1 ] ) {
1378 for( j = i + 1; j < list->len; j++ )
1379 list->list[ j - 1 ] = list->list[ j ];
1380 list->len--;
1381 flag = 1;
1382 break;
1383 }
25697a35 1384 } while( flag );
48864d28 1385 return 0;
25697a35
GS
1386}
1387
1388
32e71fa4 1389char *get_size(const char *path, const char *file)
491b862f
GS
1390{
1391 FILE *fp;
9c7c6346 1392 static char response[255];
32e71fa4 1393 char cmd[255];
9c7c6346 1394 char *ptr;
491b862f 1395
32e71fa4 1396 if (snprintf(cmd,sizeof(cmd),"du -skh %s%s",path,file)>=sizeof(cmd)) {
10210234 1397 debuga(_("Cannot get disk space because the path %s%s is too long\n"),path,file);
32e71fa4
FM
1398 exit(1);
1399 }
491b862f 1400 fp = popen(cmd, "r");
05b90947 1401 if (!fgets(response, sizeof(response), fp)) {
10210234 1402 debuga(_("Cannot get disk size with command %s\n"),cmd);
05b90947
FM
1403 exit(1);
1404 }
9c7c6346
FM
1405 ptr=strchr(response,'\t');
1406 if (ptr==NULL) {
10210234 1407 debuga(_("The command %s failed\n"),cmd);
4bcb77cf
FM
1408 exit(1);
1409 }
491b862f 1410 pclose(fp);
9c7c6346 1411 *ptr='\0';
491b862f 1412
9c7c6346 1413 return (response);
491b862f
GS
1414}
1415
dfb337be
FM
1416void show_info(FILE *fp_ou)
1417{
1418 char ftime[127];
1419
e6414a9d 1420 if(!ShowSargInfo) return;
120d768c 1421 zdate(ftime, sizeof(ftime), DateFormat);
c36c7384 1422 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
1423}
1424
c0ec9cc7 1425void show_sarg(FILE *fp_ou, int depth)
dfb337be 1426{
c0ec9cc7
FM
1427 int i;
1428
1429 if(!ShowSargLogo) return;
1430 fputs("<div class=\"logo\"><a href=\"http://sarg.sourceforge.net\"><img src=\"",fp_ou);
1431 for (i=0 ; i<depth ; i++)
1432 fputs("../",fp_ou);
1433 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
1434}
1435
1436void write_logo_image(FILE *fp_ou)
1437{
1438 if(LogoImage[0]!='\0')
c0ec9cc7 1439 fprintf(fp_ou, "<div class=\"logo\"><img src=\"%s\" width=\"%s\" height=\"%s\" alt=\"Logo\">&nbsp;%s</div>\n",LogoImage,Width,Height,LogoText);
dfb337be 1440}
491b862f 1441
c0ec9cc7 1442void write_html_header(FILE *fp_ou, int depth, const char *page_title)
491b862f 1443{
c0ec9cc7
FM
1444 //fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n",fp_ou);
1445 fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n<html>\n",fp_ou);
1446 fprintf(fp_ou, "<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n",CharSet);
1447 if (page_title) fprintf(fp_ou,"<title>%s</title>\n",page_title);
491b862f 1448 css(fp_ou);
dfb337be
FM
1449 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);
1450 write_logo_image(fp_ou);
c0ec9cc7
FM
1451 show_sarg(fp_ou, depth);
1452 fprintf(fp_ou,"<div class=\"title\"><table cellpadding=\"0\" cellspacing=\"0\">\n<tr><th class=\"title_c\">%s</th></tr>\n",Title);
1453}
1454
1455void close_html_header(FILE *fp_ou)
1456{
1457 fputs("</table></div>\n",fp_ou);
1458}
1459
1460void write_html_trailer(FILE *fp_ou)
1461{
1462 show_info(fp_ou);
1463 fputs("</body>\n</html>\n",fp_ou);
dfb337be
FM
1464}
1465
ac422f9b 1466void output_html_string(FILE *fp_ou,const char *str,int maxlen)
dfb337be 1467{
ac422f9b 1468 int i=0;
dfb337be 1469
ac422f9b 1470 while (*str && (maxlen<=0 || i<maxlen)) {
dfb337be
FM
1471 switch (*str) {
1472 case '&':
1473 fputs("&amp;",fp_ou);
1474 break;
1475 case '<':
1476 fputs("&lt;",fp_ou);
1477 break;
1478 case '>':
1479 fputs("&gt;",fp_ou);
1480 break;
1481 case '"':
1482 fputs("&quot;",fp_ou);
1483 break;
1484 case '\'':
1485 fputs("&#39;",fp_ou);
1486 break;
1487 default:
1488 fputc(*str,fp_ou);
1489 }
1490 str++;
ac422f9b
FM
1491 i++;
1492 }
1493 if (maxlen>0 && i>=maxlen)
1494 fputs("&hellip;",fp_ou);
1495}
1496
1497void output_html_url(FILE *fp_ou,const char *url)
1498{
1499 while (*url) {
1500 if (*url=='&')
1501 fputs("&amp;",fp_ou);
1502 else
1503 fputc(*url,fp_ou);
1504 url++;
dfb337be 1505 }
491b862f
GS
1506}
1507
32e71fa4 1508void baddata(void)
491b862f 1509{
51465d08 1510 char dir[1024];
05b90947 1511
d6e703cc 1512 printf("SARG: ------------------------------------------------------------------------------\n");
10210234
FM
1513 printf(_("SARG: MALICIUS CODE DETECTED.\n"));
1514 printf(_("SARG: I think someone is trying to execute arbitrary code in your system using sarg.\n"));
1515 printf(_("SARG: please review your access.log and/or your useragent.log file.\n"));
1516 printf(_("SARG: process stoped. No actions taken.\n"));
d6e703cc
FM
1517 printf("SARG: ------------------------------------------------------------------------------\n");
1518
51465d08 1519 if (snprintf(dir,sizeof(dir),"%s/sarg",tmp)>=sizeof(dir)) {
10210234 1520 debuga(_("temporary directory too long: %s/sarg\n"),tmp);
05b90947
FM
1521 exit(1);
1522 }
51465d08
FM
1523 unlinkdir(dir,0);
1524 unlinkdir(dirname,0);
d6e703cc
FM
1525
1526 exit(1);
491b862f
GS
1527}
1528
f84a35a3
FM
1529void url_hostname(const char *url,char *hostname,int hostsize)
1530{
1531 int i;
1532
1533 hostsize--;
1534 for (i=0 ; i<hostsize && url[i] && url[i]!='/' ; i++)
1535 hostname[i]=url[i];
1536 hostname[i]='\0';
1537}
491b862f 1538
48864d28 1539void url_module(const char *url, char *w2)
25697a35
GS
1540{
1541 int x, y;
1542 char w[255];
1543
25697a35
GS
1544 y=0;
1545 for(x=strlen(url)-1; x>=0; x--) {
48864d28
FM
1546 if(url[x] == '/' || y>=sizeof(w)-1) break;
1547 w[y++]=url[x];
25697a35 1548 }
4157aa09
FM
1549 if (x<0) {
1550 w2[0]='\0';
1551 return;
1552 }
25697a35 1553
48864d28
FM
1554 x=0;
1555 for(y=y-1; y>=0; y--) {
1556 w2[x++]=w[y];
25697a35 1557 }
4157aa09 1558 w2[x]='\0';
25697a35
GS
1559}
1560
e5b2c6f0
FM
1561void url_to_file(const char *url,char *file,int filesize)
1562{
1563 int i,skip;
1564
1565 filesize--;
1566 skip=0;
1567 for(i=0; i<filesize && *url; url++) {
1568 if(*url=='?' || *url=='-' || *url=='.' || *url==':' || *url=='/' || *url=='\\' ||
1569 *url=='*' || *url=='\'' || *url=='\"' || *url=='$') {
1570 if (!skip) file[i++]='_';
1571 skip=1;
1572 } else {
1573 file[i++]=*url;
1574 skip=0;
1575 }
1576 }
1577 file[i]='\0';
1578}
d6e703cc 1579
32e71fa4 1580void version(void)
25697a35 1581{
d25d4e6a 1582 printf(_("SARG Version: %s\n"),VERSION);
25697a35
GS
1583 exit(0);
1584}
5f3cfd1d
FM
1585
1586char *get_param_value(const char *param,char *line)
1587{
1588 int plen;
2357ef77 1589
5f3cfd1d
FM
1590 while (*line==' ' || *line=='\t') line++;
1591 plen=strlen(param);
1592 if (strncasecmp(line,param,plen)) return(NULL);
1593 if (line[plen]!=' ' && line[plen]!='\t') return(NULL);
1594 line+=plen;
1595 while (*line==' ' || *line=='\t') line++;
1596 return(line);
1597}
936c9905 1598
51465d08 1599void unlinkdir(const char *dir,int contentonly)
304a739d 1600{
51465d08
FM
1601 struct stat st;
1602 DIR *dirp;
1603 struct dirent *direntp;
1604 char dname[MAXLEN];
463f8e09 1605 int err;
51465d08
FM
1606
1607 dirp=opendir(dir);
1608 if (!dirp) return;
1609 while ((direntp = readdir(dirp)) != NULL) {
1610 if (direntp->d_name[0] == '.' && (direntp->d_name[1] == '\0' ||
1611 (direntp->d_name[1] == '.' && direntp->d_name[2] == '\0')))
1612 continue;
1613 if (snprintf(dname,sizeof(dname),"%s/%s",dir,direntp->d_name)>=sizeof(dname)) {
10210234 1614 debuga(_("directory name to delete too long: %s/%s\n"),dir,direntp->d_name);
51465d08
FM
1615 exit(1);
1616 }
463f8e09
FM
1617#ifdef HAVE_LSTAT
1618 err=lstat(dname,&st);
1619#else
1620 err=stat(dname,&st);
1621#endif
1622 if (err) {
10210234 1623 debuga(_("cannot stat %s\n"),dname);
51465d08
FM
1624 exit(1);
1625 }
1626 if (S_ISREG(st.st_mode)) {
1627 if (unlink(dname)) {
10210234 1628 debuga(_("cannot delete %s - %s\n"),dname,strerror(errno));
51465d08 1629 exit(1);
304a739d 1630 }
51465d08 1631 } else if (S_ISDIR(st.st_mode)) {
0511cf2d 1632 unlinkdir(dname,0);
51465d08 1633 } else {
10210234 1634 debuga(_("unknown path type %s\n"),dname);
304a739d
FM
1635 }
1636 }
51465d08 1637 closedir(dirp);
304a739d 1638
51465d08
FM
1639 if (!contentonly) {
1640 if (rmdir(dir)) {
10210234 1641 debuga(_("cannot delete %s - %s\n"),dir,strerror(errno));
51465d08
FM
1642 exit(1);
1643 }
1644 }
1645}
ac422f9b
FM
1646
1647int longline_prepare(struct longlinestruct *line)
1648{
1649 line->size=INITIAL_LINE_BUFFER_SIZE;
1650 line->buffer=malloc(line->size);
1651 if (!line->buffer)
1652 return(-1);
1653 line->start=0;
1654 line->end=0;
1655 line->length=0;
1656 return(0);
1657}
1658
1659char *longline_read(FILE *fp_in,struct longlinestruct *line)
1660{
1661 int i;
ac422f9b
FM
1662 char *newbuf;
1663 size_t nread;
1664
1665 if (!line->buffer) return(NULL);
ac422f9b 1666
0445cbf9
FM
1667 while (1) {
1668 for (i=line->end ; i<line->length && (line->buffer[i]=='\n' || line->buffer[i]=='\r') ; i++);
1669 if (i<line->length) {
1670 line->end=i;
1671 break;
1672 }
1673 nread=(feof(fp_in)) ? 0 : fread(line->buffer,1,line->size,fp_in);
1674 if (nread==0) return(NULL);
1675 line->length=nread;
1676 line->end=0;
1677 }
1678
ac422f9b 1679 line->start=line->end;
c4e25148 1680 while (1) {
0445cbf9
FM
1681 for (i=line->end ; i<line->length && line->buffer[i]!='\n' && line->buffer[i]!='\r' ; i++);
1682 line->end=i;
1683 if (line->end<line->length) break;
1684
1685 if (line->start>0) {
1686 for (i=line->start ; i<line->length ; i++) line->buffer[i-line->start]=line->buffer[i];
1687 line->length-=line->start;
1688 line->end-=line->start;
1689 line->start=0;
1690 }
1691 if (line->length>=line->size) {
1692 line->size+=8192;
1693 newbuf=realloc(line->buffer,line->size);
1694 if (!newbuf) {
10210234 1695 debuga(_("Not enough memory to read one more line from the input log file\n"));
0445cbf9 1696 exit(1);
ac422f9b 1697 }
0445cbf9
FM
1698 line->buffer=newbuf;
1699 }
1700 nread=(feof(fp_in)) ? 0 : fread(line->buffer+line->length,1,line->size-line->length,fp_in);
1701 if (nread==0) {
1702 if (line->end<=line->start) return(NULL);
1703 if (line->end>=line->size) {
1704 line->end=line->size;
1705 line->size++;
ac422f9b
FM
1706 newbuf=realloc(line->buffer,line->size);
1707 if (!newbuf) {
10210234 1708 debuga(_("Not enough memory to read one more line from the input log file\n"));
ac422f9b
FM
1709 exit(1);
1710 }
1711 line->buffer=newbuf;
1712 }
0445cbf9
FM
1713 line->buffer[line->end]='\0';
1714 return(line->buffer+line->start);
ac422f9b 1715 }
0445cbf9 1716 line->length+=nread;
ac422f9b
FM
1717 }
1718 line->buffer[line->end++]='\0';
1719 return(line->buffer+line->start);
1720}
1721
1722void longline_free(struct longlinestruct *line)
1723{
1724 if (line->buffer) {
1725 free(line->buffer);
1726 line->buffer=NULL;
1727 }
1728}