sarg  2.4.0
About: SARG ia a Squid Analysis Report Generator.
  Fossies Dox: sarg-2.4.0.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

util.c
Go to the documentation of this file.
1 /*
2  * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
3  * 1998, 2015
4  *
5  * SARG donations:
6  * please look at http://sarg.sourceforge.net/donations.php
7  * Support:
8  * http://sourceforge.net/projects/sarg/forums/forum/363374
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"
31 #include "include/defs.h"
32 
33 #if defined(__MINGW32__) && defined(HAVE_DIRECT_H)
34 #define NO_OLDNAMES 1
35 #include <direct.h>
36 #endif
37 
38 #if defined(HAVE_BACKTRACE)
39 #define USE_GETWORD_BACKTRACE 1
40 #else
41 #define USE_GETWORD_BACKTRACE 0
42 #endif
43 
44 static char mtab1[12][4]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
45 
47 static char *excludecode=NULL;
48 
50 char ImageDir[MAXLEN]=IMAGEDIR;
51 
52 extern char *CurrentLocale;
53 
54 #if USE_GETWORD_BACKTRACE
55 static void getword_backtrace(void)
56 {
57  void *buffer[5];
58  int i, n;
59  char **calls;
60 
61  n=backtrace(buffer,sizeof(buffer)/sizeof(buffer[0]));
62  if (n<=0) return;
63  calls=backtrace_symbols(buffer,n);
64  if (calls) {
65  debuga(__FILE__,__LINE__,_("getword backtrace:\n"));
66  for (i=0 ; i<n ; i++) {
67  fprintf(stderr,"SARG: %d:%s\n",i+1,calls[i]);
68  }
69  free(calls);
70  }
71 }
72 #endif //USE_GETWORD_BACKTRACE
73 
74 void getword_start(struct getwordstruct *gwarea, const char *line)
75 {
76  gwarea->beginning=line;
77  gwarea->current=line;
78  gwarea->modified=0;
79 }
80 
81 void getword_restart(struct getwordstruct *gwarea)
82 {
83  if (gwarea->modified) {
84  debuga(__FILE__,__LINE__,_("Cannot parse again the line as it was modified\n"));
85  exit(EXIT_FAILURE);
86  }
87  gwarea->current=gwarea->beginning;
88 }
89 
90 int getword(char *word, int limit, struct getwordstruct *gwarea, char stop)
91 {
92  int x;
93 
94  for (x=0;((gwarea->current[x]) && (gwarea->current[x] != stop ));x++) {
95  if (x>=limit) {
96  /*
97  TRANSLATORS: The %s is the name of the function reporting the
98  error message.
99  */
100  debuga(__FILE__,__LINE__,_("End of word not found in %s after %d bytes.\n"),__func__,x);
101  debuga(__FILE__,__LINE__,_("Line=\"%s\"\n"),gwarea->beginning);
102  debuga(__FILE__,__LINE__,_("Record=\"%s\"\n"),gwarea->current);
103  debuga(__FILE__,__LINE__,_("searching for \'x%x\'\n"),stop);
104  word[(limit>0) ? limit-1 : 0]='\0';
105 #if USE_GETWORD_BACKTRACE
106  getword_backtrace();
107 #endif
108  return(-1);
109  }
110  word[x] = gwarea->current[x];
111  }
112 
113  word[x] = '\0';
114  if (gwarea->current[x]) ++x;
115  gwarea->current+=x;
116  return(0);
117 }
118 
119 int getword_limit(char *word, int limit, struct getwordstruct *gwarea, char stop)
120 {
121  int x;
122 
123  limit--;
124  for (x=0; x<limit && gwarea->current[x] && gwarea->current[x] != stop ;x++) {
125  word[x] = gwarea->current[x];
126  }
127  word[x] = '\0';
128  gwarea->current+=x;
129  while (*gwarea->current && *gwarea->current != stop) gwarea->current++;
130  if (*gwarea->current) ++gwarea->current;
131  return(0);
132 }
133 
134 int getword_multisep(char *word, int limit, struct getwordstruct *gwarea, char stop)
135 {
136  int x;
137 
138  for (x=0;((gwarea->current[x]) && (gwarea->current[x] != stop ));x++) {
139  if (x>=limit) {
140  debuga(__FILE__,__LINE__,_("End of word not found in %s after %d bytes.\n"),__func__,x);
141  debuga(__FILE__,__LINE__,_("Line=\"%s\"\n"),gwarea->beginning);
142  debuga(__FILE__,__LINE__,_("Record=\"%s\"\n"),gwarea->current);
143  debuga(__FILE__,__LINE__,_("searching for \'x%x\'\n"),stop);
144  if (limit>0) word[limit-1]='\0';
145 #if USE_GETWORD_BACKTRACE
146  getword_backtrace();
147 #endif
148  //exit(EXIT_FAILURE);
149  return(-1);
150  }
151  word[x] = gwarea->current[x];
152  }
153 
154  word[x] = '\0';
155  while (gwarea->current[x] && gwarea->current[x]==stop) ++x;
156  gwarea->current+=x;
157  return(0);
158 }
159 
160 int getword_skip(int limit, struct getwordstruct *gwarea, char stop)
161 {
162  int x;
163 
164  for (x=0;(gwarea->current[x] && (gwarea->current[x] != stop ));x++) {
165  if (x>=limit) {
166  debuga(__FILE__,__LINE__,_("End of word not found in %s after %d bytes.\n"),__func__,x);
167  debuga(__FILE__,__LINE__,_("Line=\"%s\"\n"),gwarea->beginning);
168  debuga(__FILE__,__LINE__,_("Record=\"%s\"\n"),gwarea->current);
169  debuga(__FILE__,__LINE__,_("searching for \'x%x\'\n"),stop);
170 #if USE_GETWORD_BACKTRACE
171  getword_backtrace();
172 #endif
173  return(-1);
174  }
175  }
176 
177  if (gwarea->current[x]) ++x;
178  gwarea->current+=x;
179  return(0);
180 }
181 
182 int getword_atoll(long long int *number, struct getwordstruct *gwarea, char stop)
183 {
184  int x;
185  int sign=+1;
186  int digit;
187 
188  if (gwarea->current[0] == '-') {
189  gwarea->current++;
190  sign=-1;
191  } else if (gwarea->current[0] == '+') {
192  gwarea->current++;
193  }
194  *number=0LL;
195  for (x=0;isdigit(gwarea->current[x]);x++) {
196  digit=gwarea->current[x]-'0';
197  if (*number >= (LLONG_MAX-digit)/10) {
198  /*
199  TRANSLATORS: The first %s is the function name (in the source code) where the
200  overflow is detected.
201  */
202  debuga(__FILE__,__LINE__,_("Integer overflow detected in %s in line %s\n"),__func__,gwarea->beginning);
203  return(-1);
204  }
205  *number=(*number * 10) + digit;
206  }
207  if (gwarea->current[x] && gwarea->current[x]!=stop) {
208  /*
209  TRANSLATORS: The %s is the function name, in the source code, where the problem occured.
210  */
211  debuga(__FILE__,__LINE__,_("End of number not found in %s after %d bytes.\n"),__func__,x);
212  debuga(__FILE__,__LINE__,_("Line=\"%s\"\n"),gwarea->beginning);
213  debuga(__FILE__,__LINE__,_("Record=\"%s\"\n"),gwarea->current);
214  debuga(__FILE__,__LINE__,_("searching for \'x%x\'\n"),stop);
215 #if USE_GETWORD_BACKTRACE
216  getword_backtrace();
217 #endif
218  return(-1);
219  }
220  *number*=sign;
221 
222  if (gwarea->current[x]) ++x;
223  gwarea->current+=x;
224  return(0);
225 }
226 
227 int getword_atoi(int *number, struct getwordstruct *gwarea, char stop)
228 {
229  int x;
230  int sign=+1;
231  int digit;
232 
233  if (gwarea->current[0] == '-') {
234  gwarea->current++;
235  sign=-1;
236  } else if (gwarea->current[0] == '+') {
237  gwarea->current++;
238  }
239  *number=0;
240  for (x=0;isdigit(gwarea->current[x]);x++) {
241  digit=gwarea->current[x]-'0';
242  if (*number > (INT_MAX-digit)/10) {
243  debuga(__FILE__,__LINE__,_("Integer overflow detected in %s in line %s\n"),__func__,gwarea->beginning);
244  return(-1);
245  }
246  *number=(*number * 10) + digit;
247  }
248  if (gwarea->current[x] && gwarea->current[x]!=stop) {
249  debuga(__FILE__,__LINE__,_("End of number not found in %s after %d bytes.\n"),__func__,x);
250  debuga(__FILE__,__LINE__,_("Line=\"%s\"\n"),gwarea->beginning);
251  debuga(__FILE__,__LINE__,_("Record=\"%s\"\n"),gwarea->current);
252  debuga(__FILE__,__LINE__,_("searching for \'x%x\'\n"),stop);
253 #if USE_GETWORD_BACKTRACE
254  getword_backtrace();
255 #endif
256  return(-1);
257  }
258  *number*=sign;
259 
260  if (gwarea->current[x]) ++x;
261  gwarea->current+=x;
262  return(0);
263 }
264 
265 int getword_atol(long int *number, struct getwordstruct *gwarea, char stop)
266 {
267  int x;
268  long int sign=+1;
269  int digit;
270 
271  if (gwarea->current[0] == '-') {
272  gwarea->current++;
273  sign=-1;
274  } else if (gwarea->current[0] == '+') {
275  gwarea->current++;
276  }
277  *number=0;
278  for (x=0;isdigit(gwarea->current[x]);x++) {
279  digit=gwarea->current[x]-'0';
280  if (*number > (LONG_MAX-digit)/10) {
281  debuga(__FILE__,__LINE__,_("Integer overflow detected in %s in line %s\n"),__func__,gwarea->beginning);
282  return(-1);
283  }
284  *number=(*number * 10) + digit;
285  }
286  if (gwarea->current[x] && gwarea->current[x]!=stop) {
287  debuga(__FILE__,__LINE__,_("End of number not found in %s after %d bytes.\n"),__func__,x);
288  debuga(__FILE__,__LINE__,_("Line=\"%s\"\n"),gwarea->beginning);
289  debuga(__FILE__,__LINE__,_("Record=\"%s\"\n"),gwarea->current);
290  debuga(__FILE__,__LINE__,_("searching for \'x%x\'\n"),stop);
291 #if USE_GETWORD_BACKTRACE
292  getword_backtrace();
293 #endif
294  return(-1);
295  }
296  *number*=sign;
297 
298  if (gwarea->current[x]) ++x;
299  gwarea->current+=x;
300  return(0);
301 }
302 
303 int getword_atolu(unsigned long int *number, struct getwordstruct *gwarea, char stop)
304 {
305  int x;
306  int digit;
307 
308  if (gwarea->current[0] == '-') {
309  debuga(__FILE__,__LINE__,_("getword_atolu got a negative number.\n"));
310  debuga(__FILE__,__LINE__,_("Line=\"%s\"\n"),gwarea->beginning);
311  debuga(__FILE__,__LINE__,_("Record=\"%s\"\n"),gwarea->current);
312  return(-1);
313  }
314  if (gwarea->current[0] == '+') {
315  gwarea->current++;
316  }
317  *number=0;
318  for (x=0;isdigit(gwarea->current[x]);x++) {
319  digit=gwarea->current[x]-'0';
320  if (*number > (ULONG_MAX-digit)/10) {
321  debuga(__FILE__,__LINE__,_("Integer overflow detected in %s in line %s\n"),__func__,gwarea->beginning);
322  return(-1);
323  }
324  *number=(*number * 10) + digit;
325  }
326  if (gwarea->current[x] && gwarea->current[x]!=stop) {
327  debuga(__FILE__,__LINE__,_("End of number not found in %s after %d bytes.\n"),__func__,x);
328  debuga(__FILE__,__LINE__,_("Line=\"%s\"\n"),gwarea->beginning);
329  debuga(__FILE__,__LINE__,_("Record=\"%s\"\n"),gwarea->current);
330  debuga(__FILE__,__LINE__,_("searching for \'x%x\'\n"),stop);
331 #if USE_GETWORD_BACKTRACE
332  getword_backtrace();
333 #endif
334  return(-1);
335  }
336 
337  if (gwarea->current[x]) ++x;
338  gwarea->current+=x;
339  return(0);
340 }
341 
342 
343 int getword_ptr(char *orig_line,char **word, struct getwordstruct *gwarea, char stop)
344 {
351  int x;
352  int sep;
353  int start;
354 
355  if (orig_line && orig_line!=gwarea->beginning) {
356  debuga(__FILE__,__LINE__,_("Invalid buffer passed to getword_ptr\n"));
357  return(-1);
358  }
359 
360  start=(gwarea->current-gwarea->beginning);
361  if (word && orig_line) *word=orig_line+start;
362  for (x=0;((gwarea->current[x]) && (gwarea->current[x] != stop ));x++);
363  sep=(gwarea->current[x]!='\0');
364  if (word && orig_line) orig_line[start+x] = '\0';
365  if (sep) ++x;
366  gwarea->current+=x;
367  gwarea->modified=1;
368  return(0);
369 }
370 
371 #define MAXLLL 30
372 long long int my_atoll (const char *nptr)
373 {
374  long long int returnval=0LL;
375  int max_digits = MAXLLL ;
376 
377  // Soak up all the white space
378  while (isspace( *nptr )) {
379  nptr++;
380  }
381 
382  //For each character left to right
383  //change the character to a single digit
384  //multiply what we had before by 10 and add the new digit
385 
386  while (--max_digits && isdigit( *nptr ))
387  {
388  returnval = ( returnval * 10 ) + ( *nptr++ - '0' ) ;
389  }
390 
391  return returnval;
392 }
393 
394 int is_absolute(const char *path)
395 {
396  if (*path=='/') return(1);
397 #ifdef _WIN32
398  if (isalpha(path[0]) && path[1]==':') return(1);
399 #endif
400  return(0);
401 }
402 
403 int PortableMkDir(const char *path,int mode)
404 {
405 #if defined(__linux__)
406  int mkerror=mkdir(path,mode);
407 #else //mingw
408  (void)mode;
409  int mkerror=_mkdir(path);
410 #endif
411  return(mkerror);
412 }
413 
419 bool my_mkdir(const char *name)
420 {
421  char w0[MAXLEN];
422  int i;
423  int chars;
424  bool created = false;
425  struct stat st;
426 
427  if (!is_absolute(name)) {
428  debuga(__FILE__,__LINE__,_("Invalid path (%s). Please, use absolute paths only.\n"),name);
429  exit(EXIT_FAILURE);
430  }
431 
432  chars=0;
433  for (i=0 ; name[i] ; i++) {
434  if (i>=sizeof(w0)) {
435  debuga(__FILE__,__LINE__,_("Path too long: "));
436  debuga_more("%s\n",name);
437  exit(EXIT_FAILURE);
438  }
439  if (chars>0 && name[i] == '/') {
440  w0[i] = '\0';
441  if (access(w0, R_OK) != 0) {
442  if (PortableMkDir(w0,0755)) {
443  debuga(__FILE__,__LINE__,_("Cannot create directory \"%s\": %s\n"),w0,strerror(errno));
444  exit(EXIT_FAILURE);
445  }
446  }
447  }
448  if (name[i] != '/') chars++;
449  w0[i] = name[i];
450  }
451 
452  if (access(name, R_OK) != 0) {
453  if (PortableMkDir(name,0755)) {
454  debuga(__FILE__,__LINE__,_("Cannot create directory \"%s\": %s\n"),name,strerror(errno));
455  exit(EXIT_FAILURE);
456  }
457  created = true;
458  }
459  if (!created) {
460  /*
461  * Check the final path is a directory (symlink to a directory is ok).
462  */
463  if (stat(name, &st)) {
464  debuga(__FILE__,__LINE__,_("Cannot stat \"%s\": %s\n"), name, strerror(errno));
465  exit(EXIT_FAILURE);
466  }
467  if (!S_ISDIR(st.st_mode)) {
468  debuga(__FILE__,__LINE__,_("Directory \"%s\" can't be created because the path already exists and is not a directory\n"), name);
469  exit(EXIT_FAILURE);
470  }
471  }
472  return created;
473 }
474 
475 void makeTmpDir(const char *tmp)
476 {
477  /*
478  * We must ensure the temporary directory is ours. In particular, we must make sure no malicious
479  * users managed to create or replace the temporary directory with a symlink to a system directory.
480  * As sarg purges the content of the temporary directory upon exit, should the temporary directory
481  * be hijacked, sarg could be tricked in deleting system files such as /bin or users files in /home
482  * or logs in /var/log.
483  *
484  * The code first create the temporary directory. If it wasn't created, the content is checked and
485  * purged if it looks safe to delete every file and directory it contains.
486  */
487  if (!my_mkdir(tmp)) {
488  if (debug) debuga(__FILE__, __LINE__, _("Purging temporary directory \"%s\"\n"), tmp);
489  emptytmpdir(tmp);
490  }
491 }
492 
493 void my_lltoa(unsigned long long int n, char *s, int ssize, int len)
494 {
495  int i;
496  int slen = 0;
497  int j;
498  char c;
499 
500  ssize--;
501  if (len>ssize) {
502  debuga(__FILE__,__LINE__,_("The requested number of digits passed to my_lltoa (%d) is bigger than the output buffer size (%d)\n"),len,ssize);
503  abort();
504  }
505 
506  do {
507  s[slen++] = (n % 10) + '0';
508  } while ((n /= 10) > 0 && slen<ssize);
509  s[slen] = '\0';
510 
511  for (i = 0, j = slen-1; i<j; i++, j--) {
512  c = s[i];
513  s[i] = s[j];
514  s[j] = c;
515  }
516 
517  if (len>slen) {
518  i=len-slen;
519  for (j=slen; j>=0; j--)
520  s[j+i]=s[j];
521  for (j=0 ; j<i ; j++)
522  s[j]='0';
523  }
524 }
525 
526 int month2num(const char *month)
527 {
528  int m;
529 
530  for (m=0 ; m<12 && strcmp(mtab1[m],month) != 0; m++);
531  return(m);
532 }
533 
534 int builddia(int day, int month, int year)
535 {
536  return(year*10000+month*100+day);
537 }
538 
549 int compare_date(const struct tm *date1,const struct tm *date2)
550 {
551  if (date1->tm_year<date2->tm_year) return(-1);
552  if (date1->tm_year>date2->tm_year) return(1);
553  if (date1->tm_mon<date2->tm_mon) return(-1);
554  if (date1->tm_mon>date2->tm_mon) return(1);
555  if (date1->tm_mday<date2->tm_mday) return(-1);
556  if (date1->tm_mday>date2->tm_mday) return(1);
557  if (date1->tm_hour<date2->tm_hour) return(-1);
558  if (date1->tm_hour>date2->tm_hour) return(1);
559  if (date1->tm_min<date2->tm_min) return(-1);
560  if (date1->tm_min>date2->tm_min) return(1);
561  if (date1->tm_sec<date2->tm_sec) return(-1);
562  if (date1->tm_sec>date2->tm_sec) return(1);
563  return(0);
564 }
565 
566 void buildymd(const char *dia, const char *mes, const char *ano, char *wdata,int wdata_size)
567 {
568  int nmes;
569 
570  nmes=month2num(mes);
571  snprintf(wdata,wdata_size,"%04d%02d%02d",atoi(ano),nmes+1,atoi(dia));
572 }
573 
574 
575 int conv_month(const char *month)
576 {
577  int x;
578 
579  for (x=0; x<12 && strncmp(mtab1[x],month,3)!=0; x++);
580  return(x+1);
581 }
582 
583 
584 const char *conv_month_name(int month)
585 {
586  static char str[4];
587 
588  if (month<1 || month>12) {
589  snprintf(str,sizeof(str),"%03d",month);
590  return(str);
591  }
592  return(mtab1[month-1]);
593 }
594 
601 void debuga(const char *File,int Line,const char *msg,...)
602 {
603  va_list ap;
604 
605  if (debugz>=LogLevel_Source) {
606  /* The path is removed because every source file is in the same directory.
607  * There is no point in reporting the full path from the build directory.
608  */
609  const char *ptr=strrchr(File,'/');
610  if (!ptr) ptr=File;
611  /* TRANSLATORS: This is the prefix to stderr messages when the debug level is
612  set to display the source file (%s) and the line number (%d). */
613  fprintf(stderr,_("SARG(%s:%d): "),ptr,Line);
614  } else {
615  /* TRANSLATORS: This is the prefix to stderr messages when the debug level
616  is low. */
617  fputs(_("SARG: "),stderr);
618  }
619  va_start(ap,msg);
620  vfprintf(stderr,msg,ap);
621  va_end(ap);
622 }
623 
631 void debuga_more(const char *msg,...)
632 {
633  va_list ap;
634 
635  va_start(ap,msg);
636  vfprintf(stderr,msg,ap);
637  va_end(ap);
638 }
639 
646 void debugaz(const char *File,int Line,const char *msg,...)
647 {
648  va_list ap;
649 
650  if (debugz>=LogLevel_Source) {
651  /* The path is removed because every source file is in the same directory.
652  * There is no point in reporting the full path from the build directory.
653  */
654  const char *ptr=strrchr(File,'/');
655  if (!ptr) ptr=File;
656  /* TRANSLATORS: This is the prefix to information messages when the debug level is
657  set to display the source file (%s) and the line number (%d). */
658  fprintf(stderr,_("SARG(%s:%d): (info) "),ptr,Line);
659  } else {
660  /* TRANSLATORS: This is the prefix to information messages when the debug level
661  is low. */
662  fputs(_("SARG: (info) "),stderr);
663  }
664  va_start(ap,msg);
665  vfprintf(stderr,msg,ap);
666  va_end(ap);
667 }
668 
669 
670 char *fixnum(long long int value, int n)
671 {
672 #define MAXLEN_FIXNUM 256
673  char num[MAXLEN_FIXNUM]="";
674  char buf[MAXLEN_FIXNUM * 2];
675  char *pbuf;
676  static char ret[MAXLEN_FIXNUM * 2];
677  char *pret;
678  register int i, j, k;
679  int numlen;
680  static char abbrev[30]="";
681 
682  my_lltoa(value, num, sizeof(num), 0);
683 
685  numlen = strlen(num);
686  if (numlen <= 3)
687  strcpy(abbrev,num);
688  else if (numlen%3 == 1) {
689  abbrev[0]=num[0];
690  abbrev[1]=(UseComma) ? ',' : '.';
691  abbrev[2]=num[1];
692  abbrev[3]=num[2];
693  abbrev[4]='\0';
694  }
695  else if (numlen%3 == 2) {
696  abbrev[0]=num[0];
697  abbrev[1]=num[1];
698  abbrev[2]=(UseComma) ? ',' : '.';
699  abbrev[3]=num[2];
700  abbrev[4]=num[3];
701  abbrev[5]='\0';
702  }
703  else if (numlen%3 == 0) {
704  abbrev[0]=num[0];
705  abbrev[1]=num[1];
706  abbrev[2]=num[2];
707  abbrev[3]=(UseComma) ? ',' : '.';
708  abbrev[4]=num[3];
709  abbrev[5]=num[4];
710  abbrev[6]='\0';
711  }
712  if (n) {
713  if (numlen <= 3) {
714  //no prefix
715  }
716  else if (numlen <= 6)
717  strcat(abbrev,"K");
718  else if (numlen <= 9)
719  strcat(abbrev,"M");
720  else if (numlen <= 12)
721  strcat(abbrev,"G");
722  else if (numlen <= 15)
723  strcat(abbrev,"T");
724  else if (numlen >= 18)
725  strcat(abbrev,"P");
726  else if (numlen <= 21)
727  strcat(abbrev,"E");
728  else if (numlen <= 24)
729  strcat(abbrev,"Z");
730  else if (numlen <= 27)
731  strcat(abbrev,"Y");
732  else
733  strcat(abbrev,"???");
734  }
735  return(abbrev);
736  }
737 
738  memset(buf,0,MAXLEN_FIXNUM*2);
739 
740  pbuf = buf;
741  pret = ret;
742  k = 0;
743 
744  for ( i = strlen(num) - 1, j = 0 ; i > -1; i--) {
745  if ( k == 2 && i != 0 ) {
746  k = 0;
747  pbuf[j++] = num[i];
748  pbuf[j++] = (UseComma) ? ',' : '.';
749  continue;
750  }
751  pbuf[j] = num[i];
752  j++;
753  k++;
754  }
755 
756  pret[0]='\0';
757 
758  for ( i = strlen(pbuf) - 1, j = 0 ; i > -1; i--, j++)
759  pret[j] = pbuf[i];
760 
761  pret[j] = '\0';
762 
763  return pret;
764 }
765 
766 
767 char *fixnum2(long long int value, int n)
768 {
769 #define MAXLEN_FIXNUM2 1024
770  char num[MAXLEN_FIXNUM2];
771  char buf[MAXLEN_FIXNUM2 * 2];
772  char *pbuf;
773  static char ret[MAXLEN_FIXNUM2 * 2];
774  char *pret;
775  register int i, j, k;
776 
777  my_lltoa(value, num, sizeof(num), 0);
778  memset(buf,0,MAXLEN_FIXNUM2*2);
779 
780  pbuf = buf;
781  pret = ret;
782  k = 0;
783 
784  for ( i = strlen(num) - 1, j = 0 ; i > -1; i--) {
785  if ( k == 2 && i != 0 ) {
786  k = 0;
787  pbuf[j++] = num[i];
788  pbuf[j++] = (UseComma) ? ',' : '.';
789  continue;
790  }
791  pbuf[j] = num[i];
792  j++;
793  k++;
794  }
795 
796  pret[0]='\0';
797 
798  for ( i = strlen(pbuf) - 1, j = 0 ; i > -1; i--, j++)
799  pret[j] = pbuf[i];
800 
801  pret[j] = '\0';
802 
803  return pret;
804 }
805 
806 
807 char *buildtime(long long int elap)
808 {
809  long int num = elap / 1000LL;
810  int hor = 0;
811  int min = 0;
812  int sec = 0;
813  static char buf[20];
814 
815  hor=num / 3600L;
816  min=(num % 3600L) / 60L;
817  sec=num % 60L;
818  snprintf(buf,sizeof(buf),"%02d:%02d:%02d",hor,min,sec);
819 
820  return(buf);
821 }
822 
823 
835 int obtdate(const char *dirname, const char *name, char *data)
836 {
837  FILE *fp_in;
838  char wdir[MAXLEN];
839 
840  if (snprintf(wdir,sizeof(wdir),"%s%s/sarg-date",dirname,name)>=sizeof(wdir)) {
841  debuga(__FILE__,__LINE__,_("Buffer too small to store "));
842  debuga_more("%s%s/sarg-date",dirname,name);
843  exit(EXIT_FAILURE);
844  }
845  if ((fp_in = fopen(wdir, "rt")) == 0) {
846  if (snprintf(wdir,sizeof(wdir),"%s%s/date",dirname,name)>=sizeof(wdir)) {
847  debuga(__FILE__,__LINE__,_("Buffer too small to store "));
848  debuga_more("%s%s/date",dirname,name);
849  exit(EXIT_FAILURE);
850  }
851  if ((fp_in = fopen(wdir, "rt")) == 0) {
852  data[0]='\0';
853  return(-1);
854  }
855  }
856 
857  if (!fgets(data,80,fp_in)) {
858  debuga(__FILE__,__LINE__,_("Failed to read the date in file \"%s\"\n"),wdir);
859  exit(EXIT_FAILURE);
860  }
861  if (fclose(fp_in)==EOF) {
862  debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),wdir,strerror(errno));
863  exit(EXIT_FAILURE);
864  }
865  fixendofline(data);
866 
867  return(0);
868 }
869 
870 
871 void formatdate(char *date,int date_size,int year,int month,int day,int hour,int minute,int second,int dst)
872 {
873  struct tm ltm;
874  time_t unixtime;
875  struct tm *fulltm;
876 
877  memset(&ltm,0,sizeof(ltm));
878  if (year>=1900) ltm.tm_year=year-1900;
879  if (month>=1 && month<=12) ltm.tm_mon=month-1;
880  if (day>=1 && day<=31) ltm.tm_mday=day;
881  if (hour>=0 && hour<24) ltm.tm_hour=hour;
882  if (minute>=0 && minute<60) ltm.tm_min=minute;
883  if (second>=0 && second<60) ltm.tm_sec=second;
884  ltm.tm_isdst=dst;
885  unixtime=mktime(&ltm); //fill the missing entries
886  fulltm=localtime(&unixtime);
887  //strftime(date,date_size,"%a %b %d %H:%M:%S %Z %Y",fulltm);
888  strftime(date,date_size,"%c",fulltm);
889 }
890 
891 
892 void computedate(int year,int month,int day,struct tm *t)
893 {
894  memset(t,0,sizeof(*t));
895  t->tm_year=year-1900;
896  t->tm_mon=month-1;
897  t->tm_mday=day;
898 }
899 
900 
901 int obtuser(const char *dirname, const char *name)
902 {
903  FILE *fp_in;
904  char wdir[MAXLEN];
905  char tuser[20];
906  int nuser;
907 
908  if (snprintf(wdir,sizeof(wdir),"%s%s/sarg-users",dirname,name)>=sizeof(wdir)) {
909  debuga(__FILE__,__LINE__,_("Buffer too small to store "));
910  debuga_more("%s%s/sarg-users",dirname,name);
911  exit(EXIT_FAILURE);
912  }
913  if ((fp_in=fopen(wdir,"r"))==NULL) {
914  if (snprintf(wdir,sizeof(wdir),"%s%s/users",dirname,name)>=sizeof(wdir)) {
915  debuga(__FILE__,__LINE__,_("Buffer too small to store "));
916  debuga_more("%s%s/users",dirname,name);
917  exit(EXIT_FAILURE);
918  }
919  if ((fp_in=fopen(wdir,"r"))==NULL) {
920  return(0);
921  }
922  }
923 
924  if (!fgets(tuser,sizeof(tuser),fp_in)) {
925  debuga(__FILE__,__LINE__,_("Failed to read the number of users in file \"%s\"\n"),wdir);
926  exit(EXIT_FAILURE);
927  }
928  if (fclose(fp_in)==EOF) {
929  debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),wdir,strerror(errno));
930  exit(EXIT_FAILURE);
931  }
932  nuser=atoi(tuser);
933 
934  return(nuser);
935 }
936 
937 
938 void obttotal(const char *dirname, const char *name, int nuser, long long int *tbytes, long long int *media)
939 {
940  FileObject *fp_in;
941  char *buf;
942  char wdir[MAXLEN];
943  char user[MAX_USER_LEN];
944  char sep;
945  struct getwordstruct gwarea;
946  longline line;
947 
948  *tbytes=0;
949  *media=0;
950 
951  if (snprintf(wdir,sizeof(wdir),"%s%s/sarg-general",dirname,name)>=sizeof(wdir)) {
952  debuga(__FILE__,__LINE__,_("Buffer too small to store "));
953  debuga_more("%s%s/sarg-general",dirname,name);
954  exit(EXIT_FAILURE);
955  }
956  if ((fp_in = FileObject_Open(wdir)) == NULL) {
957  if (snprintf(wdir,sizeof(wdir),"%s%s/general",dirname,name)>=sizeof(wdir)) {
958  debuga(__FILE__,__LINE__,_("Buffer too small to store "));
959  debuga_more("%s%s/general",dirname,name);
960  exit(EXIT_FAILURE);
961  }
962  if ((fp_in = FileObject_Open(wdir)) == NULL) {
963  return;
964  }
965  }
966 
967  if ((line=longline_create())==NULL) {
968  debuga(__FILE__,__LINE__,_("Not enough memory to read file \"%s\"\n"),wdir);
969  exit(EXIT_FAILURE);
970  }
971 
972  while((buf=longline_read(fp_in,line))!=NULL) {
973  if (strncmp(buf,"TOTAL\t",6) == 0)
974  sep='\t'; //new file
975  else if (strncmp(buf,"TOTAL ",6) == 0)
976  sep=' '; //old file
977  else
978  continue;
979  getword_start(&gwarea,buf);
980  if (getword(user,sizeof(user),&gwarea,sep)<0) {
981  debuga(__FILE__,__LINE__,_("Invalid user in file \"%s\"\n"),wdir);
982  exit(EXIT_FAILURE);
983  }
984  if (strcmp(user,"TOTAL") != 0)
985  continue;
986  if (getword_skip(MAXLEN,&gwarea,sep)<0) {
987  debuga(__FILE__,__LINE__,_("Invalid total number of accesses in file \"%s\"\n"),wdir);
988  exit(EXIT_FAILURE);
989  }
990  if (getword_atoll(tbytes,&gwarea,sep)<0) {
991  debuga(__FILE__,__LINE__,_("Invalid number of bytes in file \"%s\"\n"),wdir);
992  exit(EXIT_FAILURE);
993  }
994  break;
995  }
996  if (FileObject_Close(fp_in)) {
997  debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),wdir,FileObject_GetLastCloseError());
998  exit(EXIT_FAILURE);
999  }
1000  longline_destroy(&line);
1001 
1002  if (nuser <= 0)
1003  return;
1004 
1005  *media=*tbytes / nuser;
1006  return;
1007 }
1008 
1010 {
1011  const char *str;
1012  int day0, month0, year0, hour0, minute0;
1013  int day1, month1, year1, hour1, minute1;
1014  int i;
1015 
1016  memset(period,0,sizeof(*period));
1017 
1018  str=arqtt;
1019  while((str=strstr(str,"sarg-"))!=NULL) {
1020  str+=5;
1021  if (!isdigit(str[0]) || !isdigit(str[1])) continue;
1022  day0=(str[0]-'0')*10+(str[1]-'0');
1023  if (day0<1 || day0>31) continue;
1024  str+=2;
1025  month0=(str[0]-'0')*10+(str[1]-'0')-1;
1026  if (month0<0 || month0>11) continue;
1027  str+=2;
1028  year0=0;
1029  for (i=0 ; isdigit(str[i]) && i<4 ; i++) year0=year0*10+(str[i]-'0');
1030  if (i!=4 || year0<1900) continue;
1031  str+=4;
1032  if (str[0]!='_') continue;
1033  str++;
1034 
1035  if (!isdigit(str[0]) || !isdigit(str[1])) continue;
1036  hour0=(str[0]-'0')*10+(str[1]-'0');
1037  str+=2;
1038  if (!isdigit(str[0]) || !isdigit(str[1])) continue;
1039  minute0=(str[0]-'0')*10+(str[1]-'0');
1040  str+=2;
1041 
1042  if (*str != '-') continue;
1043  str++;
1044 
1045  if (!isdigit(str[0]) || !isdigit(str[1])) continue;
1046  day1=(str[0]-'0')*10+(str[1]-'0');
1047  if (day1<1 || day1>31) continue;
1048  str+=2;
1049  month1=(str[0]-'0')*10+(str[1]-'0')-1;
1050  if (month1<0 || month1>11) continue;
1051  str+=2;
1052  year1=0;
1053  for (i=0 ; isdigit(str[i]) && i<4 ; i++) year1=year1*10+(str[i]-'0');
1054  if (i!=4 || year1<1900) continue;
1055  str+=4;
1056 
1057  if (str[0]!='_') continue;
1058  str++;
1059 
1060  if (!isdigit(str[0]) || !isdigit(str[1])) continue;
1061  hour1=(str[0]-'0')*10+(str[1]-'0');
1062  str+=2;
1063  if (!isdigit(str[0]) || !isdigit(str[1])) continue;
1064  minute1=(str[0]-'0')*10+(str[1]-'0');
1065  str+=2;
1066 
1067  period->start.tm_mday=day0;
1068  period->start.tm_mon=month0;
1069  period->start.tm_year=year0-1900;
1070  period->start.tm_hour=hour0;
1071  period->start.tm_min=minute0;
1072  period->end.tm_mday=day1;
1073  period->end.tm_mon=month1;
1074  period->end.tm_year=year1-1900;
1075  period->end.tm_hour=hour1;
1076  period->end.tm_min=minute1;
1077  return(0);
1078  }
1079  return(-1);
1080 }
1081 
1089 {
1090  int dfrom=ReadFilter->StartDate;
1091  int duntil=ReadFilter->EndDate;
1092 
1093  memset(&period->start,0,sizeof(period->start));
1094  period->start.tm_mday=dfrom%100;
1095  period->start.tm_mon=(dfrom/100)%100-1;
1096  period->start.tm_year=(dfrom/10000)-1900;
1097 
1098  memset(&period->end,0,sizeof(period->end));
1099  period->end.tm_mday=duntil%100;
1100  period->end.tm_mon=(duntil/100)%100-1;
1101  period->end.tm_year=(duntil/10000)-1900;
1102 }
1103 
1111 void getperiod_torange(const struct periodstruct *period,int *dfrom,int *duntil)
1112 {
1113  if (dfrom)
1114  *dfrom=(period->start.tm_year+1900)*10000+(period->start.tm_mon+1)*100+period->start.tm_mday;
1115  if (duntil)
1116  *duntil=(period->end.tm_year+1900)*10000+(period->end.tm_mon+1)*100+period->end.tm_mday;
1117 }
1118 
1122 void getperiod_merge(struct periodstruct *main,struct periodstruct *candidate)
1123 {
1124  int cdate;
1125  int mdate;
1126 
1127  mdate=(main->start.tm_year)*10000+(main->start.tm_mon)*100+main->start.tm_mday;
1128  cdate=(candidate->start.tm_year)*10000+(candidate->start.tm_mon)*100+candidate->start.tm_mday;
1129  if (mdate==0 || cdate<mdate) memcpy(&main->start,&candidate->start,sizeof(struct tm));
1130 
1131  mdate=(main->end.tm_year)*10000+(main->end.tm_mon)*100+main->end.tm_mday;
1132  cdate=(candidate->end.tm_year)*10000+(candidate->end.tm_mon)*100+candidate->end.tm_mday;
1133  if (cdate>mdate) memcpy(&main->end,&candidate->end,sizeof(struct tm));
1134 }
1135 
1137 {
1138  int i;
1139  int range;
1140  char text1[40], text2[40];
1141 
1142  if (df=='u') {
1143  i=strftime(text1, sizeof(text1), "%Y %b %d", &period->start);
1144  } else if (df=='e') {
1145  i=strftime(text1, sizeof(text1), "%d %b %Y", &period->start);
1146  } else /*if (df=='w')*/ {
1148  i=strftime(text1, sizeof(text1), "%Y.%U", &period->start);
1149  }
1150  if (i == 0) return(-1);
1151 
1152  range=(period->start.tm_year!=period->end.tm_year ||
1153  period->start.tm_mon!=period->end.tm_mon ||
1154  period->start.tm_mday!=period->end.tm_mday);
1155  if (range) {
1156  if (df=='u') {
1157  i=strftime(text2, sizeof(text2)-i, "%Y %b %d", &period->end);
1158  } else if (df=='e') {
1159  i=strftime(text2, sizeof(text2)-i, "%d %b %Y", &period->end);
1160  } else {
1161  i=strftime(text2, sizeof(text2)-i, "%Y.%U", &period->end);
1162  }
1163  if (i == 0) return(-1);
1164  }
1165 
1166  if (range) {
1167  snprintf(period->text,sizeof(period->text),"%s-%s",text1,text2);
1168  snprintf(period->html,sizeof(period->html),"%s&mdash;%s",text1,text2);
1169  } else {
1170  safe_strcpy(period->text,text1,sizeof(period->text));
1171  safe_strcpy(period->html,text1,sizeof(period->html));
1172  }
1173  return(0);
1174 }
1175 
1176 static void copy_images(void)
1177 {
1178  FILE *img_in, *img_ou;
1179  char images[512];
1180  char srcfile[MAXLEN];
1181  char dstfile[MAXLEN];
1182  DIR *dirp;
1183  struct dirent *direntp;
1184  char buffer[MAXLEN];
1185  size_t nread;
1186  struct stat info;
1187 
1188  if (snprintf(images,sizeof(images),"%simages",outdir)>=sizeof(images)) {
1189  debuga(__FILE__,__LINE__,_("Cannot copy images to target directory %simages\n"),outdir);
1190  exit(EXIT_FAILURE);
1191  }
1192  if (access(images,R_OK)!=0) {
1193  if (PortableMkDir(images,0755)) {
1194  debuga(__FILE__,__LINE__,_("Cannot create directory \"%s\": %s\n"),images,strerror(errno));
1195  exit(EXIT_FAILURE);
1196  }
1197  }
1198 
1199  dirp = opendir(ImageDir);
1200  if (dirp==NULL) {
1201  debuga(__FILE__,__LINE__,_("Cannot open directory \"%s\": %s\n"),ImageDir,strerror(errno));
1202  return;
1203  }
1204  while ((direntp = readdir( dirp )) != NULL ){
1205  if (direntp->d_name[0]=='.')
1206  continue;
1207  if (snprintf(srcfile,sizeof(srcfile),"%s/%s",ImageDir,direntp->d_name)>=sizeof(srcfile)) {
1208  debuga(__FILE__,__LINE__,_("Buffer too small to store "));
1209  debuga_more("%s/%s",ImageDir,direntp->d_name);
1210  exit(EXIT_FAILURE);
1211  }
1212  if (stat(srcfile,&info)) {
1213  debuga(__FILE__,__LINE__,_("Cannot stat \"%s\": %s\n"),srcfile,strerror(errno));
1214  continue;
1215  }
1216  if (S_ISREG(info.st_mode)) {
1217  if (snprintf(dstfile,sizeof(dstfile),"%s/%s",images,direntp->d_name)>=sizeof(dstfile)) {
1218  debuga(__FILE__,__LINE__,_("Buffer too small to store "));
1219  debuga_more("%s/%s",images,direntp->d_name);
1220  exit(EXIT_FAILURE);
1221  }
1222  img_in = fopen(srcfile, "rb");
1223  if (img_in!=NULL) {
1224  img_ou = fopen(dstfile, "wb");
1225  if (img_ou!=NULL) {
1226  while ((nread = fread(buffer,1,sizeof(buffer),img_in))>0) {
1227  if (fwrite(buffer,1,nread,img_ou)!=nread) {
1228  debuga(__FILE__,__LINE__,_("Failed to copy image \"%s\" to \"%s\"\n"),srcfile,dstfile);
1229  break;
1230  }
1231  }
1232  if (fclose(img_ou)==EOF) {
1233  debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),dstfile,strerror(errno));
1234  exit(EXIT_FAILURE);
1235  }
1236  } else
1237  debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"), dstfile, strerror(errno));
1238  if (fclose(img_in)==EOF) {
1239  debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),srcfile,strerror(errno));
1240  exit(EXIT_FAILURE);
1241  }
1242  } else
1243  debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"), srcfile, strerror(errno));
1244  }
1245  }
1246  (void) closedir(dirp);
1247 
1248  return;
1249 }
1250 
1257 bool IsTreeFileDirName(const char *Name)
1258 {
1259  char DateFormat;
1260  int i;
1261 
1262  // start year (date format u) or start day (date format e)
1263  if (!isdigit(Name[0]) || !isdigit(Name[1])) return(false);
1264 
1265  if (isdigit(Name[2]) && isdigit(Name[3]))
1266  {
1267  // date format is either u or w
1268  if (Name[4]=='.')
1269  {
1270  // date format is w
1271  if (!isdigit(Name[5]) || !isdigit(Name[6])) return(false);
1272  return(true);//date format w is confirmed
1273  }
1274 
1275  // date format is u
1276  Name+=4;
1277 
1278  // start month
1279  if (!isalpha(Name[0]) || !isalpha(Name[1]) || !isalpha(Name[2])) return(false);
1280  for (i=11 ; i>=0 && memcmp(mtab1[i],Name,3) ; i--);
1281  if (i<0) return(false);
1282  Name+=3;
1283 
1284  // start day
1285  if (!isdigit(Name[0]) || !isdigit(Name[1])) return(false);
1286  Name+=2;
1287 
1288  DateFormat='u';
1289  }
1290  else if (isalpha(Name[2]) && isalpha(Name[3]) && isalpha(Name[4]))
1291  {
1292  // date format is e
1293  Name+=2;
1294 
1295  // start month
1296  if (!isalpha(Name[0]) || !isalpha(Name[1]) || !isalpha(Name[2])) return(false);
1297  for (i=11 ; i>=0 && memcmp(mtab1[i],Name,3) ; i--);
1298  if (i<0) return(false);
1299  Name+=3;
1300 
1301  // start day
1302  if (!isdigit(Name[0]) || !isdigit(Name[1]) || !isdigit(Name[2]) || !isdigit(Name[3])) return(false);
1303  Name+=4;
1304 
1305  DateFormat='e';
1306  }
1307  else
1308  return(false);
1309 
1310  if (Name[0]!='-') return(false);
1311  Name++;
1312 
1313  if (DateFormat=='u')
1314  {
1315  if (!isdigit(Name[0]) || !isdigit(Name[1]) || !isdigit(Name[2]) || !isdigit(Name[3])) return(false);
1316  Name+=4;
1317 
1318  if (!isalpha(Name[0]) || !isalpha(Name[1]) || !isalpha(Name[2])) return(false);
1319  for (i=11 ; i>=0 && memcmp(mtab1[i],Name,3) ; i--);
1320  if (i<0) return(false);
1321  Name+=3;
1322 
1323  if (!isdigit(Name[0]) || !isdigit(Name[1])) return(false);
1324  Name+=2;
1325  }
1326  else //DateFormat=='e'
1327  {
1328  if (!isdigit(Name[0]) || !isdigit(Name[1])) return(false);
1329  Name+=2;
1330 
1331  if (!isalpha(Name[0]) || !isalpha(Name[1]) || !isalpha(Name[2])) return(false);
1332  for (i=11 ; i>=0 && memcmp(mtab1[i],Name,3) ; i--);
1333  if (i<0) return(false);
1334  Name+=3;
1335 
1336  if (!isdigit(Name[0]) || !isdigit(Name[1]) || !isdigit(Name[2]) || !isdigit(Name[3])) return(false);
1337  Name+=4;
1338  }
1339  /*
1340  * The directory name may contains additional characters such as a counter if
1341  * a previous report is never overwritten.
1342  */
1343  return(true);
1344 }
1345 
1350 bool IsTreeYearFileName(const char *Name)
1351 {
1352  if (!isdigit(Name[0]) || !isdigit(Name[1]) || !isdigit(Name[2]) || !isdigit(Name[3])) return(false);
1353  Name+=4;
1354  if (Name[0]=='-')
1355  {
1356  Name++;
1357  if (!isdigit(Name[0]) || !isdigit(Name[1]) || !isdigit(Name[2]) || !isdigit(Name[3])) return(false);
1358  Name+=4;
1359  }
1360  if (Name[0]) return(false);
1361  return(true);
1362 }
1363 
1368 bool IsTreeMonthFileName(const char *Name)
1369 {
1370  int m;
1371 
1372  if (!isdigit(Name[0]) || !isdigit(Name[1])) return(false);
1373  m=(Name[0]-'0')*10+(Name[1]-'0');
1374  if (m<1 || m>12) return(false);
1375  Name+=2;
1376  if (Name[0]=='-')
1377  {
1378  Name++;
1379  if (!isdigit(Name[0]) || !isdigit(Name[1])) return(false);
1380  m=(Name[0]-'0')*10+(Name[1]-'0');
1381  if (m<1 || m>12) return(false);
1382  Name+=2;
1383  }
1384  if (Name[0]) return(false);
1385  return(true);
1386 }
1387 
1392 bool IsTreeDayFileName(const char *Name)
1393 {
1394  int d;
1395 
1396  if (!isdigit(Name[0]) || !isdigit(Name[1])) return(false);
1397  d=(Name[0]-'0')*10+(Name[1]-'0');
1398  if (d<1 || d>31) return(false);
1399  if (Name[2]=='-')
1400  {
1401  Name+=3;
1402  if (!isdigit(Name[0]) || !isdigit(Name[1])) return(false);
1403  d=(Name[0]-'0')*10+(Name[1]-'0');
1404  if (d<1 || d>31) return(false);
1405  }
1406  /*
1407  * The directory name may contains additional characters such as a counter if
1408  * a previous report is never overwritten.
1409  */
1410  return(true);
1411 }
1412 
1427 int vrfydir(const struct periodstruct *per1, const char *addr, const char *site, const char *us)
1428 {
1429  FILE *fp_ou;
1430  char wdir[MAXLEN];
1431  int y1, y2;
1432  int m1, m2;
1433  int d1, d2;
1434  int wlen, wlen2;
1435  time_t curtime;
1436  struct tm *loctm;
1437 
1438  strcpy(wdir,outdir);
1439  wlen=strlen(wdir);
1440  y1=per1->start.tm_year+1900;
1441  y2=per1->end.tm_year+1900;
1442  m1=per1->start.tm_mon+1;
1443  m2=per1->end.tm_mon+1;
1444  d1=per1->start.tm_mday;
1445  d2=per1->end.tm_mday;
1446  if (IndexTree == INDEX_TREE_DATE) {
1447  wlen+=sprintf(wdir+wlen,"%04d",y1);
1448  if (y1!=y2) wlen+=sprintf(wdir+wlen,"-%04d",y2);
1449  if (access(wdir, R_OK) != 0)
1450  my_mkdir(wdir);
1451 
1452  wlen+=sprintf(wdir+wlen,"/%02d",m1);
1453  if (m1 != m2) wlen+=sprintf(wdir+wlen,"-%02d",m2);
1454  if (access(wdir, R_OK) != 0)
1455  my_mkdir(wdir);
1456 
1457  wlen+=sprintf(wdir+wlen,"/%02d",d1);
1458  if (d1!=d2) wlen+=sprintf(wdir+wlen,"-%02d",d2);
1459  } else {
1460  if (df == 'u') {
1461  wlen=snprintf(wdir+wlen,sizeof(wdir)-wlen,"%04d%s%02d-%04d%s%02d",y1,
1462  conv_month_name(m1),d1,y2,conv_month_name(m2),d2);
1463  } else if (df == 'e') {
1464  wlen=snprintf(wdir+wlen,sizeof(wdir)-wlen,"%02d%s%04d-%02d%s%04d",d1,
1465  conv_month_name(m1),y1,d2,conv_month_name(m2),y2);
1466  } else if (df == 'w') {
1467  wlen2=strftime(wdir+wlen, sizeof(wdir)-wlen, "%Y.%U", &per1->start);
1468  if (wlen2==0) return(-1);
1469  wlen+=wlen2;
1470  }
1471  }
1472 
1473  if (us[0] != '\0') {
1474  struct userinfostruct *uinfo=userinfo_find_from_id(us);
1475  if (uinfo) {
1476  strcat(wdir,"-");
1477  strcat(wdir,uinfo->filename);
1478  }
1479  }
1480  if (addr[0] != '\0') {
1481  strcat(wdir,"-");
1482  strcat(wdir,addr);
1483  }
1484  if (site[0] != '\0') {
1485  strcat(wdir,"-");
1486  strcat(wdir,site);
1487  }
1488 
1489  strcpy(outdirname,wdir);
1490 
1491  // manufacture a new unique name if configured to keep old reports or overwrite old report if configured to do so
1492  if (!OverwriteReport) {
1493  int num=1;
1494 
1495  while (access(wdir,R_OK)==0 || errno==EACCES) //file exist or can't be read
1496  {
1497  format_path(__FILE__, __LINE__, wdir, sizeof(wdir), "%s.%d", outdirname, num);
1498  num++;
1499  }
1500  if (num>1) {
1501  if (debug)
1502  debuga(__FILE__,__LINE__,_("File \"%s\" already exists, moved to \"%s\"\n"),outdirname,wdir);
1503  rename(outdirname,wdir);
1504  }
1505  } else {
1506  if (access(outdirname,R_OK) == 0) {
1507  unlinkdir(outdirname,1);
1508  }
1509  }
1511 
1512  // create sarg-date to keep track of the report creation date
1513  if (snprintf(wdir,sizeof(wdir),"%s/sarg-date",outdirname)>=sizeof(wdir)) {
1514  debuga(__FILE__,__LINE__,_("Buffer too small to store "));
1515  debuga_more("%s/sarg-date",outdirname);
1516  exit(EXIT_FAILURE);
1517  }
1518  if ((fp_ou = fopen(wdir, "wt")) == 0) {
1519  debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),wdir,strerror(errno));
1520  perror("SARG:");
1521  exit(EXIT_FAILURE);
1522  }
1523  time(&curtime);
1524  //strftime(wdir,sizeof(wdir),"%a %b %d %H:%M:%S %Z %Y",localtime(&curtime));
1525  loctm=localtime(&curtime);
1526  strftime(wdir,sizeof(wdir),"%Y-%m-%d %H:%M:%S",loctm);
1527  if (fprintf(fp_ou,"%s %d\n",wdir,loctm->tm_isdst)<0) {
1528  debuga(__FILE__,__LINE__,_("Failed to write the date in \"%s\"\n"),wdir);
1529  perror("SARG:");
1530  exit(EXIT_FAILURE);
1531  }
1532  if (fclose(fp_ou)==EOF) {
1533  debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),wdir,strerror(errno));
1534  exit(EXIT_FAILURE);
1535  }
1536 
1537  copy_images();
1538  return(0);
1539 }
1540 
1550 void safe_strcpy(char *dest,const char *src,int length)
1551 {
1552  if (length<=0) {
1553  debuga(__FILE__,__LINE__,_("Invalid buffer length passed to the function to safely copy a string\n"));
1554  exit(EXIT_FAILURE);
1555  }
1556  strncpy(dest,src,length-1);
1557  dest[length-1]='\0';
1558 }
1559 
1560 void strip_latin(char *line)
1561 {
1562  int i,j;
1563  int skip;
1564 
1565  j=0;
1566  skip=0;
1567  for (i=0;line[i];i++){
1568  if (skip){
1569  if (line[i]==';') skip=0;
1570  } else {
1571  if (line[i]=='&')
1572  skip=1;
1573  else
1574  line[j++]=line[i];
1575  }
1576  }
1577  line[j]='\0';
1578  return;
1579 }
1580 
1581 void zdate(char *ftime,int ftimesize, char DateFormat)
1582 {
1583  time_t t;
1584  struct tm *local;
1585 
1586  t = time(NULL);
1587  local = localtime(&t);
1588  if (DateFormat=='u')
1589  strftime(ftime, ftimesize, "%b/%d/%Y %H:%M", local);
1590  else if (DateFormat=='e')
1591  strftime(ftime, ftimesize, "%d/%b/%Y-%H:%M", local);
1592  else if (DateFormat=='w')
1593  strftime(ftime, ftimesize, "%W-%H-%M", local);
1594  return;
1595 }
1596 
1597 
1598 char *fixtime(long long int elap)
1599 {
1600  long int num = elap / 1000LL;
1601  int hor = 0;
1602  int min = 0;
1603  int sec = 0;
1604  static char buf[20];
1605 
1606  hor=num / 3600L;
1607  min=(num % 3600L) / 60L;
1608  sec=num % 60L;
1609 
1610  if (hor==0 && min==0 && sec==0)
1611  strcpy(buf,"0");
1612  else
1613  snprintf(buf,sizeof(buf),"%d:%02d:%02d",hor,min,sec);
1614 
1615  return buf;
1616 }
1617 
1618 
1620 {
1621  int d0=0;
1622  int m0=0;
1623  int y0=0;
1624  int d1=0;
1625  int m1=0;
1626  int y1=0;
1627 
1628  if (isdigit(ReadFilter->DateRange[0])) {
1629  int next=-1;
1630 
1631  if (sscanf(ReadFilter->DateRange,"%d/%d/%d%n",&d0,&m0,&y0,&next)!=3 || y0<100 || m0<1 || m0>12 || d0<1 || d0>31 || next<0) {
1632  debuga(__FILE__,__LINE__,_("The date passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n"));
1633  exit(EXIT_FAILURE);
1634  }
1635  if (ReadFilter->DateRange[next]=='-') {
1636  if (sscanf(ReadFilter->DateRange+next+1,"%d/%d/%d",&d1,&m1,&y1)!=3 || y1<100 || m1<1 || m1>12 || d1<1 || d1>31) {
1637  debuga(__FILE__,__LINE__,_("The date range passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n"));
1638  exit(EXIT_FAILURE);
1639  }
1640  } else if (ReadFilter->DateRange[next]!='\0') {
1641  debuga(__FILE__,__LINE__,_("The date range passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n"));
1642  exit(EXIT_FAILURE);
1643  } else {
1644  d1=d0;
1645  m1=m0;
1646  y1=y0;
1647  }
1648  } else {
1649  int i;
1650  time_t Today,t1;
1651  struct tm *Date0,Date1;
1652 
1653  if (time(&Today)==(time_t)-1) {
1654  debuga(__FILE__,__LINE__,_("Failed to get the current time\n"));
1655  exit(EXIT_FAILURE);
1656  }
1657  if (sscanf(ReadFilter->DateRange,"day-%d",&i)==1) {
1658  if (i<0) {
1659  debuga(__FILE__,__LINE__,_("Invalid number of days in -d parameter\n"));
1660  exit(EXIT_FAILURE);
1661  }
1662  Today-=i*24*60*60;
1663  Date0=localtime(&Today);
1664  if (Date0==NULL) {
1665  debuga(__FILE__,__LINE__,_("Cannot convert local time: %s\n"),strerror(errno));
1666  exit(EXIT_FAILURE);
1667  }
1668  y0=y1=Date0->tm_year+1900;
1669  m0=m1=Date0->tm_mon+1;
1670  d0=d1=Date0->tm_mday;
1671  } else if (sscanf(ReadFilter->DateRange,"week-%d",&i)==1) {
1672  /*
1673  There is no portable way to find the first day of the week even though the
1674  information is available in the locale. nl_langinfo has the unofficial
1675  parameters _NL_TIME_FIRST_WEEKDAY and _NL_TIME_WEEK_1STDAY but they are
1676  undocumented as is their return value and it is discouraged to use them.
1677  Beside, nl_langinfo isn't available on windows and the first day of the
1678  week isn't available at all on that system.
1679  */
1680  const int FirstWeekDay=1;
1681  time_t WeekBegin;
1682 
1683  if (i<0) {
1684  debuga(__FILE__,__LINE__,_("Invalid number of weeks in -d parameter\n"));
1685  exit(EXIT_FAILURE);
1686  }
1687  Date0=localtime(&Today);
1688  if (Date0==NULL) {
1689  debuga(__FILE__,__LINE__,_("Cannot convert local time: %s\n"),strerror(errno));
1690  exit(EXIT_FAILURE);
1691  }
1692  WeekBegin=Today-((Date0->tm_wday-FirstWeekDay+7)%7)*24*60*60;
1693  WeekBegin-=i*7*24*60*60;
1694  Date0=localtime(&WeekBegin);
1695  if (Date0==NULL) {
1696  debuga(__FILE__,__LINE__,_("Cannot convert local time: %s\n"),strerror(errno));
1697  exit(EXIT_FAILURE);
1698  }
1699  y0=Date0->tm_year+1900;
1700  m0=Date0->tm_mon+1;
1701  d0=Date0->tm_mday;
1702  WeekBegin+=6*24*60*60;
1703  Date0=localtime(&WeekBegin);
1704  if (Date0==NULL) {
1705  debuga(__FILE__,__LINE__,_("Cannot convert local time: %s\n"),strerror(errno));
1706  exit(EXIT_FAILURE);
1707  }
1708  y1=Date0->tm_year+1900;
1709  m1=Date0->tm_mon+1;
1710  d1=Date0->tm_mday;
1711  } else if (sscanf(ReadFilter->DateRange,"month-%d",&i)==1) {
1712  if (i<0) {
1713  debuga(__FILE__,__LINE__,_("Invalid number of months in -d parameter\n"));
1714  exit(EXIT_FAILURE);
1715  }
1716  Date0=localtime(&Today);
1717  if (Date0==NULL) {
1718  debuga(__FILE__,__LINE__,_("Cannot convert local time: %s\n"),strerror(errno));
1719  exit(EXIT_FAILURE);
1720  }
1721  if (Date0->tm_mon<i%12) {
1722  y0=Date0->tm_year+1900-i/12-1;
1723  m0=(Date0->tm_mon+12-i%12)%12+1;
1724  d0=1;
1725  } else {
1726  y0=Date0->tm_year+1900-i/12;
1727  m0=Date0->tm_mon-i%12+1;
1728  d0=1;
1729  }
1730  memcpy(&Date1,Date0,sizeof(struct tm));
1731  Date1.tm_isdst=-1;
1732  Date1.tm_mday=1;
1733  if (m0<12) {
1734  Date1.tm_mon=m0;
1735  Date1.tm_year=y0-1900;
1736  } else {
1737  Date1.tm_mon=0;
1738  Date1.tm_year=y0-1900+1;
1739  }
1740  t1=mktime(&Date1);
1741  t1-=24*60*60;
1742  Date0=localtime(&t1);
1743  y1=Date0->tm_year+1900;
1744  m1=Date0->tm_mon+1;
1745  d1=Date0->tm_mday;
1746  } else {
1747  debuga(__FILE__,__LINE__,_("Invalid date range passed on command line\n"));
1748  exit(EXIT_FAILURE);
1749  }
1750  }
1751 
1752  ReadFilter->StartDate=y0*10000+m0*100+d0;
1753  ReadFilter->EndDate=y1*10000+m1*100+d1;
1754  snprintf(ReadFilter->DateRange,sizeof(ReadFilter->DateRange),"%02d/%02d/%04d-%02d/%02d/%04d",d0,m0,y0,d1,m1,y1);
1755  return;
1756 }
1757 
1758 
1759 char *strlow(char *string)
1760 {
1761  char *s;
1762 
1763  if (string)
1764  {
1765  for (s = string; *s; ++s)
1766  *s = tolower(*s);
1767  }
1768 
1769  return string;
1770 }
1771 
1772 
1773 
1774 
1775 char *strup(char *string)
1776 {
1777  char *s;
1778 
1779  if (string)
1780  {
1781  for (s = string; *s; ++s)
1782  *s = toupper(*s);
1783  }
1784 
1785  return string;
1786 }
1787 
1788 
1789 void removetmp(const char *outdir)
1790 {
1791  FILE *fp_gen;
1792  char filename[256];
1793 
1794  if (!RemoveTempFiles)
1795  return;
1796 
1797  if (debug) {
1798  debuga(__FILE__,__LINE__,_("Purging temporary file sarg-general\n"));
1799  }
1800  if (snprintf(filename,sizeof(filename),"%s/sarg-general",outdir)>=sizeof(filename)) {
1801  debuga(__FILE__,__LINE__,_("Path too long: "));
1802  debuga_more("%s/sarg-period\n",outdir);
1803  exit(EXIT_FAILURE);
1804  }
1805  if ((fp_gen=fopen(filename,"w"))==NULL){
1806  debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),filename,strerror(errno));
1807  exit(EXIT_FAILURE);
1808  }
1809  totalger(fp_gen,filename);
1810  if (fclose(fp_gen)==EOF) {
1811  debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),filename,strerror(errno));
1812  exit(EXIT_FAILURE);
1813  }
1814 }
1815 
1817 {
1818  FILE *fp_in;
1819  char data[80];
1820  int i;
1821  int Stored;
1822  long int MemSize;
1823 
1824  if (ExcludeCodes[0] == '\0')
1825  return;
1826 
1827  if ((fp_in=fopen(ExcludeCodes,"r"))==NULL) {
1828  debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),ExcludeCodes,strerror(errno));
1829  exit(EXIT_FAILURE);
1830  }
1831 
1832  if (fseek(fp_in, 0, SEEK_END)==-1) {
1833  debuga(__FILE__,__LINE__,_("Failed to move till the end of file \"%s\": %s\n"),ExcludeCodes,strerror(errno));
1834  exit(EXIT_FAILURE);
1835  }
1836  MemSize = ftell(fp_in);
1837  if (MemSize<0) {
1838  debuga(__FILE__,__LINE__,_("Cannot get the size of file \"%s\"\n"),ExcludeCodes);
1839  exit(EXIT_FAILURE);
1840  }
1841  if (fseek(fp_in, 0, SEEK_SET)==-1) {
1842  debuga(__FILE__,__LINE__,_("Failed to rewind file \"%s\": %s\n"),ExcludeCodes,strerror(errno));
1843  exit(EXIT_FAILURE);
1844  }
1845 
1846  MemSize+=1;
1847  if ((excludecode=(char *) malloc(MemSize))==NULL) {
1848  debuga(__FILE__,__LINE__,_("malloc error (%ld bytes required)\n"),MemSize);
1849  exit(EXIT_FAILURE);
1850  }
1851  memset(excludecode,0,MemSize);
1852 
1853  Stored=0;
1854  while(fgets(data,sizeof(data),fp_in)!=NULL) {
1855  if (data[0]=='#') continue;
1856  for (i=strlen(data)-1 ; i>=0 && (unsigned char)data[i]<=' ' ; i--) data[i]='\0';
1857  if (i<0) continue;
1858  if (Stored+i+2>=MemSize) {
1859  debuga(__FILE__,__LINE__,_("Too many codes to exclude in file \"%s\"\n"),ExcludeCodes);
1860  break;
1861  }
1862  strcat(excludecode,data);
1863  strcat(excludecode,";");
1864  Stored+=i+1;
1865  }
1866 
1867  if (fclose(fp_in)==EOF) {
1868  debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),ExcludeCodes,strerror(errno));
1869  exit(EXIT_FAILURE);
1870  }
1871  return;
1872 }
1873 
1875 {
1876  if (excludecode) {
1877  free(excludecode);
1878  excludecode=NULL;
1879  }
1880 }
1881 
1882 int vercode(const char *code)
1883 {
1884  char *cod;
1885  int clen;
1886 
1887  if (excludecode && excludecode[0]!='\0') {
1888  clen=strlen(code);
1889  cod=excludecode;
1890  while (cod) {
1891  if (strncmp(code,cod,clen)==0 && cod[clen]==';')
1892  return 1;
1893  cod=strchr(cod,';');
1894  if (cod) cod++;
1895  }
1896  }
1897  return 0;
1898 }
1899 
1900 void fixnone(char *str)
1901 {
1902  int i;
1903 
1904  for (i=strlen(str)-1 ; i>=0 && (unsigned char)str[i]<=' ' ; i--);
1905  if (i==3 && strncmp(str,"none",4) == 0)
1906  str[0]='\0';
1907 
1908  return;
1909 }
1910 
1911 void fixendofline(char *str)
1912 {
1913  int i;
1914 
1915  for (i=strlen(str)-1 ; i>=0 && (unsigned char)str[i]<=' ' ; i--) str[i]=0;
1916 }
1917 
1918 #ifdef LEGACY_TESTVALIDUSERCHAR
1919 int testvaliduserchar(const char *user)
1920 {
1921  int x=0;
1922  int y=0;
1923 
1924  for (y=0; y<strlen(UserInvalidChar); y++) {
1925  for (x=0; x<strlen(user); x++) {
1926  if (user[x] == UserInvalidChar[y])
1927  return 1;
1928  }
1929  }
1930  return 0;
1931 }
1932 #else
1933 int testvaliduserchar(const char *user)
1934 {
1935  char * p_UserInvalidChar = UserInvalidChar ;
1936  const char * p_user ;
1937 
1938  while( *p_UserInvalidChar ) {
1939  p_user = user ;
1940  while ( *p_user ) {
1941  if ( *p_UserInvalidChar == *p_user )
1942  return 1;
1943  p_user++ ;
1944  }
1945  p_UserInvalidChar++ ;
1946  }
1947  return 0;
1948 }
1949 #endif
1950 
1951 int compar( const void *a, const void *b )
1952 {
1953  if ( *(int *)a > *(int *)b ) return 1;
1954  if ( *(int *)a < *(int *)b ) return -1;
1955  return 0;
1956 }
1957 
1966 static void storenumlist(const char *paramname, int *list, int d0, int d)
1967 {
1968  if (d0<0)
1969  {
1970  list[d]=1;
1971  }
1972  else
1973  {
1974  int i;
1975 
1976  if (d<d0)
1977  {
1978  debuga(__FILE__,__LINE__,_("Ending value %d is less than or equal to starting value %d in parameter \"%s\"\n"),d,d0,paramname);
1979  exit(EXIT_FAILURE);
1980  }
1981  for (i=d0 ; i<=d ; i++) list[i]=1;
1982  }
1983 }
1984 
1998 void getnumlist(const char *paramname, const char *buffer, int *list, int maxvalue)
1999 {
2000  int i, d, d0;
2001  int digitcount;
2002  int nvalues=0;
2003 
2004  // skip parameter name
2005  while (*buffer && *buffer!=' ' && *buffer!='\t') buffer++;
2006  if (!*buffer)
2007  {
2008  debuga(__FILE__,__LINE__,_("Missing values for parameter \"%s\"\n"),paramname);
2009  exit(EXIT_FAILURE);
2010  }
2011 
2012  // clear list
2013  for (i=0 ; i<maxvalue ; i++) list[i]=0;
2014 
2015  // get values
2016  d=0;
2017  d0=-1;
2018  digitcount=0;
2019  for ( ; *buffer ; buffer++)
2020  {
2021  if (isdigit(*buffer))
2022  {
2023  d=d*10+(*buffer-'0');
2024  if (d>=maxvalue)
2025  {
2026  debuga(__FILE__,__LINE__,_("Value too big found in parameter \"%s\" (max value is %d)\n"),paramname,maxvalue-1);
2027  exit(EXIT_FAILURE);
2028  }
2029  digitcount++;
2030  }
2031  else if (*buffer=='-')
2032  {
2033  if (!digitcount)
2034  {
2035  debuga(__FILE__,__LINE__,_("Missing start value before \"-\" in parameter \"%s\"\n"),paramname);
2036  exit(EXIT_FAILURE);
2037  }
2038  d0=d;
2039  d=0;
2040  digitcount=0;
2041  }
2042  else if (*buffer==',')
2043  {
2044  if (!digitcount)
2045  {
2046  debuga(__FILE__,__LINE__,_("Missing value before \",\" in parameter \"%s\"\n"),paramname);
2047  exit(EXIT_FAILURE);
2048  }
2049  storenumlist(paramname,list,d0,d);
2050  nvalues++;
2051  d0=-1;
2052  d=0;
2053  digitcount=0;
2054  }
2055  else if (*buffer=='\r' || *buffer=='\n')
2056  {
2057  break;
2058  }
2059  else if (*buffer!=' ' && *buffer!='\t')
2060  {
2061  debuga(__FILE__,__LINE__,_("Invalid character \"%c\" found in parameter \"%s\"\n"),*buffer,paramname);
2062  exit(EXIT_FAILURE);
2063  }
2064  }
2065  if (digitcount>0)
2066  {
2067  storenumlist(paramname,list,d0,d);
2068  nvalues++;
2069  }
2070  else if (d0>=0)
2071  {
2072  debuga(__FILE__,__LINE__,_("Missing ending value in range for parameter \"%s\"\n"),paramname);
2073  exit(EXIT_FAILURE);
2074  }
2075  if (!nvalues)
2076  {
2077  debuga(__FILE__,__LINE__,_("Parameter \"%s\" is empty\n"),paramname);
2078  exit(EXIT_FAILURE);
2079  }
2080 }
2081 
2091 bool numlistcontains(const int *list, int maxvalue, int value)
2092 {
2093  if (value<0 || value>=maxvalue) return(false);
2094  return(list[value]!=0);
2095 }
2096 
2097 void show_info(FILE *fp_ou)
2098 {
2099  char ftime[127];
2100 
2101  if (!ShowSargInfo) return;
2102  zdate(ftime, sizeof(ftime), df);
2103  fputs("<div class=\"info\">",fp_ou);
2104  fprintf(fp_ou,_("Generated by <a href=\"%s\">%s-%s</a> on %s"),URL,PGM,VERSION,ftime);
2105  fputs("</div>\n",fp_ou);
2106 }
2107 
2108 void show_sarg(FILE *fp_ou, int depth)
2109 {
2110  int i;
2111 
2112  if (!ShowSargLogo) return;
2113  fputs("<div class=\"logo\"><a href=\"http://sarg.sourceforge.net\"><img src=\"",fp_ou);
2114  for (i=0 ; i<depth ; i++)
2115  fputs("../",fp_ou);
2116  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);
2117 }
2118 
2119 void write_logo_image(FILE *fp_ou)
2120 {
2121  if (LogoImage[0]!='\0')
2122  fprintf(fp_ou, "<div class=\"logo\"><img src=\"%s\" width=\"%s\" height=\"%s\" alt=\"Logo\">&nbsp;%s</div>\n",LogoImage,Width,Height,LogoText);
2123 }
2124 
2125 void write_html_head(FILE *fp_ou, int depth, const char *page_title,int javascript)
2126 {
2127  int i;
2128 
2129  fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n<html>\n",fp_ou);
2130  fprintf(fp_ou, "<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n",CharSet);
2131  if (page_title) fprintf(fp_ou,"<title>%s</title>\n",page_title);
2132  css(fp_ou);
2133  if ((javascript & HTML_JS_SORTTABLE)!=0 && SortTableJs[0]) {
2134  fputs("<script type=\"text/javascript\" src=\"",fp_ou);
2135  if (strncmp(SortTableJs,"../",3)==0) {
2136  for (i=0 ; i<depth ; i++) fputs("../",fp_ou);
2137  }
2138  fputs(SortTableJs,fp_ou);
2139  fputs("\"></script>\n",fp_ou);
2140  }
2141  fputs("</head>\n<body>\n",fp_ou);
2142 }
2143 
2144 void write_html_header(FILE *fp_ou, int depth, const char *page_title,int javascript)
2145 {
2146  write_html_head(fp_ou,depth,page_title,javascript);
2147  write_logo_image(fp_ou);
2148  show_sarg(fp_ou, depth);
2149  fprintf(fp_ou,"<div class=\"title\"><table cellpadding=\"0\" cellspacing=\"0\">\n<tr><th class=\"title_c\">%s</th></tr>\n",Title);
2150 }
2151 
2152 void close_html_header(FILE *fp_ou)
2153 {
2154  fputs("</table></div>\n",fp_ou);
2155 }
2156 
2157 void write_html_trailer(FILE *fp_ou)
2158 {
2159  show_info(fp_ou);
2160  fputs("</body>\n</html>\n",fp_ou);
2161 }
2162 
2163 void output_html_string(FILE *fp_ou,const char *str,int maxlen)
2164 {
2165  int i=0;
2166 
2167  while (*str && (maxlen<=0 || i<maxlen)) {
2168  switch (*str) {
2169  case '&':
2170  fputs("&amp;",fp_ou);
2171  break;
2172  case '<':
2173  fputs("&lt;",fp_ou);
2174  break;
2175  case '>':
2176  fputs("&gt;",fp_ou);
2177  break;
2178  case '"':
2179  fputs("&quot;",fp_ou);
2180  break;
2181  case '\'':
2182  fputs("&#39;",fp_ou);
2183  break;
2184  default:
2185  fputc(*str,fp_ou);
2186  }
2187  str++;
2188  i++;
2189  }
2190  if (maxlen>0 && i>=maxlen)
2191  fputs("&hellip;",fp_ou);
2192 }
2193 
2194 void output_html_url(FILE *fp_ou,const char *url)
2195 {
2196  while (*url) {
2197  if (*url=='&')
2198  fputs("&amp;",fp_ou);
2199  else
2200  fputc(*url,fp_ou);
2201  url++;
2202  }
2203 }
2204 
2214 void output_html_link(FILE *fp_ou,const char *url,int maxlen)
2215 {
2216  if (url[0]==ALIAS_PREFIX) {
2217  // this is an alias, no need for a A tag
2218  output_html_string(fp_ou,url+1,100);
2219  } else {
2220  if (skip_scheme(url)==url)
2221  fputs("<a href=\"http://",fp_ou);//no scheme in the url, assume http:// to make the link clickable
2222  else
2223  fputs("<a href=\"",fp_ou);//the scheme is in the url, no need to add one
2224  output_html_url(fp_ou,url);
2225  fputs("\">",fp_ou);
2226  output_html_string(fp_ou,url,100);
2227  fputs("</a>",fp_ou);
2228  }
2229 }
2230 
2231 void url_module(const char *url, char *w2)
2232 {
2233  int x, y;
2234  char w[255];
2235 
2236  y=0;
2237  for (x=strlen(url)-1; x>=0; x--) {
2238  if (url[x] == '/' || y>=sizeof(w)-1) break;
2239  w[y++]=url[x];
2240  }
2241  if (x<0) {
2242  w2[0]='\0';
2243  return;
2244  }
2245 
2246  x=0;
2247  for (y=y-1; y>=0; y--) {
2248  w2[x++]=w[y];
2249  }
2250  w2[x]='\0';
2251 }
2252 
2261 void url_to_anchor(const char *url,char *anchor,int size)
2262 {
2263  int i,j;
2264  bool skip;
2265 
2266  // find url end
2267  for (i=0 ; url[i] && url[i]!='/' && url[i]!='?' ; i++);
2268  i--;
2269  if (i<=0) {
2270  anchor[0]='\0';
2271  return;
2272  }
2273 
2274  // only keep really safe characters
2275  skip=false;
2276  j=size-1;
2277  anchor[j]='\0';
2278  while (j>0 && i>=0)
2279  {
2280  if (isalnum(url[i]) || url[i]=='-' || url[i]=='_' || url[i]=='.') {
2281  anchor[--j]=url[i];
2282  skip=false;
2283  } else {
2284  if (!skip) anchor[--j]='_';
2285  skip=true;
2286  }
2287  i--;
2288  }
2289  if (j>0)
2290  {
2291  while ( anchor[j])
2292  {
2293  *anchor=anchor[j];
2294  anchor++;
2295  }
2296  *anchor='\0';
2297  }
2298 }
2299 
2300 void version(void)
2301 {
2302  printf(_("SARG Version: %s\n"),VERSION);
2303 #if defined(ENABLE_NLS) && defined(HAVE_LOCALE_H)
2304  if (debug) {
2305  printf(_("\nFor the translation to work, a valid message file should be copied to "
2306  "\"%s/<Locale>/LC_MESSAGES/%s.mo\" where <Locale> is derived from the effective locale.\n"),LOCALEDIR,PACKAGE_NAME);
2307  if (CurrentLocale) {
2308  printf(_("Currently effective locale is \"%s\".\n"),CurrentLocale);
2309  } else {
2310  printf(_("Locale is not set in the environment variable.\n"));
2311  }
2312  // TRANSLATORS: You may change this message to tell the reader that the language is correctly supported.
2313  printf(_("If this message is in English, then your language is not supported or not correctly installed.\n"));
2314  }
2315 #endif
2316  if (debug) {
2317 #ifdef HAVE_GLOB_H
2318  printf(_("File globbing compiled in.\n"));
2319 #else
2320  printf(_("File globbing NOT compiled in.\n"));
2321 #endif
2322  }
2323  exit(EXIT_SUCCESS);
2324 }
2325 
2326 char *get_param_value(const char *param,char *line)
2327 {
2328  int plen;
2329 
2330  while (*line==' ' || *line=='\t') line++;
2331  plen=strlen(param);
2332  if (strncasecmp(line,param,plen)) return(NULL);
2333  if (line[plen]!=' ' && line[plen]!='\t') return(NULL);
2334  line+=plen;
2335  while (*line==' ' || *line=='\t') line++;
2336  return(line);
2337 }
2338 
2339 void unlinkdir(const char *dir,bool contentonly)
2340 {
2341  struct stat st;
2342  DIR *dirp;
2343  struct dirent *direntp;
2344  char dname[MAXLEN];
2345  int err;
2346 
2347  dirp=opendir(dir);
2348  if (!dirp) return;
2349  while ((direntp = readdir(dirp)) != NULL) {
2350  if (direntp->d_name[0] == '.' && (direntp->d_name[1] == '\0' ||
2351  (direntp->d_name[1] == '.' && direntp->d_name[2] == '\0')))
2352  continue;
2353  if (snprintf(dname,sizeof(dname),"%s/%s",dir,direntp->d_name)>=sizeof(dname)) {
2354  debuga(__FILE__,__LINE__,_("Path too long: "));
2355  debuga_more("%s/%s\n",dir,direntp->d_name);
2356  exit(EXIT_FAILURE);
2357  }
2358 #ifdef HAVE_LSTAT
2359  err=lstat(dname,&st);
2360 #else
2361  err=stat(dname,&st);
2362 #endif
2363  if (err) {
2364  debuga(__FILE__,__LINE__,_("Cannot stat \"%s\": %s\n"),dname,strerror(errno));
2365  exit(EXIT_FAILURE);
2366  }
2367  if (S_ISREG(st.st_mode)) {
2368  if (unlink(dname)) {
2369  debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),dname,strerror(errno));
2370  exit(EXIT_FAILURE);
2371  }
2372  } else if (S_ISDIR(st.st_mode)) {
2373  unlinkdir(dname,0);
2374  } else {
2375  debuga(__FILE__,__LINE__,_("Don't know how to delete \"%s\" (not a regular file nor a directory)\n"),dname);
2376  }
2377  }
2378  closedir(dirp);
2379 
2380  if (!contentonly) {
2381  if (rmdir(dir)) {
2382  debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),dir,strerror(errno));
2383  exit(EXIT_FAILURE);
2384  }
2385  }
2386 }
2387 
2401 void emptytmpdir(const char *dir)
2402 {
2403  struct stat st;
2404  DIR *dirp;
2405  struct dirent *direntp;
2406  int dlen;
2407  int elen;
2408  char dname[MAXLEN];
2409  int err;
2410  int i;
2411  static const char *TmpExt[]=
2412  {
2413  ".int_unsort",
2414  ".int_log",
2415  ".day",
2416  "htmlrel.txt",
2417  ".user_unsort",
2418  ".user_log",
2419  ".utmp",
2420  ".ip",
2421  "lastlog1",
2422  "lastlog",
2423  "emailrep"
2424  };
2425 
2426  dirp=opendir(dir);
2427  if (!dirp) return;
2428 
2429  // make sure the temporary directory contains only our files
2430  while ((direntp = readdir(dirp)) != NULL) {
2431  if (direntp->d_name[0] == '.' && (direntp->d_name[1] == '\0' ||
2432  (direntp->d_name[1] == '.' && direntp->d_name[2] == '\0')))
2433  continue;
2434 
2435  // is it one of our files
2436  dlen=strlen(direntp->d_name);
2437  for (i=sizeof(TmpExt)/sizeof(TmpExt[0])-1 ; i>=0 ; i--) {
2438  elen=strlen(TmpExt[i]);
2439  if (dlen>=elen && strcasecmp(direntp->d_name+dlen-elen,TmpExt[i])==0) break;
2440  }
2441  if (i<0) {
2442  debuga(__FILE__,__LINE__,_("Unknown file \"%s\" found in temporary directory \"%s\". It is not one of our files. "
2443  "Please check the temporary directory you gave to sarg. Adjust the path to a safe "
2444  "directory or manually delete the content of \"%s\"\n"),direntp->d_name,dir,dir);
2445  exit(EXIT_FAILURE);
2446  }
2447 
2448  if (snprintf(dname,sizeof(dname),"%s/%s",dir,direntp->d_name)>=sizeof(dname)) {
2449  debuga(__FILE__,__LINE__,_("Path too long: "));
2450  debuga_more("%s/%s\n",dir,direntp->d_name);
2451  exit(EXIT_FAILURE);
2452  }
2453 
2454 #ifdef HAVE_LSTAT
2455  err=lstat(dname,&st);
2456 #else
2457  err=stat(dname,&st);
2458 #endif
2459  if (err) {
2460  debuga(__FILE__,__LINE__,_("Cannot stat \"%s\": %s\n"),dname,strerror(errno));
2461  exit(EXIT_FAILURE);
2462  }
2463  if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) {
2464  debuga(__FILE__,__LINE__,_("Unknown path type for \"%s\". Check temporary directory\n"),dname);
2465  exit(EXIT_FAILURE);
2466  }
2467  }
2468  rewinddir(dirp);
2469 
2470  // now delete our files
2471  while ((direntp = readdir(dirp)) != NULL) {
2472  if (direntp->d_name[0] == '.' && (direntp->d_name[1] == '\0' ||
2473  (direntp->d_name[1] == '.' && direntp->d_name[2] == '\0')))
2474  continue;
2475 
2476  // is it one of our files
2477  dlen=strlen(direntp->d_name);
2478  for (i=sizeof(TmpExt)/sizeof(TmpExt[0])-1 ; i>=0 ; i--) {
2479  elen=strlen(TmpExt[i]);
2480  if (dlen>=elen && strcasecmp(direntp->d_name+dlen-elen,TmpExt[i])==0) break;
2481  }
2482  if (i<0) {
2483  debuga(__FILE__,__LINE__,_("Unknown file \"%s\" found in temporary directory \"%s\". It is not one of our files. "
2484  "Please check the temporary directory you gave to sarg. Adjust the path to a safe "
2485  "directory or manually delete the content of \"%s\"\n"),direntp->d_name,dir,dir);
2486  exit(EXIT_FAILURE);
2487  }
2488 
2489  if (snprintf(dname,sizeof(dname),"%s/%s",dir,direntp->d_name)>=sizeof(dname)) {
2490  debuga(__FILE__,__LINE__,_("Path too long: "));
2491  debuga_more("%s/%s\n",dir,direntp->d_name);
2492  exit(EXIT_FAILURE);
2493  }
2494 #ifdef HAVE_LSTAT
2495  err=lstat(dname,&st);
2496 #else
2497  err=stat(dname,&st);
2498 #endif
2499  if (err) {
2500  debuga(__FILE__,__LINE__,_("Cannot stat \"%s\": %s\n"),dname,strerror(errno));
2501  exit(EXIT_FAILURE);
2502  }
2503  if (S_ISDIR(st.st_mode)) {
2504  unlinkdir(dname,0);
2505  } else if (S_ISREG(st.st_mode)) {
2506  if (unlink(dname)) {
2507  debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),dname,strerror(errno));
2508  exit(EXIT_FAILURE);
2509  }
2510  } else {
2511  debuga(__FILE__,__LINE__,_("Don't know how to delete \"%s\" (not a regular file)\n"),dname);
2512  }
2513  }
2514  closedir(dirp);
2515 }
2516 
2534 int extract_address_mask(const char *buf,const char **text,unsigned char *ipv4,unsigned short int *ipv6,int *nbits,const char **next)
2535 {
2536  int i;
2537  int j;
2538  int ip_size;
2539  unsigned int value4, value6;
2540  unsigned short int addr[8];
2541  int addr_len;
2542  int nibble6_len;
2543  int mask, max_mask;
2544  int pad_pos;
2545  int pad_len;
2546  bool bracket=false;
2547  bool port=false;
2548  int port_num=0;
2549 
2550  // skip leading spaces and tabs
2551  while (*buf && (*buf==' ' || *buf=='\t')) buf++;
2552 
2553  // find out the nature of the pattern
2554  ip_size=0x60 | 0x04;
2555  if (*buf=='[') {
2556  bracket=true;
2557  ip_size=0x60;
2558  buf++;
2559  }
2560  value4=0U;
2561  value6=0U;
2562  addr_len=0;
2563  nibble6_len=0;
2564  pad_pos=-1;
2565  for (i=0 ; (unsigned char)buf[i]>' ' && buf[i]!='/' && buf[i]!='?' && (!bracket || buf[i]!=']') && ip_size ; i++) {
2566  if (ip_size & 0x04) {
2567  if (isdigit(buf[i])) {
2568  if (port) {
2569  port_num=port_num*10+(buf[i]-'0');
2570  if (port_num>65535) ip_size&=~0x04;
2571  } else {
2572  value4=value4*10+(buf[i]-'0');
2573  if (value4>0xFFU) ip_size&=~0x04;
2574  }
2575  } else if (buf[i]=='.' && addr_len<4) {
2576  addr[addr_len++]=(unsigned short)(value4 & 0xFFU);
2577  value4=0U;
2578  } else if (!port && buf[i]==':') {
2579  port=true;
2580  } else {
2581  ip_size&=~0x04;
2582  }
2583  }
2584  if (ip_size & 0x60) {
2585  if (isdigit(buf[i])) {
2586  value6=(value6<<4)+(buf[i]-'0');
2587  nibble6_len++;
2588  if (value6>0xFFFFU) ip_size&=~0x60;
2589  } else if (toupper(buf[i])>='A' && toupper(buf[i])<='F') {
2590  value6=(value6<<4)+(toupper(buf[i])-'A'+10);
2591  nibble6_len++;
2592  if (value6>0xFFFFU) ip_size&=~0x60;
2593  } else if (buf[i]==':' && addr_len<8) {
2594  if (nibble6_len>0) {
2595  addr[addr_len++]=(unsigned short)(value6 & 0xFFFFU);
2596  nibble6_len=0;
2597  }
2598  value6=0U;
2599  if (buf[i+1]==':') {
2600  pad_pos=addr_len;
2601  i++;
2602  }
2603  } else {
2604  ip_size&=~0x60;
2605  }
2606  }
2607  }
2608  if (i==0) return(0);
2609  if (ip_size & 0x04) {
2610  if (addr_len!=3)
2611  ip_size&=~0x04;
2612  else
2613  addr[addr_len++]=(unsigned short)(value4 & 0xFFU);
2614  }
2615  if (ip_size & 0x60) {
2616  if (pad_pos<0 && addr_len!=7) {
2617  ip_size&=~0x60;
2618  } else if (pad_pos>=0 && addr_len>=7)
2619  ip_size&=~0x60;
2620  else if (nibble6_len>0)
2621  addr[addr_len++]=(unsigned short)(value6 & 0xFFFFU);
2622  }
2623  if (!ip_size) {
2624  if (text) {
2625  *text=buf;
2626  if (bracket) (*text)--;
2627  }
2628  while ((unsigned char)buf[i]>' ') i++;
2629  if (next) *next=buf+i;
2630  return(1);
2631  }
2632  max_mask=(ip_size & 0x04) ? 4*8 : 8*16;
2633  if (buf[i]=='/') {
2634  i++;
2635  mask=atoi(buf+i);
2636  while (isdigit(buf[i])) i++;
2637  if (mask<0 || mask>max_mask) mask=max_mask;
2638  } else
2639  mask=max_mask;
2640  if (ip_size & 0x60 && bracket && buf[i]==']') i++;
2641  if (next) *next=buf+i;
2642  if (ip_size & 0x04) {
2643  if (nbits) *nbits=mask;
2644  for (i=0 ; i<addr_len ; i++)
2645  ipv4[i]=(unsigned char)addr[i];
2646  return(2);
2647  }
2648 
2649  // IPv6 address
2650  if (nbits) *nbits=mask;
2651  i=0;
2652  j=0;
2653  if (pad_pos>=0) {
2654  while (i<pad_pos)
2655  ipv6[j++]=(unsigned short int)addr[i++];
2656  pad_len=8-addr_len;
2657  while (j<pad_pos+pad_len)
2658  ipv6[j++]=0;
2659  }
2660  while (i<addr_len)
2661  ipv6[j++]=(unsigned short int)addr[i++];
2662  return(3);
2663 }
2664 
2665 int format_path(const char *file, int line, char *output_buffer, int buffer_size, const char *format,...)
2666 {
2667  va_list ap;
2668  int output_length;
2669 
2670  va_start(ap, format);
2671  output_length = vsnprintf(output_buffer, buffer_size, format, ap);
2672  if (output_length >= buffer_size) {
2673  debuga(file, line, _("Path too long: "));
2674  vfprintf(stderr, format, ap);
2675  exit(EXIT_FAILURE);
2676  }
2677  va_end(ap);
2678  return output_length;
2679 }
2680 
2681 void append_to_path(char *base_path, int base_path_size, const char *append)
2682 {
2683  int length = strlen(base_path);
2684  int append_length;
2685 
2686  if (append[0] == '/') append++;
2687  if (length > 0 && base_path[length-1] != '/') {
2688  if (length+1 >= base_path_size) {
2689  debuga(__FILE__, __LINE__, _("Path too long: "));
2690  fprintf(stderr, "%s/%s", base_path, append);
2691  exit(EXIT_FAILURE);
2692  }
2693  base_path[length++] = '/';
2694  }
2695  append_length = strlen(append);
2696  if (length+append_length >= base_path_size) {
2697  debuga(__FILE__, __LINE__, _("Path too long: "));
2698  base_path[length] = '\0';
2699  fprintf(stderr, "%s%s", base_path, append);
2700  exit(EXIT_FAILURE);
2701  }
2702  strcpy(base_path + length, append);
2703 }
getword_atoi
int getword_atoi(int *number, struct getwordstruct *gwarea, char stop)
Definition: util.c:227
ReadFilter
struct ReadLogDataStruct ReadFilter
The log file filtering.
Definition: log.c:37
compar
int compar(const void *a, const void *b)
Definition: util.c:1951
LogoImage
char LogoImage[20000]
Definition: conf.h:345
totalger
void totalger(FILE *fp_gen, const char *filename)
Definition: report.c:563
ImageDir
char ImageDir[20000]
Directory where the images are stored.
Definition: util.c:50
getnumlist
void getnumlist(const char *paramname, const char *buffer, int *list, int maxvalue)
Definition: util.c:1998
RemoveTempFiles
bool RemoveTempFiles
Definition: conf.h:321
HTML_JS_SORTTABLE
#define HTML_JS_SORTTABLE
Bit to include sorttable.js in the html plage.
Definition: conf.h:287
IsTreeDayFileName
bool IsTreeDayFileName(const char *Name)
Definition: util.c:1392
css
void css(FILE *fp_css)
Definition: css.c:82
write_logo_image
void write_logo_image(FILE *fp_ou)
Definition: util.c:2119
site
char site[20000]
Definition: conf.h:433
fixnum
char * fixnum(long long int value, int n)
Definition: util.c:670
userinfostruct
What is known about a user.
Definition: defs.h:78
UserInvalidChar
char UserInvalidChar[255]
Definition: conf.h:369
outdir
char outdir[20000]
Definition: conf.h:310
addr
char addr[20000]
Definition: conf.h:439
code
char code[20000]
Definition: conf.h:313
longline_read
char * longline_read(FileObject *fp_in, longline line)
Definition: longline.c:97
FileObject_GetLastCloseError
const char * FileObject_GetLastCloseError(void)
Definition: fileobject.c:263
PortableMkDir
int PortableMkDir(const char *path, int mode)
Definition: util.c:403
format_path
int format_path(const char *file, int line, char *output_buffer, int buffer_size, const char *format,...)
Definition: util.c:2665
obtuser
int obtuser(const char *dirname, const char *name)
Definition: util.c:901
longlinestruct
Definition: longline.c:56
arqtt
static char arqtt[4096]
The name of the file containing the access time of the site/user.
Definition: report.c:41
url_module
void url_module(const char *url, char *w2)
Definition: util.c:2231
debuga_more
void debuga_more(const char *msg,...)
Definition: util.c:631
periodstruct
Definition: conf.h:298
unlinkdir
void unlinkdir(const char *dir, bool contentonly)
Definition: util.c:2339
buildymd
void buildymd(const char *dia, const char *mes, const char *ano, char *wdata, int wdata_size)
Definition: util.c:566
_
#define _(String)
Definition: conf.h:155
getword_ptr
int getword_ptr(char *orig_line, char **word, struct getwordstruct *gwarea, char stop)
Definition: util.c:343
getword_atoll
int getword_atoll(long long int *number, struct getwordstruct *gwarea, char stop)
Definition: util.c:182
fixendofline
void fixendofline(char *str)
Definition: util.c:1911
MAXLEN
#define MAXLEN
Definition: conf.h:176
compare_date
int compare_date(const struct tm *date1, const struct tm *date2)
Definition: util.c:549
URL
#define URL
Definition: info.h:3
INDEX_TREE_FILE
#define INDEX_TREE_FILE
Definition: conf.h:241
getword_limit
int getword_limit(char *word, int limit, struct getwordstruct *gwarea, char stop)
Definition: util.c:119
Width
char Width[20000]
Definition: conf.h:348
INDEX_TREE_DATE
#define INDEX_TREE_DATE
Definition: conf.h:240
MAX_USER_LEN
#define MAX_USER_LEN
Definition: conf.h:179
periodstruct::start
struct tm start
The first date of the period.
Definition: conf.h:301
fixnum2
char * fixnum2(long long int value, int n)
Definition: util.c:767
month2num
int month2num(const char *month)
Definition: util.c:526
name
char name[20000]
Definition: conf.h:335
testvaliduserchar
int testvaliduserchar(const char *user)
Definition: util.c:1933
output_html_url
void output_html_url(FILE *fp_ou, const char *url)
Definition: util.c:2194
DISPLAY_ABBREV
#define DISPLAY_ABBREV
Definition: conf.h:256
getwordstruct::modified
int modified
Definition: defs.h:30
userinfo_find_from_id
struct userinfostruct * userinfo_find_from_id(const char *id)
Definition: userinfo.c:218
DisplayedValues
unsigned long int DisplayedValues
Definition: conf.h:408
strip_latin
void strip_latin(char *line)
Definition: util.c:1560
conv_month
int conv_month(const char *month)
Definition: util.c:575
DateFormat
char DateFormat
Definition: conf.h:364
skip_scheme
const char * skip_scheme(const char *url)
Definition: url.c:839
getword_restart
void getword_restart(struct getwordstruct *gwarea)
Definition: util.c:81
show_info
void show_info(FILE *fp_ou)
Definition: util.c:2097
getword_atolu
int getword_atolu(unsigned long int *number, struct getwordstruct *gwarea, char stop)
Definition: util.c:303
get_param_value
char * get_param_value(const char *param, char *line)
Definition: util.c:2326
url_to_anchor
void url_to_anchor(const char *url, char *anchor, int size)
Definition: util.c:2261
PGM
#define PGM
Definition: info.h:2
version
void version(void)
Definition: util.c:2300
ReadLogDataStruct::EndDate
int EndDate
Last date to include in the report. The format is year*10000+month+100+day.
Definition: defs.h:138
LogLevel_Source
@ LogLevel_Source
Display the source file name and line number along with the message.
Definition: defs.h:19
computedate
void computedate(int year, int month, int day, struct tm *t)
Definition: util.c:892
getperiod_fromrange
void getperiod_fromrange(struct periodstruct *period, const struct ReadLogDataStruct *ReadFilter)
Definition: util.c:1088
SortTableJs
char SortTableJs[256]
The full path to sorttable.js if the table in the reports must be dynamicaly sorted.
Definition: conf.h:457
IndexTree
unsigned long int IndexTree
How to display the index of the reports.
Definition: conf.h:416
write_html_trailer
void write_html_trailer(FILE *fp_ou)
Definition: util.c:2157
extract_address_mask
int extract_address_mask(const char *buf, const char **text, unsigned char *ipv4, unsigned short int *ipv6, int *nbits, const char **next)
Definition: util.c:2534
getword_start
void getword_start(struct getwordstruct *gwarea, const char *line)
Definition: util.c:74
mask
char mask[20000]
Definition: conf.h:432
periodstruct::html
char html[90]
The HTML representation of the date.
Definition: conf.h:307
debuga
void debuga(const char *File, int Line, const char *msg,...)
Definition: util.c:601
safe_strcpy
void safe_strcpy(char *dest, const char *src, int length)
Definition: util.c:1550
main
int main(int argc, char *argv[])
Definition: log.c:54
getperiod_fromsarglog
int getperiod_fromsarglog(const char *arqtt, struct periodstruct *period)
Definition: util.c:1009
IsTreeFileDirName
bool IsTreeFileDirName(const char *Name)
Definition: util.c:1257
conv_month_name
const char * conv_month_name(int month)
Definition: util.c:584
free_excludecodes
void free_excludecodes(void)
Definition: util.c:1874
IsTreeYearFileName
bool IsTreeYearFileName(const char *Name)
Definition: util.c:1350
FileObject_Open
FileObject * FileObject_Open(const char *FileName)
Definition: fileobject.c:104
output_html_link
void output_html_link(FILE *fp_ou, const char *url, int maxlen)
Definition: util.c:2214
conf.h
Include headers and define global variables. */.
MAXLEN_FIXNUM
#define MAXLEN_FIXNUM
obttotal
void obttotal(const char *dirname, const char *name, int nuser, long long int *tbytes, long long int *media)
Definition: util.c:938
append_to_path
void append_to_path(char *base_path, int base_path_size, const char *append)
Definition: util.c:2681
emptytmpdir
void emptytmpdir(const char *dir)
Definition: util.c:2401
builddia
int builddia(int day, int month, int year)
Definition: util.c:534
write_html_head
void write_html_head(FILE *fp_ou, int depth, const char *page_title, int javascript)
Definition: util.c:2125
getwordstruct::beginning
const char * beginning
Definition: defs.h:29
df
char df
Definition: conf.h:319
ALIAS_PREFIX
#define ALIAS_PREFIX
The character prefixed in front of the host names that are aliased.
Definition: conf.h:290
strlow
char * strlow(char *string)
Definition: util.c:1759
is_absolute
int is_absolute(const char *path)
Definition: util.c:394
vercode
int vercode(const char *code)
Definition: util.c:1882
numlistcontains
bool numlistcontains(const int *list, int maxvalue, int value)
Definition: util.c:2091
strup
char * strup(char *string)
Definition: util.c:1775
formatdate
void formatdate(char *date, int date_size, int year, int month, int day, int hour, int minute, int second, int dst)
Definition: util.c:871
ReadLogDataStruct
Log filtering criterion.
Definition: defs.h:131
fixtime
char * fixtime(long long int elap)
Definition: util.c:1598
longline_create
longline longline_create(void)
Definition: longline.c:70
my_mkdir
bool my_mkdir(const char *name)
Definition: util.c:419
output_html_string
void output_html_string(FILE *fp_ou, const char *str, int maxlen)
Definition: util.c:2163
write_html_header
void write_html_header(FILE *fp_ou, int depth, const char *page_title, int javascript)
Definition: util.c:2144
userinfostruct::filename
const char * filename
The mangled name to use in file names of that user.
Definition: defs.h:91
vrfydir
int vrfydir(const struct periodstruct *per1, const char *addr, const char *site, const char *us)
Definition: util.c:1427
Height
char Height[20000]
Definition: conf.h:349
ExcludeCodes
char ExcludeCodes[256]
Definition: conf.h:330
getperiod_buildtext
int getperiod_buildtext(struct periodstruct *period)
Definition: util.c:1136
mtab1
static char mtab1[12][4]
Definition: util.c:44
date_from
void date_from(struct ReadLogDataStruct *ReadFilter)
Definition: util.c:1619
load_excludecodes
void load_excludecodes(const char *ExcludeCodes)
Definition: util.c:1816
excludecode
static char * excludecode
The list of the HTTP codes to exclude from the report.
Definition: util.c:47
getwordstruct
Definition: defs.h:26
ShowSargInfo
bool ShowSargInfo
Definition: conf.h:403
longline_destroy
void longline_destroy(longline *line_ptr)
Definition: longline.c:168
storenumlist
static void storenumlist(const char *paramname, int *list, int d0, int d)
Definition: util.c:1966
getwordstruct::current
const char * current
Definition: defs.h:28
getword_multisep
int getword_multisep(char *word, int limit, struct getwordstruct *gwarea, char stop)
Definition: util.c:134
ShowSargLogo
bool ShowSargLogo
Definition: conf.h:405
MAXLEN_FIXNUM2
#define MAXLEN_FIXNUM2
periodstruct::text
char text[90]
The textual representation of the date.
Definition: conf.h:305
zdate
void zdate(char *ftime, int ftimesize, char DateFormat)
Definition: util.c:1581
removetmp
void removetmp(const char *outdir)
Definition: util.c:1789
us
char us[50]
Definition: conf.h:434
obtdate
int obtdate(const char *dirname, const char *name, char *data)
Definition: util.c:835
tmp
char tmp[20000]
Definition: conf.h:315
getperiod_torange
void getperiod_torange(const struct periodstruct *period, int *dfrom, int *duntil)
Definition: util.c:1111
debugaz
void debugaz(const char *File, int Line, const char *msg,...)
Definition: util.c:646
defs.h
Declaration of the structures and functions.
CharSet
char CharSet[255]
Definition: conf.h:368
buildtime
char * buildtime(long long int elap)
Definition: util.c:807
LogoText
char LogoText[20000]
Definition: conf.h:346
outdirname
char outdirname[20000]
Definition: conf.h:311
fixnone
void fixnone(char *str)
Definition: util.c:1900
my_lltoa
void my_lltoa(unsigned long long int n, char *s, int ssize, int len)
Definition: util.c:493
ReadLogDataStruct::DateRange
char DateRange[255]
The filtering date range.
Definition: defs.h:134
debugz
int debugz
Definition: conf.h:490
period
struct periodstruct period
Definition: conf.h:312
getword_skip
int getword_skip(int limit, struct getwordstruct *gwarea, char stop)
Definition: util.c:160
show_sarg
void show_sarg(FILE *fp_ou, int depth)
Definition: util.c:2108
Title
char Title[20000]
Definition: conf.h:339
VERSION
#define VERSION
Definition: info.h:1
getword_atol
int getword_atol(long int *number, struct getwordstruct *gwarea, char stop)
Definition: util.c:265
close_html_header
void close_html_header(FILE *fp_ou)
Definition: util.c:2152
ReadLogDataStruct::StartDate
int StartDate
First date to include in the report. The format is year*10000+month+100+day.
Definition: defs.h:136
periodstruct::end
struct tm end
The last date of the period.
Definition: conf.h:303
FileObject_Close
int FileObject_Close(FileObject *File)
Definition: fileobject.c:206
OverwriteReport
bool OverwriteReport
Definition: conf.h:324
debug
int debug
Definition: conf.h:489
FileObjectStruct
Definition: fileobject.h:4
IsTreeMonthFileName
bool IsTreeMonthFileName(const char *Name)
Definition: util.c:1368
MAXLLL
#define MAXLLL
Maximum number of digits in long long (a guess).
Definition: util.c:371
CurrentLocale
char * CurrentLocale
Selected locale set through the environment variable.
Definition: log.c:45
makeTmpDir
void makeTmpDir(const char *tmp)
Definition: util.c:475
getword
int getword(char *word, int limit, struct getwordstruct *gwarea, char stop)
Definition: util.c:90
UseComma
bool UseComma
Definition: conf.h:326
getperiod_merge
void getperiod_merge(struct periodstruct *main, struct periodstruct *candidate)
Definition: util.c:1122
copy_images
static void copy_images(void)
Definition: util.c:1176