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