X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fsarg.git;a=blobdiff_plain;f=util.c;h=aba23b191b769db4af96cb708361bda67c3d6bdb;hp=84c85dba921ffefd6090a9c09e439d9b08167b1d;hb=HEAD;hpb=1bf79dab6b8e76c4e2de820687017e8377cfa0a8 diff --git a/util.c b/util.c index 84c85db..aba23b1 100644 --- a/util.c +++ b/util.c @@ -1,6 +1,6 @@ /* * SARG Squid Analysis Report Generator http://sarg.sourceforge.net - * 1998, 2010 + * 1998, 2015 * * SARG donations: * please look at http://sarg.sourceforge.net/donations.php @@ -30,6 +30,11 @@ #include "include/conf.h" #include "include/defs.h" +#if defined(__MINGW32__) && defined(HAVE_DIRECT_H) +#define NO_OLDNAMES 1 +#include +#endif + #if defined(HAVE_BACKTRACE) #define USE_GETWORD_BACKTRACE 1 #else @@ -41,1252 +46,1686 @@ static char mtab1[12][4]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep", //! The list of the HTTP codes to exclude from the report. static char *excludecode=NULL; -/*void fgetword(char *word, char *line, int stop) -{ - //VARIANT N1 - int x; - - for (x=0; line[x] && (line[x] != stop); x++) word[x] = line[x]; - word[x] = '\0'; - - //VARIANT N2 - char *tchar; - int difflen; +//! Directory where the images are stored. +char ImageDir[MAXLEN]=IMAGEDIR; - tchar = strchr(line, stop); - if (tchar == NULL) strcpy(word, line); - else - { - difflen = tchar - line; - strncpy(word, line, difflen); - word[difflen] = '\0'; - } -}*/ +extern char *CurrentLocale; #if USE_GETWORD_BACKTRACE static void getword_backtrace(void) { - void *buffer[5]; - int i, n; - char **calls; - - n=backtrace(buffer,sizeof(buffer)/sizeof(buffer[0])); - if (n<=0) return; - calls=backtrace_symbols(buffer,n); - if (calls) { - debuga(_("getword backtrace:\n")); - for (i=0 ; ibeginning=line; - gwarea->current=line; - gwarea->modified=0; + gwarea->beginning=line; + gwarea->current=line; + gwarea->modified=0; } void getword_restart(struct getwordstruct *gwarea) { - if (gwarea->modified) { - debuga(_("Cannot parse again the line as it was modified\n")); - exit(EXIT_FAILURE); - } - gwarea->current=gwarea->beginning; + if (gwarea->modified) { + debuga(__FILE__,__LINE__,_("Cannot parse again the line as it was modified\n")); + exit(EXIT_FAILURE); + } + gwarea->current=gwarea->beginning; } int getword(char *word, int limit, struct getwordstruct *gwarea, char stop) { - int x; - - for(x=0;((gwarea->current[x]) && (gwarea->current[x] != stop ));x++) { - if(x>=limit) { - printf("SARG: getword loop detected after %d bytes.\n",x); - printf("SARG: Line=\"%s\"\n",gwarea->beginning); - printf("SARG: Record=\"%s\"\n",gwarea->current); - printf("SARG: searching for \'x%x\'\n",stop); - //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n"); - word[(limit>0) ? limit-1 : 0]='\0'; + int x; + + for(x=0;((gwarea->current[x]) && (gwarea->current[x] != stop ));x++) { + if(x>=limit) { + /* + TRANSLATORS: The %s is the name of the function reporting the + error message. + */ + debuga(__FILE__,__LINE__,_("End of word not found in %s after %d bytes.\n"),__func__,x); + debuga(__FILE__,__LINE__,_("Line=\"%s\"\n"),gwarea->beginning); + debuga(__FILE__,__LINE__,_("Record=\"%s\"\n"),gwarea->current); + debuga(__FILE__,__LINE__,_("searching for \'x%x\'\n"),stop); + word[(limit>0) ? limit-1 : 0]='\0'; #if USE_GETWORD_BACKTRACE - getword_backtrace(); + getword_backtrace(); #endif - return(-1); - } - word[x] = gwarea->current[x]; - } + return(-1); + } + word[x] = gwarea->current[x]; + } - word[x] = '\0'; - if (gwarea->current[x]) ++x; - gwarea->current+=x; - return(0); + word[x] = '\0'; + if (gwarea->current[x]) ++x; + gwarea->current+=x; + return(0); } int getword_limit(char *word, int limit, struct getwordstruct *gwarea, char stop) { - int x; + int x; - limit--; - for(x=0; xcurrent[x] && gwarea->current[x] != stop ;x++) { - word[x] = gwarea->current[x]; - } - word[x] = '\0'; - gwarea->current+=x; - while (*gwarea->current && *gwarea->current != stop) gwarea->current++; - if (*gwarea->current) ++gwarea->current; - return(0); + limit--; + for(x=0; xcurrent[x] && gwarea->current[x] != stop ;x++) { + word[x] = gwarea->current[x]; + } + word[x] = '\0'; + gwarea->current+=x; + while (*gwarea->current && *gwarea->current != stop) gwarea->current++; + if (*gwarea->current) ++gwarea->current; + return(0); } int getword_multisep(char *word, int limit, struct getwordstruct *gwarea, char stop) { - int x; + int x; - for(x=0;((gwarea->current[x]) && (gwarea->current[x] != stop ));x++) { - if(x>=limit) { - printf("SARG: getword_multisep loop detected.\n"); - printf("SARG: Line=\"%s\"\n",gwarea->beginning); - printf("SARG: Record=\"%s\"\n",gwarea->current); - printf("SARG: searching for \'x%x\'\n",stop); - //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n"); - if (limit>0) word[limit-1]='\0'; + for(x=0;((gwarea->current[x]) && (gwarea->current[x] != stop ));x++) { + if(x>=limit) { + debuga(__FILE__,__LINE__,_("End of word not found in %s after %d bytes.\n"),__func__,x); + debuga(__FILE__,__LINE__,_("Line=\"%s\"\n"),gwarea->beginning); + debuga(__FILE__,__LINE__,_("Record=\"%s\"\n"),gwarea->current); + debuga(__FILE__,__LINE__,_("searching for \'x%x\'\n"),stop); + if (limit>0) word[limit-1]='\0'; #if USE_GETWORD_BACKTRACE - getword_backtrace(); + getword_backtrace(); #endif - //exit(EXIT_FAILURE); - return(-1); - } - word[x] = gwarea->current[x]; - } + //exit(EXIT_FAILURE); + return(-1); + } + word[x] = gwarea->current[x]; + } - word[x] = '\0'; - while (gwarea->current[x] && gwarea->current[x]==stop) ++x; - gwarea->current+=x; - return(0); + word[x] = '\0'; + while (gwarea->current[x] && gwarea->current[x]==stop) ++x; + gwarea->current+=x; + return(0); } int getword_skip(int limit, struct getwordstruct *gwarea, char stop) { - int x; + int x; - for(x=0;(gwarea->current[x] && (gwarea->current[x] != stop ));x++) { - if(x>=limit) { - printf("SARG: getword_skip loop detected after %d bytes.\n",x); - printf("SARG: Line=\"%s\"\n",gwarea->beginning); - printf("SARG: Record=\"%s\"\n",gwarea->current); - printf("SARG: searching for \'x%x\'\n",stop); - //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n"); + for(x=0;(gwarea->current[x] && (gwarea->current[x] != stop ));x++) { + if(x>=limit) { + debuga(__FILE__,__LINE__,_("End of word not found in %s after %d bytes.\n"),__func__,x); + debuga(__FILE__,__LINE__,_("Line=\"%s\"\n"),gwarea->beginning); + debuga(__FILE__,__LINE__,_("Record=\"%s\"\n"),gwarea->current); + debuga(__FILE__,__LINE__,_("searching for \'x%x\'\n"),stop); #if USE_GETWORD_BACKTRACE - getword_backtrace(); + getword_backtrace(); #endif - return(-1); - } - } + return(-1); + } + } - if (gwarea->current[x]) ++x; - gwarea->current+=x; - return(0); + if (gwarea->current[x]) ++x; + gwarea->current+=x; + return(0); } int getword_atoll(long long int *number, struct getwordstruct *gwarea, char stop) { - int x; - int sign=+1; - - if (gwarea->current[0] == '-') { - gwarea->current++; - sign=-1; - } else if (gwarea->current[0] == '+') { - gwarea->current++; - } - *number=0LL; - for(x=0;isdigit(gwarea->current[x]);x++) { - *number=(*number * 10) + gwarea->current[x]-'0'; - } - if(gwarea->current[x] && gwarea->current[x]!=stop) { - printf("SARG: getword_atoll loop detected after %d bytes.\n",x); - printf("SARG: Line=\"%s\"\n",gwarea->beginning); - printf("SARG: Record=\"%s\"\n",gwarea->current); - printf("SARG: searching for \'x%x\'\n",stop); - //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n"); + int x; + int sign=+1; + int digit; + + if (gwarea->current[0] == '-') { + gwarea->current++; + sign=-1; + } else if (gwarea->current[0] == '+') { + gwarea->current++; + } + *number=0LL; + for(x=0;isdigit(gwarea->current[x]);x++) { + digit=gwarea->current[x]-'0'; + if (*number >= (LLONG_MAX-digit)/10) { + /* + TRANSLATORS: The first %s is the function name (in the source code) where the + overflow is detected. + */ + debuga(__FILE__,__LINE__,_("Integer overflow detected in %s in line %s\n"),__func__,gwarea->beginning); + return(-1); + } + *number=(*number * 10) + digit; + } + if(gwarea->current[x] && gwarea->current[x]!=stop) { + /* + TRANSLATORS: The %s is the function name, in the source code, where the problem occured. + */ + debuga(__FILE__,__LINE__,_("End of number not found in %s after %d bytes.\n"),__func__,x); + debuga(__FILE__,__LINE__,_("Line=\"%s\"\n"),gwarea->beginning); + debuga(__FILE__,__LINE__,_("Record=\"%s\"\n"),gwarea->current); + debuga(__FILE__,__LINE__,_("searching for \'x%x\'\n"),stop); #if USE_GETWORD_BACKTRACE - getword_backtrace(); + getword_backtrace(); #endif - return(-1); - } - *number*=sign; + return(-1); + } + *number*=sign; + + if (gwarea->current[x]) ++x; + gwarea->current+=x; + return(0); +} + +int getword_atoi(int *number, struct getwordstruct *gwarea, char stop) +{ + int x; + int sign=+1; + int digit; + + if (gwarea->current[0] == '-') { + gwarea->current++; + sign=-1; + } else if (gwarea->current[0] == '+') { + gwarea->current++; + } + *number=0; + for(x=0;isdigit(gwarea->current[x]);x++) { + digit=gwarea->current[x]-'0'; + if (*number > (INT_MAX-digit)/10) { + debuga(__FILE__,__LINE__,_("Integer overflow detected in %s in line %s\n"),__func__,gwarea->beginning); + return(-1); + } + *number=(*number * 10) + digit; + } + if(gwarea->current[x] && gwarea->current[x]!=stop) { + debuga(__FILE__,__LINE__,_("End of number not found in %s after %d bytes.\n"),__func__,x); + debuga(__FILE__,__LINE__,_("Line=\"%s\"\n"),gwarea->beginning); + debuga(__FILE__,__LINE__,_("Record=\"%s\"\n"),gwarea->current); + debuga(__FILE__,__LINE__,_("searching for \'x%x\'\n"),stop); +#if USE_GETWORD_BACKTRACE + getword_backtrace(); +#endif + return(-1); + } + *number*=sign; + + if (gwarea->current[x]) ++x; + gwarea->current+=x; + return(0); +} + +int getword_atol(long int *number, struct getwordstruct *gwarea, char stop) +{ + int x; + long int sign=+1; + int digit; + + if (gwarea->current[0] == '-') { + gwarea->current++; + sign=-1; + } else if (gwarea->current[0] == '+') { + gwarea->current++; + } + *number=0; + for(x=0;isdigit(gwarea->current[x]);x++) { + digit=gwarea->current[x]-'0'; + if (*number > (LONG_MAX-digit)/10) { + debuga(__FILE__,__LINE__,_("Integer overflow detected in %s in line %s\n"),__func__,gwarea->beginning); + return(-1); + } + *number=(*number * 10) + digit; + } + if(gwarea->current[x] && gwarea->current[x]!=stop) { + debuga(__FILE__,__LINE__,_("End of number not found in %s after %d bytes.\n"),__func__,x); + debuga(__FILE__,__LINE__,_("Line=\"%s\"\n"),gwarea->beginning); + debuga(__FILE__,__LINE__,_("Record=\"%s\"\n"),gwarea->current); + debuga(__FILE__,__LINE__,_("searching for \'x%x\'\n"),stop); +#if USE_GETWORD_BACKTRACE + getword_backtrace(); +#endif + return(-1); + } + *number*=sign; + + if (gwarea->current[x]) ++x; + gwarea->current+=x; + return(0); +} + +int getword_atolu(unsigned long int *number, struct getwordstruct *gwarea, char stop) +{ + int x; + int digit; + + if (gwarea->current[0] == '-') { + debuga(__FILE__,__LINE__,_("getword_atolu got a negative number.\n")); + debuga(__FILE__,__LINE__,_("Line=\"%s\"\n"),gwarea->beginning); + debuga(__FILE__,__LINE__,_("Record=\"%s\"\n"),gwarea->current); + return(-1); + } + if (gwarea->current[0] == '+') { + gwarea->current++; + } + *number=0; + for(x=0;isdigit(gwarea->current[x]);x++) { + digit=gwarea->current[x]-'0'; + if (*number > (ULONG_MAX-digit)/10) { + debuga(__FILE__,__LINE__,_("Integer overflow detected in %s in line %s\n"),__func__,gwarea->beginning); + return(-1); + } + *number=(*number * 10) + digit; + } + if(gwarea->current[x] && gwarea->current[x]!=stop) { + debuga(__FILE__,__LINE__,_("End of number not found in %s after %d bytes.\n"),__func__,x); + debuga(__FILE__,__LINE__,_("Line=\"%s\"\n"),gwarea->beginning); + debuga(__FILE__,__LINE__,_("Record=\"%s\"\n"),gwarea->current); + debuga(__FILE__,__LINE__,_("searching for \'x%x\'\n"),stop); +#if USE_GETWORD_BACKTRACE + getword_backtrace(); +#endif + return(-1); + } - if (gwarea->current[x]) ++x; - gwarea->current+=x; - return(0); + if (gwarea->current[x]) ++x; + gwarea->current+=x; + return(0); } int getword_ptr(char *orig_line,char **word, struct getwordstruct *gwarea, char stop) { - /*! - \note Why pass the original buffer to the function ? Because we must modify it to - insert the terminating ASCII zero for the word we return and that's not compatible - with getword_restart(). Moreover, getword_start() sometime works on constant strings - so this function require the original buffer to detect any missuse. - */ - int x; - int sep; - int start; - - if (orig_line && orig_line!=gwarea->beginning) { - debuga(_("Invalid buffer passed to getword_ptr\n")); - return(-1); - } - - start=(gwarea->current-gwarea->beginning); - if (word && orig_line) *word=orig_line+start; - for(x=0;((gwarea->current[x]) && (gwarea->current[x] != stop ));x++); - sep=(gwarea->current[x]!='\0'); - if (word && orig_line) orig_line[start+x] = '\0'; - if (sep) ++x; - gwarea->current+=x; - gwarea->modified=1; - return(0); + /*! + \note Why pass the original buffer to the function ? Because we must modify it to + insert the terminating ASCII zero for the word we return and that's not compatible + with getword_restart(). Moreover, getword_start() sometime works on constant strings + so this function require the original buffer to detect any missuse. + */ + int x; + int sep; + int start; + + if (orig_line && orig_line!=gwarea->beginning) { + debuga(__FILE__,__LINE__,_("Invalid buffer passed to getword_ptr\n")); + return(-1); + } + + start=(gwarea->current-gwarea->beginning); + if (word && orig_line) *word=orig_line+start; + for(x=0;((gwarea->current[x]) && (gwarea->current[x] != stop ));x++); + sep=(gwarea->current[x]!='\0'); + if (word && orig_line) orig_line[start+x] = '\0'; + if (sep) ++x; + gwarea->current+=x; + gwarea->modified=1; + return(0); } #define MAXLLL 30 //!< Maximum number of digits in long long (a guess). long long int my_atoll (const char *nptr) { - long long int returnval=0LL; - int max_digits = MAXLLL ; + long long int returnval=0LL; + int max_digits = MAXLLL ; - // Soak up all the white space - while (isspace( *nptr )) { - nptr++; - } + // Soak up all the white space + while (isspace( *nptr )) { + nptr++; + } - //For each character left to right - //change the character to a single digit - //multiply what we had before by 10 and add the new digit + //For each character left to right + //change the character to a single digit + //multiply what we had before by 10 and add the new digit - while (--max_digits && isdigit( *nptr )) - { - returnval = ( returnval * 10 ) + ( *nptr++ - '0' ) ; - } + while (--max_digits && isdigit( *nptr )) + { + returnval = ( returnval * 10 ) + ( *nptr++ - '0' ) ; + } - return returnval; + return returnval; } int is_absolute(const char *path) { - if (*path=='/') return(1); -#ifdef WINDOWS - if (isalpha(path[0]) && path[1]==':') return(1); + if (*path=='/') return(1); +#ifdef _WIN32 + if (isalpha(path[0]) && path[1]==':') return(1); +#endif + return(0); +} + +int PortableMkDir(const char *path,int mode) +{ +#if defined(__linux__) + int mkerror=mkdir(path,mode); +#else //mingw + (void)mode; + int mkerror=_mkdir(path); #endif - return(0); + return(mkerror); } void my_mkdir(const char *name) { - char w0[MAXLEN]; - int i; - int chars; - - if(!is_absolute(name)) { - debuga(_("Invalid path (%s). Please, use absolute paths only.\n"),name); - debuga(_("process aborted.\n")); - exit(EXIT_FAILURE); - } - - chars=0; - for (i=0 ; name[i] ; i++) { - if (i>=sizeof(w0)) { - debuga(_("directory name too long: %s\n"),name); - exit(EXIT_FAILURE); - } - if (chars>0 && name[i] == '/') { - w0[i] = '\0'; - if(access(w0, R_OK) != 0) { - if(mkdir(w0,0755)) { - debuga(_("mkdir %s %s\n"),w0,strerror(errno)); - debuga(_("process aborted.\n")); - exit(EXIT_FAILURE); - } - } - } - if (name[i] != '/') chars++; - w0[i] = name[i]; - } - - if(access(name, R_OK) != 0) { - if(mkdir(name,0755)) { - debuga(_("mkdir %s %s\n"),name,strerror(errno)); - debuga(_("process aborted.\n")); - exit(EXIT_FAILURE); - } - } + char w0[MAXLEN]; + int i; + int chars; + + if(!is_absolute(name)) { + debuga(__FILE__,__LINE__,_("Invalid path (%s). Please, use absolute paths only.\n"),name); + exit(EXIT_FAILURE); + } + + chars=0; + for (i=0 ; name[i] ; i++) { + if (i>=sizeof(w0)) { + debuga(__FILE__,__LINE__,_("Path too long: ")); + debuga_more("%s\n",name); + exit(EXIT_FAILURE); + } + if (chars>0 && name[i] == '/') { + w0[i] = '\0'; + if (access(w0, R_OK) != 0) { + if (PortableMkDir(w0,0755)) { + debuga(__FILE__,__LINE__,_("Cannot create directory \"%s\": %s\n"),w0,strerror(errno)); + exit(EXIT_FAILURE); + } + } + } + if (name[i] != '/') chars++; + w0[i] = name[i]; + } + + if (access(name, R_OK) != 0) { + if (PortableMkDir(name,0755)) { + debuga(__FILE__,__LINE__,_("Cannot create directory \"%s\": %s\n"),name,strerror(errno)); + exit(EXIT_FAILURE); + } + } } void my_lltoa(unsigned long long int n, char *s, int ssize, int len) { - int i; - int slen = 0; - int j; - char c; - - ssize--; - if (len>ssize) { - debuga(_("The requested number of digits passed to my_lltoa (%d) is bigger than the output buffer size (%d)\n"),len,ssize); - abort(); - } - - do { - s[slen++] = (n % 10) + '0'; - } while ((n /= 10) > 0 && slenslen) { - i=len-slen; - for(j=slen; j>=0; j--) - s[j+i]=s[j]; - for(j=0 ; jssize) { + debuga(__FILE__,__LINE__,_("The requested number of digits passed to my_lltoa (%d) is bigger than the output buffer size (%d)\n"),len,ssize); + abort(); + } + + do { + s[slen++] = (n % 10) + '0'; + } while ((n /= 10) > 0 && slenslen) { + i=len-slen; + for(j=slen; j>=0; j--) + s[j+i]=s[j]; + for(j=0 ; jdate2. +*/ +int compare_date(const struct tm *date1,const struct tm *date2) { - static char str[4]; - - if (month<1 || month>12) { - snprintf(str,sizeof(str),"%03d",month); - return(str); - } - return(mtab1[month-1]); + if (date1->tm_yeartm_year) return(-1); + if (date1->tm_year>date2->tm_year) return(1); + if (date1->tm_montm_mon) return(-1); + if (date1->tm_mon>date2->tm_mon) return(1); + if (date1->tm_mdaytm_mday) return(-1); + if (date1->tm_mday>date2->tm_mday) return(1); + if (date1->tm_hourtm_hour) return(-1); + if (date1->tm_hour>date2->tm_hour) return(1); + if (date1->tm_mintm_min) return(-1); + if (date1->tm_min>date2->tm_min) return(1); + if (date1->tm_sectm_sec) return(-1); + if (date1->tm_sec>date2->tm_sec) return(1); + return(0); } - -void name_month(char *month,int month_len) +void buildymd(const char *dia, const char *mes, const char *ano, char *wdata,int wdata_size) { - int x, z=atoi(month)-1; - char m[255]; - char w[20]; - struct getwordstruct gwarea; - - strcpy(m,_("January,February,March,April,May,June,July,August,September,October,November,December")); - getword_start(&gwarea,m); + int nmes; - for(x=0; x12) { + snprintf(str,sizeof(str),"%03d",month); + return(str); + } + return(mtab1[month-1]); +} + +/*! +Write a debug message to stderr. The message is prefixed by "SARG:" to identify its origin. + +\param msg The printf like message to format. +\param ... The arguments to format in the message. +*/ +void debuga(const char *File,int Line,const char *msg,...) +{ + va_list ap; + + if (debugz>=LogLevel_Source) { + /* The path is removed because every source file is in the same directory. + * There is no point in reporting the full path from the build directory. + */ + const char *ptr=strrchr(File,'/'); + if (!ptr) ptr=File; + /* TRANSLATORS: This is the prefix to stderr messages when the debug level is + set to display the source file (%s) and the line number (%d). */ + fprintf(stderr,_("SARG(%s:%d): "),ptr,Line); + } else { + /* TRANSLATORS: This is the prefix to stderr messages when the debug level + is low. */ + fputs(_("SARG: "),stderr); + } + va_start(ap,msg); + vfprintf(stderr,msg,ap); + va_end(ap); +} + +/*! +Write a debug message to stderr. The message is supposed +to be displayed after a message from debuga(). + +\param msg The printf like message to format. +\param ... The arguments to format in the message. +*/ +void debuga_more(const char *msg,...) +{ + va_list ap; + + va_start(ap,msg); + vfprintf(stderr,msg,ap); + va_end(ap); +} + +/*! +Write a debug message to stderr. The message is prefixed by "SARG: (info)". + +\param msg The printf like message to format. +\param ... The arguments to format in the message. +*/ +void debugaz(const char *File,int Line,const char *msg,...) +{ + va_list ap; + + if (debugz>=LogLevel_Source) { + /* The path is removed because every source file is in the same directory. + * There is no point in reporting the full path from the build directory. + */ + const char *ptr=strrchr(File,'/'); + if (!ptr) ptr=File; + /* TRANSLATORS: This is the prefix to information messages when the debug level is + set to display the source file (%s) and the line number (%d). */ + fprintf(stderr,_("SARG(%s:%d): (info) "),ptr,Line); + } else { + /* TRANSLATORS: This is the prefix to information messages when the debug level + is low. */ + fputs(_("SARG: (info) "),stderr); + } + va_start(ap,msg); + vfprintf(stderr,msg,ap); + va_end(ap); } char *fixnum(long long int value, int n) { #define MAXLEN_FIXNUM 256 - char num[MAXLEN_FIXNUM]=""; - char buf[MAXLEN_FIXNUM * 2]; - char *pbuf; - static char ret[MAXLEN_FIXNUM * 2]; - char *pret; - register int i, j, k; - int numlen; - static char abbrev[30]; - - my_lltoa(value, num, sizeof(num), 0); - - if(DisplayedValues==DISPLAY_ABBREV) { - numlen = strlen(num); - if(numlen <= 3) - sprintf(abbrev,"%s",num); - if(numlen == 4 || numlen == 7 || numlen == 10 || numlen == 13) { - snprintf(abbrev,2,"%s",num); - strncat(abbrev,".",1); - strncat(abbrev,num+1,2); - if(!n) return(abbrev); - if(numlen == 4) - strncat(abbrev,"K",1); - else if(numlen == 7) - strncat(abbrev,"M",1); - else if(numlen == 10) - strncat(abbrev,"G",1); - else if(numlen == 13) - strncat(abbrev,"T",1); - } - if(numlen == 5 || numlen == 8 || numlen == 11 || numlen == 14) { - snprintf(abbrev,3,"%s",num); - strncat(abbrev,".",1); - strncat(abbrev,num+2,2); - if(!n) return(abbrev); - if(numlen == 5) - strncat(abbrev,"K",1); - else if(numlen == 8) - strncat(abbrev,"M",1); - else if(numlen == 11) - strncat(abbrev,"G",1); - else if(numlen == 14) - strncat(abbrev,"T",1); - } - if(numlen == 6 || numlen == 9 || numlen == 12 || numlen == 15) { - snprintf(abbrev,4,"%s",num); - strncat(abbrev,".",1); - strncat(abbrev,num+3,2); - if(!n) return(abbrev); - if(numlen == 6) - strncat(abbrev,"K",1); - else if(numlen == 9) - strncat(abbrev,"M",1); - else if(numlen == 12) - strncat(abbrev,"G",1); - else if(numlen == 15) - strncat(abbrev,"T",1); - } - - return(abbrev); - } - - bzero(buf, MAXLEN_FIXNUM*2); - - pbuf = buf; - pret = ret; - k = 0; - - for ( i = strlen(num) - 1, j = 0 ; i > -1; i--) { - if ( k == 2 && i != 0 ) { - k = 0; - pbuf[j++] = num[i]; - pbuf[j++] = (UseComma) ? ',' : '.'; - continue; - } - pbuf[j] = num[i]; - j++; - k++; - } - - pret[0]='\0'; - - for ( i = strlen(pbuf) - 1, j = 0 ; i > -1; i--, j++) - pret[j] = pbuf[i]; - - pret[j] = '\0'; - - return pret; + char num[MAXLEN_FIXNUM]=""; + char buf[MAXLEN_FIXNUM * 2]; + char *pbuf; + static char ret[MAXLEN_FIXNUM * 2]; + char *pret; + register int i, j, k; + int numlen; + static char abbrev[30]=""; + + my_lltoa(value, num, sizeof(num), 0); + + if(DisplayedValues==DISPLAY_ABBREV) { + numlen = strlen(num); + if(numlen <= 3) + strcpy(abbrev,num); + else if (numlen%3 == 1) { + abbrev[0]=num[0]; + abbrev[1]=(UseComma) ? ',' : '.'; + abbrev[2]=num[1]; + abbrev[3]=num[2]; + abbrev[4]='\0'; + } + else if (numlen%3 == 2) { + abbrev[0]=num[0]; + abbrev[1]=num[1]; + abbrev[2]=(UseComma) ? ',' : '.'; + abbrev[3]=num[2]; + abbrev[4]=num[3]; + abbrev[5]='\0'; + } + else if (numlen%3 == 0) { + abbrev[0]=num[0]; + abbrev[1]=num[1]; + abbrev[2]=num[2]; + abbrev[3]=(UseComma) ? ',' : '.'; + abbrev[4]=num[3]; + abbrev[5]=num[4]; + abbrev[6]='\0'; + } + if (n) { + if (numlen <= 3) { + //no prefix + } + else if (numlen <= 6) + strcat(abbrev,"K"); + else if (numlen <= 9) + strcat(abbrev,"M"); + else if (numlen <= 12) + strcat(abbrev,"G"); + else if (numlen <= 15) + strcat(abbrev,"T"); + else if (numlen >= 18) + strcat(abbrev,"P"); + else if (numlen <= 21) + strcat(abbrev,"E"); + else if (numlen <= 24) + strcat(abbrev,"Z"); + else if (numlen <= 27) + strcat(abbrev,"Y"); + else + strcat(abbrev,"???"); + } + return(abbrev); + } + + memset(buf,0,MAXLEN_FIXNUM*2); + + pbuf = buf; + pret = ret; + k = 0; + + for ( i = strlen(num) - 1, j = 0 ; i > -1; i--) { + if ( k == 2 && i != 0 ) { + k = 0; + pbuf[j++] = num[i]; + pbuf[j++] = (UseComma) ? ',' : '.'; + continue; + } + pbuf[j] = num[i]; + j++; + k++; + } + + pret[0]='\0'; + + for ( i = strlen(pbuf) - 1, j = 0 ; i > -1; i--, j++) + pret[j] = pbuf[i]; + + pret[j] = '\0'; + + return pret; } char *fixnum2(long long int value, int n) { #define MAXLEN_FIXNUM2 1024 - char num[MAXLEN_FIXNUM2]; - char buf[MAXLEN_FIXNUM2 * 2]; - char *pbuf; - static char ret[MAXLEN_FIXNUM2 * 2]; - char *pret; - register int i, j, k; + char num[MAXLEN_FIXNUM2]; + char buf[MAXLEN_FIXNUM2 * 2]; + char *pbuf; + static char ret[MAXLEN_FIXNUM2 * 2]; + char *pret; + register int i, j, k; - my_lltoa(value, num, sizeof(num), 0); - bzero(buf, MAXLEN_FIXNUM2*2); + my_lltoa(value, num, sizeof(num), 0); + memset(buf,0,MAXLEN_FIXNUM2*2); - pbuf = buf; - pret = ret; - k = 0; + pbuf = buf; + pret = ret; + k = 0; - for ( i = strlen(num) - 1, j = 0 ; i > -1; i--) { - if ( k == 2 && i != 0 ) { - k = 0; - pbuf[j++] = num[i]; - pbuf[j++] = (UseComma) ? ',' : '.'; - continue; - } - pbuf[j] = num[i]; - j++; - k++; - } + for ( i = strlen(num) - 1, j = 0 ; i > -1; i--) { + if ( k == 2 && i != 0 ) { + k = 0; + pbuf[j++] = num[i]; + pbuf[j++] = (UseComma) ? ',' : '.'; + continue; + } + pbuf[j] = num[i]; + j++; + k++; + } - pret[0]='\0'; + pret[0]='\0'; - for ( i = strlen(pbuf) - 1, j = 0 ; i > -1; i--, j++) - pret[j] = pbuf[i]; + for ( i = strlen(pbuf) - 1, j = 0 ; i > -1; i--, j++) + pret[j] = pbuf[i]; - pret[j] = '\0'; + pret[j] = '\0'; - return pret; + return pret; } char *buildtime(long long int elap) { + long int num = elap / 1000LL; + int hor = 0; + int min = 0; + int sec = 0; + static char buf[20]; - int num = elap / 1000; - int hor = 0; - int min = 0; - int sec = 0; - static char buf[12]; - - buf[0]='\0'; - - hor=num / 3600; - min=(num % 3600) / 60; - sec=num % 60; - sprintf(buf,"%02d:%02d:%02d",hor,min,sec); - - return(buf); + hor=num / 3600L; + min=(num % 3600L) / 60L; + sec=num % 60L; + snprintf(buf,sizeof(buf),"%02d:%02d:%02d",hor,min,sec); + return(buf); } -void obtdate(const char *dirname, const char *name, char *data) -{ +/*! +Get the date stored in the sarg-date file of a directory with the connection data. - FILE *fp_in; - char wdir[MAXLEN]; +\param dirname The directory to look for the connection directory. +\param name The name of the directory whose sarg-date file must be read. +\param data The buffer to store the content of the file. It must be more than 80 +bytes long. - sprintf(wdir,"%s%s/sarg-date",dirname,name); - if ((fp_in = fopen(wdir, "rt")) == 0) { - sprintf(wdir,"%s%s/date",dirname,name); - if ((fp_in = fopen(wdir, "rt")) == 0) { - data[0]='\0'; - return; - } - } +\retval 0 No error. +\retval -1 File not found. +*/ +int obtdate(const char *dirname, const char *name, char *data) +{ + FILE *fp_in; + char wdir[MAXLEN]; - if (!fgets(data,80,fp_in)) { - debuga(_("Failed to read the date in %s\n"),wdir); - exit(EXIT_FAILURE); - } - fclose(fp_in); - fixendofline(data); + if (snprintf(wdir,sizeof(wdir),"%s%s/sarg-date",dirname,name)>=sizeof(wdir)) { + debuga(__FILE__,__LINE__,_("Buffer too small to store ")); + debuga_more("%s%s/sarg-date",dirname,name); + exit(EXIT_FAILURE); + } + if ((fp_in = fopen(wdir, "rt")) == 0) { + if (snprintf(wdir,sizeof(wdir),"%s%s/date",dirname,name)>=sizeof(wdir)) { + debuga(__FILE__,__LINE__,_("Buffer too small to store ")); + debuga_more("%s%s/date",dirname,name); + exit(EXIT_FAILURE); + } + if ((fp_in = fopen(wdir, "rt")) == 0) { + data[0]='\0'; + return(-1); + } + } - return; + if (!fgets(data,80,fp_in)) { + debuga(__FILE__,__LINE__,_("Failed to read the date in file \"%s\"\n"),wdir); + exit(EXIT_FAILURE); + } + if (fclose(fp_in)==EOF) { + debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),wdir,strerror(errno)); + exit(EXIT_FAILURE); + } + fixendofline(data); + return(0); } void formatdate(char *date,int date_size,int year,int month,int day,int hour,int minute,int second,int dst) { - struct tm ltm; - time_t unixtime; - struct tm *fulltm; + struct tm ltm; + time_t unixtime; + struct tm *fulltm; - memset(<m,0,sizeof(ltm)); - if (year>=1900) ltm.tm_year=year-1900; - if (month>=1 && month<=12) ltm.tm_mon=month-1; - if (day>=1 && day<=31) ltm.tm_mday=day; - if (hour>=0 && hour<24) ltm.tm_hour=hour; - if (minute>=0 && minute<60) ltm.tm_min=minute; - if (second>=0 && second<60) ltm.tm_sec=second; - ltm.tm_isdst=dst; - unixtime=mktime(<m); //fill the missing entries - fulltm=localtime(&unixtime); - //strftime(date,date_size,"%a %b %d %H:%M:%S %Z %Y",fulltm); - strftime(date,date_size,"%c",fulltm); + memset(<m,0,sizeof(ltm)); + if (year>=1900) ltm.tm_year=year-1900; + if (month>=1 && month<=12) ltm.tm_mon=month-1; + if (day>=1 && day<=31) ltm.tm_mday=day; + if (hour>=0 && hour<24) ltm.tm_hour=hour; + if (minute>=0 && minute<60) ltm.tm_min=minute; + if (second>=0 && second<60) ltm.tm_sec=second; + ltm.tm_isdst=dst; + unixtime=mktime(<m); //fill the missing entries + fulltm=localtime(&unixtime); + //strftime(date,date_size,"%a %b %d %H:%M:%S %Z %Y",fulltm); + strftime(date,date_size,"%c",fulltm); } void computedate(int year,int month,int day,struct tm *t) { - memset(t,0,sizeof(*t)); - t->tm_year=year-1900; - t->tm_mon=month-1; - t->tm_mday=day; + memset(t,0,sizeof(*t)); + t->tm_year=year-1900; + t->tm_mon=month-1; + t->tm_mday=day; } int obtuser(const char *dirname, const char *name) { - - FILE *fp_in; - char wdir[MAXLEN]; - char tuser[20]; - int nuser; - - sprintf(wdir,"%s%s/sarg-users",dirname,name); - if((fp_in=fopen(wdir,"r"))==NULL) { - sprintf(wdir,"%s%s/users",dirname,name); - if((fp_in=fopen(wdir,"r"))==NULL) { - return(0); - } - } - - if (!fgets(tuser,sizeof(tuser),fp_in)) { - debuga(_("Failed to read the number of users in %s\n"),wdir); - exit(EXIT_FAILURE); - } - fclose(fp_in); - nuser=atoi(tuser); - - return(nuser); + FILE *fp_in; + char wdir[MAXLEN]; + char tuser[20]; + int nuser; + + if (snprintf(wdir,sizeof(wdir),"%s%s/sarg-users",dirname,name)>=sizeof(wdir)) { + debuga(__FILE__,__LINE__,_("Buffer too small to store ")); + debuga_more("%s%s/sarg-users",dirname,name); + exit(EXIT_FAILURE); + } + if((fp_in=fopen(wdir,"r"))==NULL) { + if (snprintf(wdir,sizeof(wdir),"%s%s/users",dirname,name)>=sizeof(wdir)) { + debuga(__FILE__,__LINE__,_("Buffer too small to store ")); + debuga_more("%s%s/users",dirname,name); + exit(EXIT_FAILURE); + } + if((fp_in=fopen(wdir,"r"))==NULL) { + return(0); + } + } + + if (!fgets(tuser,sizeof(tuser),fp_in)) { + debuga(__FILE__,__LINE__,_("Failed to read the number of users in file \"%s\"\n"),wdir); + exit(EXIT_FAILURE); + } + if (fclose(fp_in)==EOF) { + debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),wdir,strerror(errno)); + exit(EXIT_FAILURE); + } + nuser=atoi(tuser); + + return(nuser); } void obttotal(const char *dirname, const char *name, int nuser, long long int *tbytes, long long int *media) { - FILE *fp_in; - char *buf; - char wdir[MAXLEN]; - char user[MAX_USER_LEN]; - char sep; - struct getwordstruct gwarea; - longline line; - - *tbytes=0; - *media=0; - - sprintf(wdir,"%s%s/sarg-general",dirname,name); - if ((fp_in = fopen(wdir, "r")) == 0) { - sprintf(wdir,"%s%s/general",dirname,name); - if ((fp_in = fopen(wdir, "r")) == 0) { - return; - } - } - - if ((line=longline_create())==NULL) { - debuga(_("Not enough memory to read the file %s\n"),wdir); - exit(EXIT_FAILURE); - } - - while((buf=longline_read(fp_in,line))!=NULL) { - if (strncmp(buf,"TOTAL\t",6) == 0) - sep='\t'; //new file - else if (strncmp(buf,"TOTAL ",6) == 0) - sep=' '; //old file - else - continue; - getword_start(&gwarea,buf); - if (getword(user,sizeof(user),&gwarea,sep)<0) { - debuga(_("There is a invalid user in file %s\n"),wdir); - exit(EXIT_FAILURE); - } - if(strcmp(user,"TOTAL") != 0) - continue; - if (getword_skip(MAXLEN,&gwarea,sep)<0) { - debuga(_("There a broken total number of access in file %s\n"),wdir); - exit(EXIT_FAILURE); - } - if (getword_atoll(tbytes,&gwarea,sep)<0) { - debuga(_("There is a broken number of bytes in file %s\n"),wdir); - exit(EXIT_FAILURE); - } - break; - } - fclose(fp_in); - longline_destroy(&line); - - if (nuser <= 0) - return; - - *media=*tbytes / nuser; - return; + FileObject *fp_in; + char *buf; + char wdir[MAXLEN]; + char user[MAX_USER_LEN]; + char sep; + struct getwordstruct gwarea; + longline line; + + *tbytes=0; + *media=0; + + if (snprintf(wdir,sizeof(wdir),"%s%s/sarg-general",dirname,name)>=sizeof(wdir)) { + debuga(__FILE__,__LINE__,_("Buffer too small to store ")); + debuga_more("%s%s/sarg-general",dirname,name); + exit(EXIT_FAILURE); + } + if ((fp_in = FileObject_Open(wdir)) == NULL) { + if (snprintf(wdir,sizeof(wdir),"%s%s/general",dirname,name)>=sizeof(wdir)) { + debuga(__FILE__,__LINE__,_("Buffer too small to store ")); + debuga_more("%s%s/general",dirname,name); + exit(EXIT_FAILURE); + } + if ((fp_in = FileObject_Open(wdir)) == NULL) { + return; + } + } + + if ((line=longline_create())==NULL) { + debuga(__FILE__,__LINE__,_("Not enough memory to read file \"%s\"\n"),wdir); + exit(EXIT_FAILURE); + } + + while((buf=longline_read(fp_in,line))!=NULL) { + if (strncmp(buf,"TOTAL\t",6) == 0) + sep='\t'; //new file + else if (strncmp(buf,"TOTAL ",6) == 0) + sep=' '; //old file + else + continue; + getword_start(&gwarea,buf); + if (getword(user,sizeof(user),&gwarea,sep)<0) { + debuga(__FILE__,__LINE__,_("Invalid user in file \"%s\"\n"),wdir); + exit(EXIT_FAILURE); + } + if(strcmp(user,"TOTAL") != 0) + continue; + if (getword_skip(MAXLEN,&gwarea,sep)<0) { + debuga(__FILE__,__LINE__,_("Invalid total number of accesses in file \"%s\"\n"),wdir); + exit(EXIT_FAILURE); + } + if (getword_atoll(tbytes,&gwarea,sep)<0) { + debuga(__FILE__,__LINE__,_("Invalid number of bytes in file \"%s\"\n"),wdir); + exit(EXIT_FAILURE); + } + break; + } + if (FileObject_Close(fp_in)) { + debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),wdir,FileObject_GetLastCloseError()); + exit(EXIT_FAILURE); + } + longline_destroy(&line); + + if (nuser <= 0) + return; + + *media=*tbytes / nuser; + return; } int getperiod_fromsarglog(const char *arqtt,struct periodstruct *period) { - const char *str; - int day0, month0, year0, hour0, minute0; - int day1, month1, year1, hour1, minute1; - char month[4]; - int i; - - memset(period,0,sizeof(*period)); - - str=arqtt; - while((str=strstr(str,"sarg-"))!=NULL) { - str+=5; - if (!isdigit(str[0]) || !isdigit(str[1])) continue; - day0=(str[0]-'0')*10+(str[1]-'0'); - str+=2; - strncpy(month,str,3); - month[3]=0; - month0=month2num(month); - if (month0>=12) continue; - str+=3; - year0=0; - for (i=0 ; isdigit(str[i]) && i<4 ; i++) year0=year0*10+(str[i]-'0'); - if (i!=4) continue; - str+=4; - if (str[0]!='_') continue; - str++; - - if (!isdigit(str[0]) || !isdigit(str[1])) continue; - hour0=(str[0]-'0')*10+(str[1]-'0'); - str+=2; - if (!isdigit(str[0]) || !isdigit(str[1])) continue; - minute0=(str[0]-'0')*10+(str[1]-'0'); - str+=2; - - if (*str != '-') continue; - str++; - - if (!isdigit(str[0]) || !isdigit(str[1])) continue; - day1=(str[0]-'0')*10+(str[1]-'0'); - str+=2; - strncpy(month,str,3); - month[3]=0; - month1=month2num(month); - if (month1>=12) continue; - str+=3; - year1=0; - for (i=0 ; isdigit(str[i]) && i<4 ; i++) year1=year1*10+(str[i]-'0'); - if (i!=4) continue; - str+=4; - - if (str[0]!='_') continue; - str++; - - if (!isdigit(str[0]) || !isdigit(str[1])) continue; - hour1=(str[0]-'0')*10+(str[1]-'0'); - str+=2; - if (!isdigit(str[0]) || !isdigit(str[1])) continue; - minute1=(str[0]-'0')*10+(str[1]-'0'); - str+=2; - - period->start.tm_mday=day0; - period->start.tm_mon=month0; - period->start.tm_year=year0-1900; - period->start.tm_hour=hour0; - period->start.tm_min=minute0; - period->end.tm_mday=day1; - period->end.tm_mon=month1; - period->end.tm_year=year1-1900; - period->end.tm_hour=hour1; - period->end.tm_min=minute1; - return(0); - } - return(-1); + const char *str; + int day0, month0, year0, hour0, minute0; + int day1, month1, year1, hour1, minute1; + int i; + + memset(period,0,sizeof(*period)); + + str=arqtt; + while((str=strstr(str,"sarg-"))!=NULL) { + str+=5; + if (!isdigit(str[0]) || !isdigit(str[1])) continue; + day0=(str[0]-'0')*10+(str[1]-'0'); + if (day0<1 || day0>31) continue; + str+=2; + month0=(str[0]-'0')*10+(str[1]-'0')-1; + if (month0<0 || month0>11) continue; + str+=2; + year0=0; + for (i=0 ; isdigit(str[i]) && i<4 ; i++) year0=year0*10+(str[i]-'0'); + if (i!=4 || year0<1900) continue; + str+=4; + if (str[0]!='_') continue; + str++; + + if (!isdigit(str[0]) || !isdigit(str[1])) continue; + hour0=(str[0]-'0')*10+(str[1]-'0'); + str+=2; + if (!isdigit(str[0]) || !isdigit(str[1])) continue; + minute0=(str[0]-'0')*10+(str[1]-'0'); + str+=2; + + if (*str != '-') continue; + str++; + + if (!isdigit(str[0]) || !isdigit(str[1])) continue; + day1=(str[0]-'0')*10+(str[1]-'0'); + if (day1<1 || day1>31) continue; + str+=2; + month1=(str[0]-'0')*10+(str[1]-'0')-1; + if (month1<0 || month1>11) continue; + str+=2; + year1=0; + for (i=0 ; isdigit(str[i]) && i<4 ; i++) year1=year1*10+(str[i]-'0'); + if (i!=4 || year1<1900) continue; + str+=4; + + if (str[0]!='_') continue; + str++; + + if (!isdigit(str[0]) || !isdigit(str[1])) continue; + hour1=(str[0]-'0')*10+(str[1]-'0'); + str+=2; + if (!isdigit(str[0]) || !isdigit(str[1])) continue; + minute1=(str[0]-'0')*10+(str[1]-'0'); + str+=2; + + period->start.tm_mday=day0; + period->start.tm_mon=month0; + period->start.tm_year=year0-1900; + period->start.tm_hour=hour0; + period->start.tm_min=minute0; + period->end.tm_mday=day1; + period->end.tm_mon=month1; + period->end.tm_year=year1-1900; + period->end.tm_hour=hour1; + period->end.tm_min=minute1; + return(0); + } + return(-1); +} + +/*! +Fill the period with the specified range. + +\param period The period to change. +\param dfrom The start date in the form year*10000+month*100+day. +\param duntil The end date in the form year*10000+month*100+day. +*/ +void getperiod_fromrange(struct periodstruct *period,int dfrom,int duntil) +{ + memset(&period->start,0,sizeof(period->start)); + period->start.tm_mday=dfrom%100; + period->start.tm_mon=(dfrom/100)%100-1; + period->start.tm_year=(dfrom/10000)-1900; + + memset(&period->end,0,sizeof(period->end)); + period->end.tm_mday=duntil%100; + period->end.tm_mon=(duntil/100)%100-1; + period->end.tm_year=(duntil/10000)-1900; } -void getperiod_fromrange(struct periodstruct *period,int dfrom,int duntil) +/*! +Get the range from a period. + +\param period The period to convert to a range. +\param dfrom The variable to store the range beginning. It can be NULL. +\param duntil The variable to store the range end. It can be NULL. +*/ +void getperiod_torange(const struct periodstruct *period,int *dfrom,int *duntil) { - memset(&period->start,0,sizeof(period->start)); - period->start.tm_mday=dfrom%100; - period->start.tm_mon=(dfrom/100)%100-1; - period->start.tm_year=(dfrom/10000)-1900; + if (dfrom) + *dfrom=(period->start.tm_year+1900)*10000+(period->start.tm_mon+1)*100+period->start.tm_mday; + if (duntil) + *duntil=(period->end.tm_year+1900)*10000+(period->end.tm_mon+1)*100+period->end.tm_mday; +} - memset(&period->end,0,sizeof(period->end)); - period->end.tm_mday=duntil%100; - period->end.tm_mon=(duntil/100)%100-1; - period->end.tm_year=(duntil/10000)-1900; +/*! +Update the \a main period to encompass the period in \a candidate. +*/ +void getperiod_merge(struct periodstruct *main,struct periodstruct *candidate) +{ + int cdate; + int mdate; + + mdate=(main->start.tm_year)*10000+(main->start.tm_mon)*100+main->start.tm_mday; + cdate=(candidate->start.tm_year)*10000+(candidate->start.tm_mon)*100+candidate->start.tm_mday; + if (mdate==0 || cdatestart,&candidate->start,sizeof(struct tm)); + + mdate=(main->end.tm_year)*10000+(main->end.tm_mon)*100+main->end.tm_mday; + cdate=(candidate->end.tm_year)*10000+(candidate->end.tm_mon)*100+candidate->end.tm_mday; + if (cdate>mdate) memcpy(&main->end,&candidate->end,sizeof(struct tm)); } int getperiod_buildtext(struct periodstruct *period) { - int i; - int range; - char text1[40], text2[40]; - - if(df[0]=='u') { - i=strftime(text1, sizeof(text1), "%Y %b %d", &period->start); - }else if(df[0]=='e') { - i=strftime(text1, sizeof(text1), "%d %b %Y", &period->start); - } else /*if(df[0]=='w')*/ { - IndexTree=INDEX_TREE_FILE; - i=strftime(text1, sizeof(text1), "%Y.%U", &period->start); - } - if (i == 0) return(-1); - - range=(period->start.tm_year!=period->end.tm_year || - period->start.tm_mon!=period->end.tm_mon || - period->start.tm_mday!=period->end.tm_mday); - if (range) { - if(df[0]=='u') { - i=strftime(text2, sizeof(text2)-i, "%Y %b %d", &period->end); - } else if(df[0]=='e') { - i=strftime(text2, sizeof(text2)-i, "%d %b %Y", &period->end); - } else { - i=strftime(text2, sizeof(text2)-i, "%Y.%U", &period->end); - } - if (i == 0) return(-1); - } - - if (range) { - snprintf(period->text,sizeof(period->text),"%s-%s",text1,text2); - snprintf(period->html,sizeof(period->html),"%s—%s",text1,text2); - } else { - strncpy(period->text,text1,sizeof(period->text)-1); - period->text[sizeof(period->text)-1]='\0'; - strncpy(period->html,text1,sizeof(period->html)-1); - period->html[sizeof(period->html)-1]='\0'; - } - return(0); + int i; + int range; + char text1[40], text2[40]; + + if (df=='u') { + i=strftime(text1, sizeof(text1), "%Y %b %d", &period->start); + } else if(df=='e') { + i=strftime(text1, sizeof(text1), "%d %b %Y", &period->start); + } else /*if (df=='w')*/ { + IndexTree=INDEX_TREE_FILE; + i=strftime(text1, sizeof(text1), "%Y.%U", &period->start); + } + if (i == 0) return(-1); + + range=(period->start.tm_year!=period->end.tm_year || + period->start.tm_mon!=period->end.tm_mon || + period->start.tm_mday!=period->end.tm_mday); + if (range) { + if (df=='u') { + i=strftime(text2, sizeof(text2)-i, "%Y %b %d", &period->end); + } else if (df=='e') { + i=strftime(text2, sizeof(text2)-i, "%d %b %Y", &period->end); + } else { + i=strftime(text2, sizeof(text2)-i, "%Y.%U", &period->end); + } + if (i == 0) return(-1); + } + + if (range) { + snprintf(period->text,sizeof(period->text),"%s-%s",text1,text2); + snprintf(period->html,sizeof(period->html),"%s—%s",text1,text2); + } else { + safe_strcpy(period->text,text1,sizeof(period->text)); + safe_strcpy(period->html,text1,sizeof(period->html)); + } + return(0); } static void copy_images(void) { - FILE *img_in, *img_ou; - char images[512]; - char imgdir[MAXLEN]; - char srcfile[MAXLEN]; - char dstfile[MAXLEN]; - DIR *dirp; - struct dirent *direntp; - char buffer[MAXLEN]; - size_t nread; - struct stat info; - - if (snprintf(images,sizeof(images),"%simages",outdir)>=sizeof(images)) { - debuga(_("Cannot copy images to target directory %simages\n"),outdir); - exit(EXIT_FAILURE); - } - if (access(images,R_OK)!=0) { - mkdir(images,0755); - } - - strcpy(imgdir,IMAGEDIR); - dirp = opendir(imgdir); - if(dirp==NULL) { - debuga(_("(util) Can't open directory %s: %s\n"),imgdir,strerror(errno)); - return; - } - while ((direntp = readdir( dirp )) != NULL ){ - if(direntp->d_name[0]=='.') - continue; - sprintf(srcfile,"%s/%s",imgdir,direntp->d_name); - if (stat(srcfile,&info)) { - debuga(_("Cannot stat \"%s\" - %s\n"),srcfile,strerror(errno)); - continue; - } - if (S_ISREG(info.st_mode)) { - sprintf(dstfile,"%s/%s",images,direntp->d_name); - img_in = fopen(srcfile, "rb"); - if(img_in!=NULL) { - img_ou = fopen(dstfile, "wb"); - if(img_ou!=NULL) { - while ((nread = fread(buffer,1,sizeof(buffer),img_in))>0) { - if (fwrite(buffer,1,nread,img_ou)!=nread) { - debuga(_("Failed to copy image %s to %s\n"),srcfile,dstfile); - break; - } - } - fclose(img_ou); - } else - fprintf(stderr,"SARG: (util): %s %s: %s\n", _("Cannot open file")?_("Cannot open file"):"Can't open/create file", dstfile, strerror(errno)); - fclose(img_in); - } else - fprintf(stderr,"SARG: (util): %s %s: %s\n", _("Cannot open file")?_("Cannot open file"):"Can't open file", srcfile, strerror(errno)); - } - } - (void) closedir(dirp); - - return; -} - -int vrfydir(const struct periodstruct *per1, const char *addr, const char *site, const char *us, const char *form) -{ - FILE *fp_ou; - int num=1, count=0; - char wdir[MAXLEN]; - char dirname2[MAXLEN]; - int y1, y2; - int m1, m2; - int d1, d2; - int wlen, wlen2; - time_t curtime; - struct tm *loctm; - - strcpy(wdir,outdir); - wlen=strlen(wdir); - y1=per1->start.tm_year+1900; - y2=per1->end.tm_year+1900; - m1=per1->start.tm_mon+1; - m2=per1->end.tm_mon+1; - d1=per1->start.tm_mday; - d2=per1->end.tm_mday; - if(IndexTree == INDEX_TREE_DATE) { - wlen+=sprintf(wdir+wlen,"%04d",y1); - if(y1!=y2) wlen+=sprintf(wdir+wlen,"-%04d",y2); - if(access(wdir, R_OK) != 0) - my_mkdir(wdir); - - wlen+=sprintf(wdir+wlen,"/%02d",m1); - if(m1 != m2) wlen+=sprintf(wdir+wlen,"-%02d",m2); - if(access(wdir, R_OK) != 0) - my_mkdir(wdir); - - wlen+=sprintf(wdir+wlen,"/%02d",d1); - if(d1!=d2) wlen+=sprintf(wdir+wlen,"-%02d",d2); - } else { - if(df[0] == 'u') { - wlen=snprintf(wdir+wlen,sizeof(wdir)-wlen,"%04d%s%02d-%04d%s%02d",y1, - conv_month_name(m1),d1,y2,conv_month_name(m2),d2); - } else if(df[0] == 'e') { - wlen=snprintf(wdir+wlen,sizeof(wdir)-wlen,"%02d%s%04d-%02d%s%04d",d1, - conv_month_name(m1),y1,d2,conv_month_name(m2),y2); - } else if(df[0] == 'w') { - wlen2=strftime(wdir+wlen, sizeof(wdir)-wlen, "%Y.%U", &per1->start); - if (wlen2==0) return(-1); - wlen+=wlen2; - } - } - - if(us[0] != '\0') { - struct userinfostruct *uinfo=userinfo_find_from_id(us); - if (uinfo) { - strcat(wdir,"-"); - strcat(wdir,uinfo->filename); - } - } - if(addr[0] != '\0') { - strcat(wdir,"-"); - strcat(wdir,addr); - } - if(site[0] != '\0') { - strcat(wdir,"-"); - strcat(wdir,site); - } - - strcpy(outdirname,wdir); - - if(IndexTree != INDEX_TREE_DATE) { - if(!OverwriteReport) { - while(num) { - if(access(wdir,R_OK) == 0) { - sprintf(wdir,"%s.%d",outdirname,num); - num++; - count++; - } else - break; - } - - if(count > 0) { - if(debug) - debuga(_("File %s already exists, moved to %s\n"),outdirname,wdir); - rename(outdirname,wdir); - } - } else { - if(access(outdirname,R_OK) == 0) { - unlinkdir(outdirname,1); - } - } - my_mkdir(outdirname); - } else { - strcpy(dirname2,wdir); - if(!OverwriteReport) { - while(num) { - if(access(wdir,R_OK) == 0) { - sprintf(wdir,"%s.%d",dirname2,num); - num++; - count++; - } else - break; - } - - if(count > 0) { - if(debug) - debuga(_("File %s already exists, moved to %s\n"),dirname2,wdir); - rename(dirname2,wdir); - strcpy(dirname2,wdir); - } - } else { - if(access(wdir,R_OK) == 0) { - unlinkdir(wdir,1); - } - } - - if(access(wdir, R_OK) != 0) - my_mkdir(wdir); - } - - strcpy(dirname2,wdir); - - sprintf(wdir,"%s/sarg-date",outdirname); - if ((fp_ou = fopen(wdir, "wt")) == 0) { - debuga(_("cannot open %s for writing\n"),wdir); - perror("SARG:"); - exit(EXIT_FAILURE); - } - time(&curtime); - //strftime(wdir,sizeof(wdir),"%a %b %d %H:%M:%S %Z %Y",localtime(&curtime)); - loctm=localtime(&curtime); - strftime(wdir,sizeof(wdir),"%Y-%m-%d %H:%M:%S",loctm); - if (fprintf(fp_ou,"%s %d\n",wdir,loctm->tm_isdst)<0) { - debuga(_("Failed to write the date in %s\n"),wdir); - perror("SARG:"); - exit(EXIT_FAILURE); - } - if (fclose(fp_ou)==EOF) { - debuga(_("Failed to write the date in %s\n"),wdir); - perror("SARG:"); - exit(EXIT_FAILURE); - } - - copy_images(); - return(0); + FILE *img_in, *img_ou; + char images[512]; + char srcfile[MAXLEN]; + char dstfile[MAXLEN]; + DIR *dirp; + struct dirent *direntp; + char buffer[MAXLEN]; + size_t nread; + struct stat info; + + if (snprintf(images,sizeof(images),"%simages",outdir)>=sizeof(images)) { + debuga(__FILE__,__LINE__,_("Cannot copy images to target directory %simages\n"),outdir); + exit(EXIT_FAILURE); + } + if (access(images,R_OK)!=0) { + if (PortableMkDir(images,0755)) { + debuga(__FILE__,__LINE__,_("Cannot create directory \"%s\": %s\n"),images,strerror(errno)); + exit(EXIT_FAILURE); + } + } + + dirp = opendir(ImageDir); + if(dirp==NULL) { + debuga(__FILE__,__LINE__,_("Cannot open directory \"%s\": %s\n"),ImageDir,strerror(errno)); + return; + } + while ((direntp = readdir( dirp )) != NULL ){ + if(direntp->d_name[0]=='.') + continue; + if (snprintf(srcfile,sizeof(srcfile),"%s/%s",ImageDir,direntp->d_name)>=sizeof(srcfile)) { + debuga(__FILE__,__LINE__,_("Buffer too small to store ")); + debuga_more("%s/%s",ImageDir,direntp->d_name); + exit(EXIT_FAILURE); + } + if (stat(srcfile,&info)) { + debuga(__FILE__,__LINE__,_("Cannot stat \"%s\": %s\n"),srcfile,strerror(errno)); + continue; + } + if (S_ISREG(info.st_mode)) { + if (snprintf(dstfile,sizeof(dstfile),"%s/%s",images,direntp->d_name)>=sizeof(dstfile)) { + debuga(__FILE__,__LINE__,_("Buffer too small to store ")); + debuga_more("%s/%s",images,direntp->d_name); + exit(EXIT_FAILURE); + } + img_in = fopen(srcfile, "rb"); + if(img_in!=NULL) { + img_ou = fopen(dstfile, "wb"); + if(img_ou!=NULL) { + while ((nread = fread(buffer,1,sizeof(buffer),img_in))>0) { + if (fwrite(buffer,1,nread,img_ou)!=nread) { + debuga(__FILE__,__LINE__,_("Failed to copy image %s to %s\n"),srcfile,dstfile); + break; + } + } + if (fclose(img_ou)==EOF) { + debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),dstfile,strerror(errno)); + exit(EXIT_FAILURE); + } + } else + debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"), dstfile, strerror(errno)); + if (fclose(img_in)==EOF) { + debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),srcfile,strerror(errno)); + exit(EXIT_FAILURE); + } + } else + debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"), srcfile, strerror(errno)); + } + } + (void) closedir(dirp); + + return; +} + +/*! + * Check if the proposed file name conforms to the directory structure layed out + * as a file tree. It is used to check if the file name enumerated while scanning + * a directory content may have been created by sarg running with IndexTree set to + * INDEX_TREE_FILE. + */ +bool IsTreeFileDirName(const char *Name) +{ + char DateFormat; + int i; + + // start year (date format u) or start day (date format e) + if (!isdigit(Name[0]) || !isdigit(Name[1])) return(false); + + if (isdigit(Name[2]) && isdigit(Name[3])) + { + // date format is either u or w + if (Name[4]=='.') + { + // date format is w + if (!isdigit(Name[5]) || !isdigit(Name[6])) return(false); + return(true);//date format w is confirmed + } + + // date format is u + Name+=4; + + // start month + if (!isalpha(Name[0]) || !isalpha(Name[1]) || !isalpha(Name[2])) return(false); + for (i=11 ; i>=0 && memcmp(mtab1[i],Name,3) ; i--); + if (i<0) return(false); + Name+=3; + + // start day + if (!isdigit(Name[0]) || !isdigit(Name[1])) return(false); + Name+=2; + + DateFormat='u'; + } + else if (isalpha(Name[2]) && isalpha(Name[3]) && isalpha(Name[4])) + { + // date format is e + Name+=2; + + // start month + if (!isalpha(Name[0]) || !isalpha(Name[1]) || !isalpha(Name[2])) return(false); + for (i=11 ; i>=0 && memcmp(mtab1[i],Name,3) ; i--); + if (i<0) return(false); + Name+=3; + + // start day + if (!isdigit(Name[0]) || !isdigit(Name[1]) || !isdigit(Name[2]) || !isdigit(Name[3])) return(false); + Name+=4; + + DateFormat='e'; + } + else + return(false); + + if (Name[0]!='-') return(false); + Name++; + + if (DateFormat=='u') + { + if (!isdigit(Name[0]) || !isdigit(Name[1]) || !isdigit(Name[2]) || !isdigit(Name[3])) return(false); + Name+=4; + + if (!isalpha(Name[0]) || !isalpha(Name[1]) || !isalpha(Name[2])) return(false); + for (i=11 ; i>=0 && memcmp(mtab1[i],Name,3) ; i--); + if (i<0) return(false); + Name+=3; + + if (!isdigit(Name[0]) || !isdigit(Name[1])) return(false); + Name+=2; + } + else //DateFormat=='e' + { + if (!isdigit(Name[0]) || !isdigit(Name[1])) return(false); + Name+=2; + + if (!isalpha(Name[0]) || !isalpha(Name[1]) || !isalpha(Name[2])) return(false); + for (i=11 ; i>=0 && memcmp(mtab1[i],Name,3) ; i--); + if (i<0) return(false); + Name+=3; + + if (!isdigit(Name[0]) || !isdigit(Name[1]) || !isdigit(Name[2]) || !isdigit(Name[3])) return(false); + Name+=4; + } + /* + * The directory name may contains additional characters such as a counter if + * a previous report is never overwritten. + */ + return(true); +} + +/*! + * Check if the proposed file name can be the year part of a report tree build with + * IndexTree set to INDEX_TREE_DATE. + */ +bool IsTreeYearFileName(const char *Name) +{ + if (!isdigit(Name[0]) || !isdigit(Name[1]) || !isdigit(Name[2]) || !isdigit(Name[3])) return(false); + Name+=4; + if (Name[0]=='-') + { + Name++; + if (!isdigit(Name[0]) || !isdigit(Name[1]) || !isdigit(Name[2]) || !isdigit(Name[3])) return(false); + Name+=4; + } + if (Name[0]) return(false); + return(true); +} + +/*! + * Check if the proposed file name can be the month part of a report tree build with + * IndexTree set to INDEX_TREE_DATE. + */ +bool IsTreeMonthFileName(const char *Name) +{ + int m; + + if (!isdigit(Name[0]) || !isdigit(Name[1])) return(false); + m=(Name[0]-'0')*10+(Name[1]-'0'); + if (m<1 || m>12) return(false); + Name+=2; + if (Name[0]=='-') + { + Name++; + if (!isdigit(Name[0]) || !isdigit(Name[1])) return(false); + m=(Name[0]-'0')*10+(Name[1]-'0'); + if (m<1 || m>12) return(false); + Name+=2; + } + if (Name[0]) return(false); + return(true); +} + +/*! + * Check if the proposed file name can be the day part of a report tree build with + * IndexTree set to INDEX_TREE_DATE. + */ +bool IsTreeDayFileName(const char *Name) +{ + int d; + + if (!isdigit(Name[0]) || !isdigit(Name[1])) return(false); + d=(Name[0]-'0')*10+(Name[1]-'0'); + if (d<1 || d>31) return(false); + if (Name[2]=='-') + { + Name+=3; + if (!isdigit(Name[0]) || !isdigit(Name[1])) return(false); + d=(Name[0]-'0')*10+(Name[1]-'0'); + if (d<1 || d>31) return(false); + } + /* + * The directory name may contains additional characters such as a counter if + * a previous report is never overwritten. + */ + return(true); +} + +/*! + * Create a directory to generate a report for the specified connection data + * and populate it with the a sarg-date file containing the current + * date. + * + * The function also create an images directory in \a dir and copy all + * the files from the SYSCONFDIR/images into that directory. + * + * \param per1 The date range in the form: YYYYMMMDD-YYYYMMMDD or DDMMMYYYY-DDMMMYYYY depending on the value of + * ::DateFormat. + * \param addr The ip address or host name to which the report is limited. If the string is empty, all the addresses are accepted. + * \param site The destination site to which the report is limited. If the string is empty, all the sites are accepted. + * \param us The user to whom the report is limited. It is an empty string if all the users are accepted. + */ +int vrfydir(const struct periodstruct *per1, const char *addr, const char *site, const char *us) +{ + FILE *fp_ou; + char wdir[MAXLEN]; + int y1, y2; + int m1, m2; + int d1, d2; + int wlen, wlen2; + time_t curtime; + struct tm *loctm; + + strcpy(wdir,outdir); + wlen=strlen(wdir); + y1=per1->start.tm_year+1900; + y2=per1->end.tm_year+1900; + m1=per1->start.tm_mon+1; + m2=per1->end.tm_mon+1; + d1=per1->start.tm_mday; + d2=per1->end.tm_mday; + if(IndexTree == INDEX_TREE_DATE) { + wlen+=sprintf(wdir+wlen,"%04d",y1); + if(y1!=y2) wlen+=sprintf(wdir+wlen,"-%04d",y2); + if(access(wdir, R_OK) != 0) + my_mkdir(wdir); + + wlen+=sprintf(wdir+wlen,"/%02d",m1); + if(m1 != m2) wlen+=sprintf(wdir+wlen,"-%02d",m2); + if(access(wdir, R_OK) != 0) + my_mkdir(wdir); + + wlen+=sprintf(wdir+wlen,"/%02d",d1); + if(d1!=d2) wlen+=sprintf(wdir+wlen,"-%02d",d2); + } else { + if (df == 'u') { + wlen=snprintf(wdir+wlen,sizeof(wdir)-wlen,"%04d%s%02d-%04d%s%02d",y1, + conv_month_name(m1),d1,y2,conv_month_name(m2),d2); + } else if (df == 'e') { + wlen=snprintf(wdir+wlen,sizeof(wdir)-wlen,"%02d%s%04d-%02d%s%04d",d1, + conv_month_name(m1),y1,d2,conv_month_name(m2),y2); + } else if (df == 'w') { + wlen2=strftime(wdir+wlen, sizeof(wdir)-wlen, "%Y.%U", &per1->start); + if (wlen2==0) return(-1); + wlen+=wlen2; + } + } + + if(us[0] != '\0') { + struct userinfostruct *uinfo=userinfo_find_from_id(us); + if (uinfo) { + strcat(wdir,"-"); + strcat(wdir,uinfo->filename); + } + } + if(addr[0] != '\0') { + strcat(wdir,"-"); + strcat(wdir,addr); + } + if(site[0] != '\0') { + strcat(wdir,"-"); + strcat(wdir,site); + } + + strcpy(outdirname,wdir); + + // manufacture a new unique name if configured to keep old reports or overwrite old report if configured to do so + if (!OverwriteReport) { + int num=1; + + while (access(wdir,R_OK)==0 || errno==EACCES) //file exist or can't be read + { + sprintf(wdir,"%s.%d",outdirname,num); + num++; + } + if (num>1) { + if(debug) + debuga(__FILE__,__LINE__,_("File %s already exists, moved to %s\n"),outdirname,wdir); + rename(outdirname,wdir); + } + } else { + if(access(outdirname,R_OK) == 0) { + unlinkdir(outdirname,1); + } + } + my_mkdir(outdirname); + + // create sarg-date to keep track of the report creation date + if (snprintf(wdir,sizeof(wdir),"%s/sarg-date",outdirname)>=sizeof(wdir)) { + debuga(__FILE__,__LINE__,_("Buffer too small to store ")); + debuga_more("%s/sarg-date",outdirname); + exit(EXIT_FAILURE); + } + if ((fp_ou = fopen(wdir, "wt")) == 0) { + debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),wdir,strerror(errno)); + perror("SARG:"); + exit(EXIT_FAILURE); + } + time(&curtime); + //strftime(wdir,sizeof(wdir),"%a %b %d %H:%M:%S %Z %Y",localtime(&curtime)); + loctm=localtime(&curtime); + strftime(wdir,sizeof(wdir),"%Y-%m-%d %H:%M:%S",loctm); + if (fprintf(fp_ou,"%s %d\n",wdir,loctm->tm_isdst)<0) { + debuga(__FILE__,__LINE__,_("Failed to write the date in %s\n"),wdir); + perror("SARG:"); + exit(EXIT_FAILURE); + } + if (fclose(fp_ou)==EOF) { + debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),wdir,strerror(errno)); + exit(EXIT_FAILURE); + } + + copy_images(); + return(0); +} + +/*! + Copy a string without overflowing the buffer. The copied string + is properly terminated by an ASCII zero. + + \param dest The destination buffer. + \param src The source buffer. + \param length The size of the destination buffer. The program is aborted + if the length is negative or zero. +*/ +void safe_strcpy(char *dest,const char *src,int length) +{ + if (length<=0) { + debuga(__FILE__,__LINE__,_("Invalid buffer length passed to the function to safely copy a string\n")); + exit(EXIT_FAILURE); + } + strncpy(dest,src,length-1); + dest[length-1]='\0'; } void strip_latin(char *line) { - int i,j; - int skip; - - j=0; - skip=0; - for (i=0;line[i];i++){ - if (skip){ - if (line[i]==';') skip=0; - } else { - if (line[i]=='&') - skip=1; - else - line[j++]=line[i]; - } - } - line[j]='\0'; - return; + int i,j; + int skip; + j=0; + skip=0; + for (i=0;line[i];i++){ + if (skip){ + if (line[i]==';') skip=0; + } else { + if (line[i]=='&') + skip=1; + else + line[j++]=line[i]; + } + } + line[j]='\0'; + return; } -void zdate(char *ftime,int ftimesize, const char *DateFormat) +void zdate(char *ftime,int ftimesize, char DateFormat) { + time_t t; + struct tm *local; - time_t t; - struct tm *local; - - t = time(NULL); - local = localtime(&t); - if(strcmp(DateFormat,"u") == 0) - strftime(ftime, ftimesize, "%b/%d/%Y %H:%M", local); - if(strcmp(DateFormat,"e") == 0) - strftime(ftime, ftimesize, "%d/%b/%Y-%H:%M", local); - if(strcmp(DateFormat,"w") == 0) - strftime(ftime, ftimesize, "%W-%H-%M", local); - return; + t = time(NULL); + local = localtime(&t); + if (DateFormat=='u') + strftime(ftime, ftimesize, "%b/%d/%Y %H:%M", local); + else if (DateFormat=='e') + strftime(ftime, ftimesize, "%d/%b/%Y-%H:%M", local); + else if (DateFormat=='w') + strftime(ftime, ftimesize, "%W-%H-%M", local); + return; } char *fixtime(long long int elap) { - int num = elap / 1000; - int hor = 0; - int min = 0; - int sec = 0; - static char buf[12]; - - hor=num / 3600; - min=(num % 3600) / 60; - sec=num % 60; - - if(hor==0 && min==0 && sec==0) - strcpy(buf,"0"); - else - sprintf(buf,"%d:%02d:%02d",hor,min,sec); - - return buf; -} - - -void date_from(char *date, int *dfrom, int *duntil) -{ - int d0=0; - int m0=0; - int y0=0; - int d1=0; - int m1=0; - int y1=0; - - if (isdigit(date[0])) { - int next=-1; - - if (sscanf(date,"%d/%d/%d%n",&d0,&m0,&y0,&next)!=3 || y0<100 || m0<1 || m0>12 || d0<1 || d0>31 || next<0) { - debuga(_("The date passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n")); - exit(EXIT_FAILURE); - } - if (date[next]=='-') { - if (sscanf(date+next+1,"%d/%d/%d",&d1,&m1,&y1)!=3 || y1<100 || m1<1 || m1>12 || d1<1 || d1>31) { - debuga(_("The date range passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n")); - exit(EXIT_FAILURE); - } - } else if (date[next]!='\0') { - debuga(_("The date range passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n")); - exit(EXIT_FAILURE); - } else { - d1=d0; - m1=m0; - y1=y0; - } - } else { - int i; - time_t Today,t1; - struct tm *Date0,Date1; - - if (time(&Today)==(time_t)-1) { - debuga(_("Failed to get the current time\n")); - exit(EXIT_FAILURE); - } - if (sscanf(date,"day-%d",&i)==1) { - if (i<0) { - debuga(_("Invalid number of days in -d parameter\n")); - exit(EXIT_FAILURE); - } - Today-=i*24*60*60; - Date0=localtime(&Today); - if (Date0==NULL) { - debuga(_("Cannot convert local time: %s\n"),strerror(errno)); - exit(EXIT_FAILURE); - } - y0=y1=Date0->tm_year+1900; - m0=m1=Date0->tm_mon+1; - d0=d1=Date0->tm_mday; - } else if (sscanf(date,"week-%d",&i)==1) { - /* - There is no portable way to find the first day of the week even though the - information is available in the locale. nl_langinfo has the unofficial - parameters _NL_TIME_FIRST_WEEKDAY and _NL_TIME_WEEK_1STDAY but they are - undocumented as is their return value and it is discouraged to use them. - Beside, nl_langinfo isn't available on windows and the first day of the - week isn't available at all on that system. - */ - const int FirstWeekDay=1; - time_t WeekBegin; - - if (i<0) { - debuga(_("Invalid number of weeks in -d parameter\n")); - exit(EXIT_FAILURE); - } - Date0=localtime(&Today); - if (Date0==NULL) { - debuga(_("Cannot convert local time: %s\n"),strerror(errno)); - exit(EXIT_FAILURE); - } - WeekBegin=Today-((Date0->tm_wday-FirstWeekDay+7)%7)*24*60*60; - WeekBegin-=i*7*24*60*60; - Date0=localtime(&WeekBegin); - if (Date0==NULL) { - debuga(_("Cannot convert local time: %s\n"),strerror(errno)); - exit(EXIT_FAILURE); - } - y0=Date0->tm_year+1900; - m0=Date0->tm_mon+1; - d0=Date0->tm_mday; - WeekBegin+=6*24*60*60; - Date0=localtime(&WeekBegin); - if (Date0==NULL) { - debuga(_("Cannot convert local time: %s\n"),strerror(errno)); - exit(EXIT_FAILURE); - } - y1=Date0->tm_year+1900; - m1=Date0->tm_mon+1; - d1=Date0->tm_mday; - } else if (sscanf(date,"month-%d",&i)==1) { - if (i<0) { - debuga(_("Invalid number of months in -d parameter\n")); - exit(EXIT_FAILURE); - } - Date0=localtime(&Today); - if (Date0==NULL) { - debuga(_("Cannot convert local time: %s\n"),strerror(errno)); - exit(EXIT_FAILURE); - } - if (Date0->tm_montm_year+1900-i/12-1; - m0=(Date0->tm_mon+12-i%12)%12+1; - d0=1; - } else { - y0=Date0->tm_year+1900-i/12; - m0=Date0->tm_mon-i%12+1; - d0=1; - } - memcpy(&Date1,Date0,sizeof(struct tm)); - Date1.tm_isdst=-1; - Date1.tm_mday=1; - if (m0<12) { - Date1.tm_mon=m0; - Date1.tm_year=y0-1900; - } else { - Date1.tm_mon=0; - Date1.tm_year=y0-1900+1; - } - t1=mktime(&Date1); - t1-=24*60*60; - Date0=localtime(&t1); - y1=Date0->tm_year+1900; - m1=Date0->tm_mon+1; - d1=Date0->tm_mday; - } else { - debuga(_("Invalid date range passed on command line\n")); - exit(EXIT_FAILURE); - } - } - - *dfrom=y0*10000+m0*100+d0; - *duntil=y1*10000+m1*100+d1; - sprintf(date,"%02d/%02d/%04d-%02d/%02d/%04d",d0,m0,y0,d1,m1,y1); - return; + long int num = elap / 1000LL; + int hor = 0; + int min = 0; + int sec = 0; + static char buf[20]; + + hor=num / 3600L; + min=(num % 3600L) / 60L; + sec=num % 60L; + + if(hor==0 && min==0 && sec==0) + strcpy(buf,"0"); + else + snprintf(buf,sizeof(buf),"%d:%02d:%02d",hor,min,sec); + + return buf; +} + + +void date_from(char *date,int date_size, int *dfrom, int *duntil) +{ + int d0=0; + int m0=0; + int y0=0; + int d1=0; + int m1=0; + int y1=0; + + if (isdigit(date[0])) { + int next=-1; + + if (sscanf(date,"%d/%d/%d%n",&d0,&m0,&y0,&next)!=3 || y0<100 || m0<1 || m0>12 || d0<1 || d0>31 || next<0) { + debuga(__FILE__,__LINE__,_("The date passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n")); + exit(EXIT_FAILURE); + } + if (date[next]=='-') { + if (sscanf(date+next+1,"%d/%d/%d",&d1,&m1,&y1)!=3 || y1<100 || m1<1 || m1>12 || d1<1 || d1>31) { + debuga(__FILE__,__LINE__,_("The date range passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n")); + exit(EXIT_FAILURE); + } + } else if (date[next]!='\0') { + debuga(__FILE__,__LINE__,_("The date range passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n")); + exit(EXIT_FAILURE); + } else { + d1=d0; + m1=m0; + y1=y0; + } + } else { + int i; + time_t Today,t1; + struct tm *Date0,Date1; + + if (time(&Today)==(time_t)-1) { + debuga(__FILE__,__LINE__,_("Failed to get the current time\n")); + exit(EXIT_FAILURE); + } + if (sscanf(date,"day-%d",&i)==1) { + if (i<0) { + debuga(__FILE__,__LINE__,_("Invalid number of days in -d parameter\n")); + exit(EXIT_FAILURE); + } + Today-=i*24*60*60; + Date0=localtime(&Today); + if (Date0==NULL) { + debuga(__FILE__,__LINE__,_("Cannot convert local time: %s\n"),strerror(errno)); + exit(EXIT_FAILURE); + } + y0=y1=Date0->tm_year+1900; + m0=m1=Date0->tm_mon+1; + d0=d1=Date0->tm_mday; + } else if (sscanf(date,"week-%d",&i)==1) { + /* + There is no portable way to find the first day of the week even though the + information is available in the locale. nl_langinfo has the unofficial + parameters _NL_TIME_FIRST_WEEKDAY and _NL_TIME_WEEK_1STDAY but they are + undocumented as is their return value and it is discouraged to use them. + Beside, nl_langinfo isn't available on windows and the first day of the + week isn't available at all on that system. + */ + const int FirstWeekDay=1; + time_t WeekBegin; + + if (i<0) { + debuga(__FILE__,__LINE__,_("Invalid number of weeks in -d parameter\n")); + exit(EXIT_FAILURE); + } + Date0=localtime(&Today); + if (Date0==NULL) { + debuga(__FILE__,__LINE__,_("Cannot convert local time: %s\n"),strerror(errno)); + exit(EXIT_FAILURE); + } + WeekBegin=Today-((Date0->tm_wday-FirstWeekDay+7)%7)*24*60*60; + WeekBegin-=i*7*24*60*60; + Date0=localtime(&WeekBegin); + if (Date0==NULL) { + debuga(__FILE__,__LINE__,_("Cannot convert local time: %s\n"),strerror(errno)); + exit(EXIT_FAILURE); + } + y0=Date0->tm_year+1900; + m0=Date0->tm_mon+1; + d0=Date0->tm_mday; + WeekBegin+=6*24*60*60; + Date0=localtime(&WeekBegin); + if (Date0==NULL) { + debuga(__FILE__,__LINE__,_("Cannot convert local time: %s\n"),strerror(errno)); + exit(EXIT_FAILURE); + } + y1=Date0->tm_year+1900; + m1=Date0->tm_mon+1; + d1=Date0->tm_mday; + } else if (sscanf(date,"month-%d",&i)==1) { + if (i<0) { + debuga(__FILE__,__LINE__,_("Invalid number of months in -d parameter\n")); + exit(EXIT_FAILURE); + } + Date0=localtime(&Today); + if (Date0==NULL) { + debuga(__FILE__,__LINE__,_("Cannot convert local time: %s\n"),strerror(errno)); + exit(EXIT_FAILURE); + } + if (Date0->tm_montm_year+1900-i/12-1; + m0=(Date0->tm_mon+12-i%12)%12+1; + d0=1; + } else { + y0=Date0->tm_year+1900-i/12; + m0=Date0->tm_mon-i%12+1; + d0=1; + } + memcpy(&Date1,Date0,sizeof(struct tm)); + Date1.tm_isdst=-1; + Date1.tm_mday=1; + if (m0<12) { + Date1.tm_mon=m0; + Date1.tm_year=y0-1900; + } else { + Date1.tm_mon=0; + Date1.tm_year=y0-1900+1; + } + t1=mktime(&Date1); + t1-=24*60*60; + Date0=localtime(&t1); + y1=Date0->tm_year+1900; + m1=Date0->tm_mon+1; + d1=Date0->tm_mday; + } else { + debuga(__FILE__,__LINE__,_("Invalid date range passed on command line\n")); + exit(EXIT_FAILURE); + } + } + + *dfrom=y0*10000+m0*100+d0; + *duntil=y1*10000+m1*100+d1; + snprintf(date,date_size,"%02d/%02d/%04d-%02d/%02d/%04d",d0,m0,y0,d1,m1,y1); + return; } char *strlow(char *string) { - char *s; + char *s; - if (string) - { - for (s = string; *s; ++s) - *s = tolower(*s); - } + if (string) + { + for (s = string; *s; ++s) + *s = tolower(*s); + } - return string; + return string; } @@ -1294,507 +1733,800 @@ char *strlow(char *string) char *strup(char *string) { - char *s; + char *s; - if (string) - { - for (s = string; *s; ++s) - *s = toupper(*s); - } + if (string) + { + for (s = string; *s; ++s) + *s = toupper(*s); + } - return string; + return string; } void removetmp(const char *outdir) { - FILE *fp_in; - char warea[256]; - char buf[MAXLEN]; - long pos; - - if(!RemoveTempFiles) - return; - - if(debug) { - debuga(_("Purging temporary file sarg-general\n")); - } - if (snprintf(warea,sizeof(warea),"%s/sarg-general",outdir)>=sizeof(warea)) { - debuga(_("(removetmp) directory too long to remove %s/sarg-period\n"),outdir); - exit(EXIT_FAILURE); - } - if((fp_in=fopen(warea,"r+"))==NULL){ - debuga(_("(removetmp) Cannot open file %s\n"),warea); - exit(EXIT_FAILURE); - } - while(fgets(buf,sizeof(buf),fp_in)!=NULL) { - if(strncmp(buf,"TOTAL",5) == 0 && (buf[6]=='\t' || buf[6]==' ')) - break; - } - if (fseek(fp_in,0,SEEK_SET)==-1) { - debuga(_("Failed to rewind to the beginning of the file %s: %s\n"),warea,strerror(errno)); - exit(EXIT_FAILURE); - } - - if (fputs(buf,fp_in)==EOF) { - debuga(_("Failed to write the total line in %s - %s\n"),warea,strerror(errno)); - exit(EXIT_FAILURE); - } - pos=ftell(fp_in); - if (pos>0 && ftruncate(fileno(fp_in),pos)==-1) { - debuga(_("Failed to truncate %s: %s\n"),warea,strerror(errno)); - exit(EXIT_FAILURE); - } - if (fclose(fp_in)==EOF) { - debuga(_("Failed to close %s after writing the total line - %s\n"),warea,strerror(errno)); - exit(EXIT_FAILURE); - } - - return; + FILE *fp_gen; + char filename[256]; + + if(!RemoveTempFiles) + return; + + if(debug) { + debuga(__FILE__,__LINE__,_("Purging temporary file sarg-general\n")); + } + if (snprintf(filename,sizeof(filename),"%s/sarg-general",outdir)>=sizeof(filename)) { + debuga(__FILE__,__LINE__,_("Path too long: ")); + debuga_more("%s/sarg-period\n",outdir); + exit(EXIT_FAILURE); + } + if((fp_gen=fopen(filename,"w"))==NULL){ + debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),filename,strerror(errno)); + exit(EXIT_FAILURE); + } + totalger(fp_gen,filename); + if (fclose(fp_gen)==EOF) { + debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),filename,strerror(errno)); + exit(EXIT_FAILURE); + } } void load_excludecodes(const char *ExcludeCodes) { - - FILE *fp_in; - char data[80]; - int i; - int Stored; - long int MemSize; - - if(ExcludeCodes[0] == '\0') - return; - - if((fp_in=fopen(ExcludeCodes,"r"))==NULL) { - debuga(_("(util) Cannot open file %s (exclude_codes)\n"),ExcludeCodes); - exit(EXIT_FAILURE); - } - - if (fseek(fp_in, 0, SEEK_END)==-1) { - debuga(_("Failed to move till the end of the excluded codes file %s: %s\n"),ExcludeCodes,strerror(errno)); - exit(EXIT_FAILURE); - } - MemSize = ftell(fp_in); - if (MemSize<0) { - debuga(_("Cannot get the size of file %s\n"),ExcludeCodes); - exit(EXIT_FAILURE); - } - if (fseek(fp_in, 0, SEEK_SET)==-1) { - debuga(_("Failed to rewind the excluded codes file %s: %s\n"),ExcludeCodes,strerror(errno)); - exit(EXIT_FAILURE); - } - - MemSize+=1; - if((excludecode=(char *) malloc(MemSize))==NULL) { - debuga(_("malloc error (%ld)\n"),MemSize); - exit(EXIT_FAILURE); - } - memset(excludecode,0,MemSize); - - Stored=0; - while(fgets(data,sizeof(data),fp_in)!=NULL) { - if (data[0]=='#') continue; - for (i=strlen(data)-1 ; i>=0 && (unsigned char)data[i]<=' ' ; i--) data[i]='\0'; - if (i<0) continue; - if (Stored+i+2>=MemSize) { - debuga(_("Too many codes to exclude in file %s\n"),ExcludeCodes); - break; - } - strcat(excludecode,data); - strcat(excludecode,";"); - Stored+=i+1; - } - - fclose(fp_in); - return; + FILE *fp_in; + char data[80]; + int i; + int Stored; + long int MemSize; + + if(ExcludeCodes[0] == '\0') + return; + + if((fp_in=fopen(ExcludeCodes,"r"))==NULL) { + debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),ExcludeCodes,strerror(errno)); + exit(EXIT_FAILURE); + } + + if (fseek(fp_in, 0, SEEK_END)==-1) { + debuga(__FILE__,__LINE__,_("Failed to move till the end of file \"%s\": %s\n"),ExcludeCodes,strerror(errno)); + exit(EXIT_FAILURE); + } + MemSize = ftell(fp_in); + if (MemSize<0) { + debuga(__FILE__,__LINE__,_("Cannot get the size of file \"%s\"\n"),ExcludeCodes); + exit(EXIT_FAILURE); + } + if (fseek(fp_in, 0, SEEK_SET)==-1) { + debuga(__FILE__,__LINE__,_("Failed to rewind file \"%s\": %s\n"),ExcludeCodes,strerror(errno)); + exit(EXIT_FAILURE); + } + + MemSize+=1; + if((excludecode=(char *) malloc(MemSize))==NULL) { + debuga(__FILE__,__LINE__,_("malloc error (%ld bytes required)\n"),MemSize); + exit(EXIT_FAILURE); + } + memset(excludecode,0,MemSize); + + Stored=0; + while(fgets(data,sizeof(data),fp_in)!=NULL) { + if (data[0]=='#') continue; + for (i=strlen(data)-1 ; i>=0 && (unsigned char)data[i]<=' ' ; i--) data[i]='\0'; + if (i<0) continue; + if (Stored+i+2>=MemSize) { + debuga(__FILE__,__LINE__,_("Too many codes to exclude in file \"%s\"\n"),ExcludeCodes); + break; + } + strcat(excludecode,data); + strcat(excludecode,";"); + Stored+=i+1; + } + + if (fclose(fp_in)==EOF) { + debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),ExcludeCodes,strerror(errno)); + exit(EXIT_FAILURE); + } + return; } void free_excludecodes(void) { - if (excludecode) { - free(excludecode); - excludecode=NULL; - } + if (excludecode) { + free(excludecode); + excludecode=NULL; + } } int vercode(const char *code) { - char *cod; - int clen; + char *cod; + int clen; - if (excludecode && excludecode[0]!='\0') { - clen=strlen(code); - cod=excludecode; - while (cod) { - if (strncmp(code,cod,clen)==0 && cod[clen]==';') - return 1; - cod=strchr(cod,';'); - if (cod) cod++; - } - } - return 0; + if (excludecode && excludecode[0]!='\0') { + clen=strlen(code); + cod=excludecode; + while (cod) { + if (strncmp(code,cod,clen)==0 && cod[clen]==';') + return 1; + cod=strchr(cod,';'); + if (cod) cod++; + } + } + return 0; } void fixnone(char *str) { - int i; + int i; - for (i=strlen(str)-1 ; i>=0 && (unsigned char)str[i]<=' ' ; i--); - if(i==3 && strncmp(str,"none",4) == 0) - str[0]='\0'; + for (i=strlen(str)-1 ; i>=0 && (unsigned char)str[i]<=' ' ; i--); + if(i==3 && strncmp(str,"none",4) == 0) + str[0]='\0'; - return; + return; } void fixendofline(char *str) { - int i; + int i; - for (i=strlen(str)-1 ; i>=0 && (unsigned char)str[i]<=' ' ; i--) str[i]=0; + for (i=strlen(str)-1 ; i>=0 && (unsigned char)str[i]<=' ' ; i--) str[i]=0; } #ifdef LEGACY_TESTVALIDUSERCHAR int testvaliduserchar(const char *user) { + int x=0; + int y=0; - int x=0; - int y=0; - - for (y=0; y *(int *)b ) return 1; - if( *(int *)a < *(int *)b ) return -1; - return 0; +{ + if( *(int *)a > *(int *)b ) return 1; + if( *(int *)a < *(int *)b ) return -1; + return 0; } int getnumlist( char *buf, numlist *list, const int len, const int maxvalue ) { - int i, j, d, flag, r1, r2; - char *pbuf, **bp, *strbufs[ 24 ]; - - bp = strbufs; - strtok( buf, " \t" ); - for( *bp = strtok( NULL, "," ), list->len = 0; *bp; *bp = strtok( NULL, "," ) ) { - if( ++bp >= &strbufs[ 24 ] ) - break; - list->len++; - } - if( ! list->len ) - return -1; - d = 0; - for( i = 0; i < list->len; i++ ) { - if( strchr( strbufs[ i ], '-' ) != 0 ) { - pbuf = strbufs[ i ]; - strtok( pbuf, "-" ); - pbuf = strtok( NULL, "\0" ); - r1 = atoi( strbufs[ i ] ); - if( ( r2 = atoi( pbuf ) ) >= maxvalue || r1 >= r2 ) - return -1; - if( i + d + ( r2 - r1 ) + 1 <= len ) { - for( j = r1; j <= r2; j++ ) - list->list[ i + d++ ] = j; - d--; - } - } - else - if( ( list->list[ i + d ] = atoi( strbufs[ i ] ) ) >= maxvalue ) - return 1; - } - list->len += d; - qsort( list->list, list->len, sizeof( int ), compar ); - do { - flag = 0; - for( i = 0; i < list->len - 1; i++ ) - if( list->list[ i ] == list->list[ i + 1 ] ) { - for( j = i + 1; j < list->len; j++ ) - list->list[ j - 1 ] = list->list[ j ]; - list->len--; - flag = 1; - break; - } - } while( flag ); - return 0; -} - - -char *get_size(const char *path, const char *file) -{ - FILE *fp; - static char response[255]; - char cmd[255]; - char *ptr; - - if (snprintf(cmd,sizeof(cmd),"du -skh %s%s",path,file)>=sizeof(cmd)) { - debuga(_("Cannot get disk space because the path %s%s is too long\n"),path,file); - exit(EXIT_FAILURE); - } - if ((fp = popen(cmd, "r")) == NULL) { - debuga(_("Cannot get disk space with command %s\n"),cmd); - exit(EXIT_FAILURE); - } - if (!fgets(response, sizeof(response), fp)) { - debuga(_("Cannot get disk size with command %s\n"),cmd); - exit(EXIT_FAILURE); - } - ptr=strchr(response,'\t'); - if (ptr==NULL) { - debuga(_("The command %s failed\n"),cmd); - exit(EXIT_FAILURE); - } - pclose(fp); - *ptr='\0'; - - return (response); + int i, j, d, flag, r1, r2; + char *pbuf, **bp, *strbufs[ 24 ]; + + bp = strbufs; + strtok( buf, " \t" ); + for( *bp = strtok( NULL, "," ), list->len = 0; *bp; *bp = strtok( NULL, "," ) ) { + if( ++bp >= &strbufs[ 24 ] ) + break; + list->len++; + } + if( ! list->len ) + return -1; + d = 0; + for( i = 0; i < list->len; i++ ) { + if( strchr( strbufs[ i ], '-' ) != 0 ) { + pbuf = strbufs[ i ]; + strtok( pbuf, "-" ); + pbuf = strtok( NULL, "\0" ); + r1 = atoi( strbufs[ i ] ); + if( ( r2 = atoi( pbuf ) ) >= maxvalue || r1 >= r2 ) + return -1; + if( i + d + ( r2 - r1 ) + 1 <= len ) { + for( j = r1; j <= r2; j++ ) + list->list[ i + d++ ] = j; + d--; + } + } + else + if( ( list->list[ i + d ] = atoi( strbufs[ i ] ) ) >= maxvalue ) + return 1; + } + list->len += d; + qsort( list->list, list->len, sizeof( int ), compar ); + do { + flag = 0; + for( i = 0; i < list->len - 1; i++ ) + if( list->list[ i ] == list->list[ i + 1 ] ) { + for( j = i + 1; j < list->len; j++ ) + list->list[ j - 1 ] = list->list[ j ]; + list->len--; + flag = 1; + break; + } + } while( flag ); + return 0; } void show_info(FILE *fp_ou) { - char ftime[127]; + char ftime[127]; - if(!ShowSargInfo) return; - zdate(ftime, sizeof(ftime), DateFormat); - fprintf(fp_ou,"
%s %s-%s %s %s
\n",_("Generated by"),URL,PGM,VERSION,_("on"),ftime); + if(!ShowSargInfo) return; + zdate(ftime, sizeof(ftime), df); + fputs("
",fp_ou); + fprintf(fp_ou,_("Generated by %s-%s on %s"),URL,PGM,VERSION,ftime); + fputs("
\n",fp_ou); } void show_sarg(FILE *fp_ou, int depth) { - int i; + int i; - if(!ShowSargLogo) return; - fputs("
\"Sarg\" Squid Analysis Report Generator
\n",fp_ou); + if(!ShowSargLogo) return; + fputs("
\"Sarg\" Squid Analysis Report Generator
\n",fp_ou); } void write_logo_image(FILE *fp_ou) { - if(LogoImage[0]!='\0') - fprintf(fp_ou, "
\"Logo\" %s
\n",LogoImage,Width,Height,LogoText); + if(LogoImage[0]!='\0') + fprintf(fp_ou, "
\"Logo\" %s
\n",LogoImage,Width,Height,LogoText); } void write_html_head(FILE *fp_ou, int depth, const char *page_title,int javascript) { - int i; + int i; - fputs("\n\n",fp_ou); - fprintf(fp_ou, "\n \n",CharSet); - if (page_title) fprintf(fp_ou,"%s\n",page_title); - css(fp_ou); - if ((javascript & HTML_JS_SORTTABLE)!=0 && SortTableJs[0]) { - fputs("\n",fp_ou); - } - fputs("\n\n",fp_ou); + fputs("\n\n",fp_ou); + fprintf(fp_ou, "\n \n",CharSet); + if (page_title) fprintf(fp_ou,"%s\n",page_title); + css(fp_ou); + if ((javascript & HTML_JS_SORTTABLE)!=0 && SortTableJs[0]) { + fputs("\n",fp_ou); + } + fputs("\n\n",fp_ou); } void write_html_header(FILE *fp_ou, int depth, const char *page_title,int javascript) { - write_html_head(fp_ou,depth,page_title,javascript); - write_logo_image(fp_ou); - show_sarg(fp_ou, depth); - fprintf(fp_ou,"
\n\n",Title); + write_html_head(fp_ou,depth,page_title,javascript); + write_logo_image(fp_ou); + show_sarg(fp_ou, depth); + fprintf(fp_ou,"
%s
\n\n",Title); } void close_html_header(FILE *fp_ou) { - fputs("
%s
\n",fp_ou); + fputs("\n",fp_ou); } -int write_html_trailer(FILE *fp_ou) +void write_html_trailer(FILE *fp_ou) { - show_info(fp_ou); - if (fputs("\n\n",fp_ou)==EOF) return(-1); - return(0); + show_info(fp_ou); + fputs("\n\n",fp_ou); } void output_html_string(FILE *fp_ou,const char *str,int maxlen) { - int i=0; - - while (*str && (maxlen<=0 || i': - fputs(">",fp_ou); - break; - case '"': - fputs(""",fp_ou); - break; - case '\'': - fputs("'",fp_ou); - break; - default: - fputc(*str,fp_ou); - } - str++; - i++; - } - if (maxlen>0 && i>=maxlen) - fputs("…",fp_ou); + int i=0; + + while (*str && (maxlen<=0 || i': + fputs(">",fp_ou); + break; + case '"': + fputs(""",fp_ou); + break; + case '\'': + fputs("'",fp_ou); + break; + default: + fputc(*str,fp_ou); + } + str++; + i++; + } + if (maxlen>0 && i>=maxlen) + fputs("…",fp_ou); } void output_html_url(FILE *fp_ou,const char *url) { - while (*url) { - if (*url=='&') - fputs("&",fp_ou); - else - fputc(*url,fp_ou); - url++; - } + while (*url) { + if (*url=='&') + fputs("&",fp_ou); + else + fputc(*url,fp_ou); + url++; + } } -void url_hostname(const char *url,char *hostname,int hostsize) -{ - int i; +/*! + Write a host name inside an A tag of a HTML file. If the host name starts + with a star, it is assumed to be an alias that cannot be put inside a link + so the A tag is not written around the host name. - hostsize--; - for (i=0 ; i",fp_ou); + output_html_string(fp_ou,url,100); + fputs("",fp_ou); + } } void url_module(const char *url, char *w2) { - int x, y; - char w[255]; - - y=0; - for(x=strlen(url)-1; x>=0; x--) { - if(url[x] == '/' || y>=sizeof(w)-1) break; - w[y++]=url[x]; - } - if (x<0) { - w2[0]='\0'; - return; - } - - x=0; - for(y=y-1; y>=0; y--) { - w2[x++]=w[y]; - } - w2[x]='\0'; -} - -void url_to_file(const char *url,char *file,int filesize) -{ - int i,skip; - - filesize--; - skip=0; - for(i=0; i=0; x--) { + if(url[x] == '/' || y>=sizeof(w)-1) break; + w[y++]=url[x]; + } + if (x<0) { + w2[0]='\0'; + return; + } + + x=0; + for(y=y-1; y>=0; y--) { + w2[x++]=w[y]; + } + w2[x]='\0'; +} + +/*! +Mangle an URL to produce a part that can be used as an anchor in +a html tag. + +\param url The URL to mangle. +\param anchor The buffer to write the mangled URL. +\param size The size of the buffer. +*/ +void url_to_anchor(const char *url,char *anchor,int size) +{ + int i,j; + bool skip; + + // find url end + for (i=0 ; url[i] && url[i]!='/' && url[i]!='?' ; i++); + i--; + if (i<=0) { + anchor[0]='\0'; + return; + } + + // only keep really safe characters + skip=false; + j=size-1; + anchor[j]='\0'; + while (j>0 && i>=0) + { + if(isalnum(url[i]) || url[i]=='-' || url[i]=='_' || url[i]=='.') { + anchor[--j]=url[i]; + skip=false; + } else { + if (!skip) anchor[--j]='_'; + skip=true; + } + i--; + } + if (j>0) + { + while ( anchor[j]) + { + *anchor=anchor[j]; + anchor++; + } + *anchor='\0'; + } } void version(void) { - printf(_("SARG Version: %s\n"),VERSION); - exit(EXIT_SUCCESS); + printf(_("SARG Version: %s\n"),VERSION); +#if defined(ENABLE_NLS) && defined(HAVE_LOCALE_H) + if (debug) { + printf(_("\nFor the translation to work, a valid message file should be copied to " + "\"%s//LC_MESSAGES/%s.mo\" where is derived from the effective locale.\n"),LOCALEDIR,PACKAGE_NAME); + if (CurrentLocale) { + printf(_("Currently effective locale is \"%s\".\n"),CurrentLocale); + } else { + printf(_("Locale is not set in the environment variable.\n")); + } + // TRANSLATORS: You may change this message to tell the reader that the language is correctly supported. + printf(_("If this message is in English, then your language is not supported or not correctly installed.\n")); + } +#endif + if (debug) { +#ifdef HAVE_GLOB_H + printf(_("File globbing compiled in.\n")); +#else + printf(_("File globbing NOT compiled in.\n")); +#endif + } + exit(EXIT_SUCCESS); } char *get_param_value(const char *param,char *line) { - int plen; - - while (*line==' ' || *line=='\t') line++; - plen=strlen(param); - if (strncasecmp(line,param,plen)) return(NULL); - if (line[plen]!=' ' && line[plen]!='\t') return(NULL); - line+=plen; - while (*line==' ' || *line=='\t') line++; - return(line); -} - -void unlinkdir(const char *dir,int contentonly) -{ - struct stat st; - DIR *dirp; - struct dirent *direntp; - char dname[MAXLEN]; - int err; - - dirp=opendir(dir); - if (!dirp) return; - while ((direntp = readdir(dirp)) != NULL) { - if (direntp->d_name[0] == '.' && (direntp->d_name[1] == '\0' || - (direntp->d_name[1] == '.' && direntp->d_name[2] == '\0'))) - continue; - if (snprintf(dname,sizeof(dname),"%s/%s",dir,direntp->d_name)>=sizeof(dname)) { - debuga(_("directory name to delete too long: %s/%s\n"),dir,direntp->d_name); - exit(EXIT_FAILURE); - } + int plen; + + while (*line==' ' || *line=='\t') line++; + plen=strlen(param); + if (strncasecmp(line,param,plen)) return(NULL); + if (line[plen]!=' ' && line[plen]!='\t') return(NULL); + line+=plen; + while (*line==' ' || *line=='\t') line++; + return(line); +} + +void unlinkdir(const char *dir,bool contentonly) +{ + struct stat st; + DIR *dirp; + struct dirent *direntp; + char dname[MAXLEN]; + int err; + + dirp=opendir(dir); + if (!dirp) return; + while ((direntp = readdir(dirp)) != NULL) { + if (direntp->d_name[0] == '.' && (direntp->d_name[1] == '\0' || + (direntp->d_name[1] == '.' && direntp->d_name[2] == '\0'))) + continue; + if (snprintf(dname,sizeof(dname),"%s/%s",dir,direntp->d_name)>=sizeof(dname)) { + debuga(__FILE__,__LINE__,_("Path too long: ")); + debuga_more("%s/%s\n",dir,direntp->d_name); + exit(EXIT_FAILURE); + } #ifdef HAVE_LSTAT - err=lstat(dname,&st); + err=lstat(dname,&st); #else - err=stat(dname,&st); + err=stat(dname,&st); #endif - if (err) { - debuga(_("cannot stat %s\n"),dname); - exit(EXIT_FAILURE); - } - if (S_ISREG(st.st_mode)) { - if (unlink(dname)) { - debuga(_("cannot delete %s - %s\n"),dname,strerror(errno)); - exit(EXIT_FAILURE); - } - } else if (S_ISDIR(st.st_mode)) { - unlinkdir(dname,0); - } else { - debuga(_("unknown path type %s\n"),dname); - } - } - closedir(dirp); - - if (!contentonly) { - if (rmdir(dir)) { - debuga(_("cannot delete %s - %s\n"),dir,strerror(errno)); - exit(EXIT_FAILURE); - } - } -} + if (err) { + debuga(__FILE__,__LINE__,_("Cannot stat \"%s\": %s\n"),dname,strerror(errno)); + exit(EXIT_FAILURE); + } + if (S_ISREG(st.st_mode)) { + if (unlink(dname)) { + debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),dname,strerror(errno)); + exit(EXIT_FAILURE); + } + } else if (S_ISDIR(st.st_mode)) { + unlinkdir(dname,0); + } else { + debuga(__FILE__,__LINE__,_("Don't know how to delete \"%s\" (not a regular file nor a directory)\n"),dname); + } + } + closedir(dirp); + + if (!contentonly) { + if (rmdir(dir)) { + debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),dir,strerror(errno)); + exit(EXIT_FAILURE); + } + } +} + +/*! +Delete every file from the temporary directory where sarg is told to store its +temporary files. + +As any stray file left over by a previous run would be included in the report, we +must delete every file from the temporary directory before we start processing the logs. + +But the temporary directory is given by the user either in the configuration file or +on the command line. We check that the user didn't give a wrong directory by looking +at the files stored in the directory. If a single file is not one of ours, we abort. + +\param dir The temporary directory to purge. +*/ +void emptytmpdir(const char *dir) +{ + struct stat st; + DIR *dirp; + struct dirent *direntp; + int dlen; + int elen; + char dname[MAXLEN]; + int err; + int i; + static const char *TmpExt[]= + { + ".int_unsort", + ".int_log", + ".day", + "htmlrel.txt", + ".user_unsort", + ".user_log", + ".utmp", + ".ip", + "lastlog1", + "lastlog", + "emailrep" + }; + + dirp=opendir(dir); + if (!dirp) return; + + // make sure the temporary directory contains only our files + while ((direntp = readdir(dirp)) != NULL) { + if (direntp->d_name[0] == '.' && (direntp->d_name[1] == '\0' || + (direntp->d_name[1] == '.' && direntp->d_name[2] == '\0'))) + continue; + + // is it one of our files + dlen=strlen(direntp->d_name); + for (i=sizeof(TmpExt)/sizeof(TmpExt[0])-1 ; i>=0 ; i--) { + elen=strlen(TmpExt[i]); + if (dlen>=elen && strcasecmp(direntp->d_name+dlen-elen,TmpExt[i])==0) break; + } + if (i<0) { + debuga(__FILE__,__LINE__,_("Unknown file \"%s\" found in temporary directory \"%s\". It is not one of our files. " + "Please check the temporary directory you gave to sarg. Adjust the path to a safe " + "directory or manually delete the content of \"%s\"\n"),direntp->d_name,dir,dir); + exit(EXIT_FAILURE); + } + + if (snprintf(dname,sizeof(dname),"%s/%s",dir,direntp->d_name)>=sizeof(dname)) { + debuga(__FILE__,__LINE__,_("Path too long: ")); + debuga_more("%s/%s\n",dir,direntp->d_name); + exit(EXIT_FAILURE); + } +#ifdef HAVE_LSTAT + err=lstat(dname,&st); +#else + err=stat(dname,&st); +#endif + if (err) { + debuga(__FILE__,__LINE__,_("Cannot stat \"%s\": %s\n"),dname,strerror(errno)); + exit(EXIT_FAILURE); + } + if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) { + debuga(__FILE__,__LINE__,_("Unknown path type for \"%s\". Check temporary directory\n"),dname); + exit(EXIT_FAILURE); + } + } + rewinddir(dirp); + + // now delete our files + while ((direntp = readdir(dirp)) != NULL) { + if (direntp->d_name[0] == '.' && (direntp->d_name[1] == '\0' || + (direntp->d_name[1] == '.' && direntp->d_name[2] == '\0'))) + continue; + + // is it one of our files + dlen=strlen(direntp->d_name); + for (i=sizeof(TmpExt)/sizeof(TmpExt[0])-1 ; i>=0 ; i--) { + elen=strlen(TmpExt[i]); + if (dlen>=elen && strcasecmp(direntp->d_name+dlen-elen,TmpExt[i])==0) break; + } + if (i<0) { + debuga(__FILE__,__LINE__,_("Unknown file \"%s\" found in temporary directory \"%s\". It is not one of our files. " + "Please check the temporary directory you gave to sarg. Adjust the path to a safe " + "directory or manually delete the content of \"%s\"\n"),direntp->d_name,dir,dir); + exit(EXIT_FAILURE); + } + + if (snprintf(dname,sizeof(dname),"%s/%s",dir,direntp->d_name)>=sizeof(dname)) { + debuga(__FILE__,__LINE__,_("Path too long: ")); + debuga_more("%s/%s\n",dir,direntp->d_name); + exit(EXIT_FAILURE); + } +#ifdef HAVE_LSTAT + err=lstat(dname,&st); +#else + err=stat(dname,&st); +#endif + if (err) { + debuga(__FILE__,__LINE__,_("Cannot stat \"%s\": %s\n"),dname,strerror(errno)); + exit(EXIT_FAILURE); + } + if (S_ISDIR(st.st_mode)) { + unlinkdir(dname,0); + } else if (S_ISREG(st.st_mode)) { + if (unlink(dname)) { + debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),dname,strerror(errno)); + exit(EXIT_FAILURE); + } + } else { + debuga(__FILE__,__LINE__,_("Don't know how to delete \"%s\" (not a regular file)\n"),dname); + } + } + closedir(dirp); +} + +/*! + Extract an url, IPv4 or IPv6 from a buffer. The IP addresses may end with a + prefix size. + + \param buf The buffer to parse. + \param text A pointer to set to the beginning of the string pattern. No terminating zero is inserted. + The pointer may be NULL. + \param ipv4 A 4 bytes buffer to store the bytes of the IPv4 address. + \param ipv6 A 8 short integers buffer to store the values of the IPv6 address. + \param nbits The number of prefix bits for an IP address. + \param next The content of the line after the extracted address. + + \retval 3 The pattern is a IPv6 address. + \retval 2 The pattern is a IPv4 address. + \retval 1 The patter is a string. + \retval 0 Empty pattern. + */ +int extract_address_mask(const char *buf,const char **text,unsigned char *ipv4,unsigned short int *ipv6,int *nbits,const char **next) +{ + int i; + int j; + int ip_size; + unsigned int value4, value6; + unsigned short int addr[8]; + int addr_len; + int nibble6_len; + int mask, max_mask; + int pad_pos; + int pad_len; + bool bracket=false; + bool port=false; + bool port_num=0; + + // skip leading spaces and tabs + while (*buf && (*buf==' ' || *buf=='\t')) buf++; + + // find out the nature of the pattern + ip_size=0x60 | 0x04; + if (*buf=='[') { + bracket=true; + ip_size=0x60; + buf++; + } + value4=0U; + value6=0U; + addr_len=0; + nibble6_len=0; + pad_pos=-1; + for (i=0 ; (unsigned char)buf[i]>' ' && buf[i]!='/' && buf[i]!='?' && (!bracket || buf[i]!=']') && ip_size ; i++) { + if (ip_size & 0x04) { + if (isdigit(buf[i])) { + if (port) { + port_num=port_num*10+(buf[i]-'0'); + if (port_num>65535) ip_size&=~0x04; + } else { + value4=value4*10+(buf[i]-'0'); + if (value4>0xFFU) ip_size&=~0x04; + } + } else if (buf[i]=='.' && addr_len<4) { + addr[addr_len++]=(unsigned short)(value4 & 0xFFU); + value4=0U; + } else if (!port && buf[i]==':') { + port=true; + } else { + ip_size&=~0x04; + } + } + if (ip_size & 0x60) { + if (isdigit(buf[i])) { + value6=(value6<<4)+(buf[i]-'0'); + nibble6_len++; + if (value6>0xFFFFU) ip_size&=~0x60; + } else if (toupper(buf[i])>='A' && toupper(buf[i])<='F') { + value6=(value6<<4)+(toupper(buf[i])-'A'+10); + nibble6_len++; + if (value6>0xFFFFU) ip_size&=~0x60; + } else if (buf[i]==':' && addr_len<8) { + if (nibble6_len>0) { + addr[addr_len++]=(unsigned short)(value6 & 0xFFFFU); + nibble6_len=0; + } + value6=0U; + if (buf[i+1]==':') { + pad_pos=addr_len; + i++; + } + } else { + ip_size&=~0x60; + } + } + } + if (i==0) return(0); + if (ip_size & 0x04) { + if (addr_len!=3) + ip_size&=~0x04; + else + addr[addr_len++]=(unsigned short)(value4 & 0xFFU); + } + if (ip_size & 0x60) { + if (pad_pos<0 && addr_len!=7) { + ip_size&=~0x60; + } else if (pad_pos>=0 && addr_len>=7) + ip_size&=~0x60; + else if (nibble6_len>0) + addr[addr_len++]=(unsigned short)(value6 & 0xFFFFU); + } + if (!ip_size) { + if (text) { + *text=buf; + if (bracket) (*text)--; + } + while ((unsigned char)buf[i]>' ') i++; + if (next) *next=buf+i; + return(1); + } + max_mask=(ip_size & 0x04) ? 4*8 : 8*16; + if (buf[i]=='/') { + i++; + mask=atoi(buf+i); + while (isdigit(buf[i])) i++; + if (mask<0 || mask>max_mask) mask=max_mask; + } else + mask=max_mask; + if (ip_size & 0x60 && bracket && buf[i]==']') i++; + if (next) *next=buf+i; + if (ip_size & 0x04) { + if (nbits) *nbits=mask; + for (i=0 ; i=0) { + while (i