X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=realtime.c;h=cf90e479d9c25842cd3ef53efc11eb9dccfede7e;hb=51f6da273beef37080bc9e6940aa5451fdae7664;hp=fe33c30251ff9648034e481516783da40ef0fce9;hpb=0e86563516f78b1e240d2d8fd57aad92447e46d6;p=thirdparty%2Fsarg.git diff --git a/realtime.c b/realtime.c old mode 100755 new mode 100644 index fe33c30..cf90e47 --- a/realtime.c +++ b/realtime.c @@ -1,10 +1,11 @@ /* - * AUTHOR: Pedro Lineu Orso orso@penguintech.com.br - * 1998, 2010 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net + * 1998, 2015 * * SARG donations: * please look at http://sarg.sourceforge.net/donations.php + * Support: + * http://sourceforge.net/projects/sarg/forums/forum/363374 * --------------------------------------------------------------------- * * This program is free software; you can redistribute it and/or modify @@ -25,232 +26,229 @@ #include "include/conf.h" #include "include/defs.h" +#include "include/filelist.h" +#include "include/readlog.h" -static int getdata(char*, FILE*); -static void datashow(const char *); -static void getlog(void); -static void header(void); +//! Maximum length of the scheme plus host name from the url. +#define MAX_URL_HOST_LEN 260 -char dat[128]; -char tim[128]; -char typ[128]; -char ouser[MAXLEN]=""; -char ourl[MAXLEN]=""; - -void realtime(void) +/*! +\brief Data read from an input log file. +*/ +struct RealtimeReadLogStruct { - - getlog(); - + //! The time corresponding to the entry. + struct tm EntryTime; + //! The IP address connecting to internet. + char Ip[48]; + //! The user's name. + char User[MAX_USER_LEN]; + /*! + The URL of the visited site. + + The pointer may be NULL if the URL doesn't exists in the log file. + */ + char Url[MAX_URL_HOST_LEN]; + //! HTTP method or NULL if the information is not stored in the log. + char HttpMethod[32]; +}; + +extern FileListObject AccessLog; + +static bool GetLatestModified(char *file_name,int file_name_size) +{ + FileListIterator FIter; + const char *file; + bool found=false; + struct stat st; + time_t latest; + + FIter=FileListIter_Open(AccessLog); + while ((file=FileListIter_Next(FIter))!=NULL) + { + if (stat(file,&st)==-1) { + debuga(__FILE__,__LINE__,_("Cannot stat \"%s\": %s\n"),file,strerror(errno)); + } + if (!found) + { + found=true; + latest=st.st_mtime; + safe_strcpy(file_name,file,file_name_size); + } + else if (st.st_mtime>latest) + { + latest=st.st_mtime; + safe_strcpy(file_name,file,file_name_size); + } + } + FileListIter_Close(FIter); + return(found); } -static void getlog(void) +/*! + * \brief Store a log entry. + * + * \param Dest A pointer to the list entry where to store the entry. + * \param Entry The entry to store. + */ +static void StoreLogEntry(struct RealtimeReadLogStruct *Dest,struct ReadLogStruct *Entry) { - FILE *tmp, *fp; - char template1[255]="/var/tmp/sargtpl1.XXXXXX"; - char template2[255]="/var/tmp/sargtpl2.XXXXXX"; - char cmd[512]; - char buf[MAXLEN]; - int fd1,fd2; - int cstatus; - - init_usertab(UserTabFile); - - fd1 = mkstemp(template1); - fd2 = mkstemp(template2); - - if((fd1 == -1 ) || ((tmp = fdopen (fd1, "w+" )) == NULL) ) { /* failure, bail out */ - fprintf(stderr, "SARG: (realtime) mkstemp error - %s\n",strerror(errno)); - exit(1); - } - - sprintf(cmd,"tail -%d %s",realtime_access_log_lines,AccessLog[0]); - fp = popen(cmd, "r"); - while(fgets(buf,sizeof(buf),fp) != NULL ) - if (getdata(buf,tmp)<0) { - fprintf(stderr,"SARG: Maybe a broken record or garbage was returned by %s.\n",cmd); - exit(1); - } - pclose(fp); - fclose(tmp); - - sprintf(cmd,"sort -r -k 1,1 -k 2,2 -o \"%s\" \"%s\"",template2,template1); - cstatus=system(cmd); - if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) { - fprintf(stderr, "SARG: sort command return status %d\n",WEXITSTATUS(cstatus)); - fprintf(stderr, "SARG: sort command: %s\n",cmd); - exit(1); - } - unlink(template1); - datashow(template2); + memcpy(&Dest->EntryTime,&Entry->EntryTime,sizeof(Dest->EntryTime)); + safe_strcpy(Dest->Ip,Entry->Ip,sizeof(Dest->Ip)); + if (Entry->Url) + { + int i; + const char *url=Entry->Url; + + // skip the scheme + for (i=0 ; i<8 && url[i] && (isalnum(url[i]) || url[i]=='+' || url[i]=='-' || url[i]=='.') ; i++); + if (url[i]==':' && url[i+1]=='/' && url[i+2]=='/') + { + url+=i+3; + for (i=0 ; url[i] && url[i]!='/' ; i++); + } + if (i>=sizeof(Dest->Url)) i=sizeof(Dest->Url)-1; + strncpy(Dest->Url,url,i); + Dest->Url[i]='\0'; + } + safe_strcpy(Dest->User,Entry->User,sizeof(Dest->User)); + safe_strcpy(Dest->HttpMethod,Entry->HttpMethod,sizeof(Dest->HttpMethod)); } -static int getdata(char *rec, FILE *ftmp) +static void header(void) { - time_t tt; - struct tm *t; - char tbuf[128]; - char warea[MAXLEN]; - struct getwordstruct gwarea; - - getword_start(&gwarea,rec); - if (getword(dat,sizeof(dat),&gwarea,' ')<0) { - fprintf(stderr,"SARG: The time stamp at column 1 is too long.\n"); - return(-1); - } - if (getword(warea,sizeof(warea),&gwarea,' ')<0) { - fprintf(stderr,"SARG: The connection duration at column 2 is too long.\n"); - return(-1); - } - while(strcmp(warea,"") == 0 && gwarea.current[0] != '\0') - if (getword(warea,sizeof(warea),&gwarea,' ')<0) { - return(-1); - } - if (getword(ip,sizeof(ip),&gwarea,' ')<0) { - fprintf(stderr,"SARG: The IP address at column 3 is too long.\n"); - return(-1); - } - if (getword_skip(MAXLEN,&gwarea,' ')<0) { - fprintf(stderr,"SARG: The status at column 4 is too long.\n"); - return(-1); - } - if (getword_skip(MAXLEN,&gwarea,' ')<0) { - fprintf(stderr,"SARG: The size at column 5 is too long.\n"); - return(-1); - } - if (getword(typ,sizeof(typ),&gwarea,' ')<0) { - fprintf(stderr,"SARG: The action at column 6 is too long.\n"); - return(-1); - } - if(strncmp(typ,"CONNECT",7) == 0) { - if (getword(url,sizeof(url),&gwarea,' ')<0) { - return(-1); - } - if (getword(user,sizeof(user),&gwarea,' ')<0) { - return(-1); - } - }else { - if (getword_skip(MAXLEN,&gwarea,'/')<0) { - fprintf(stderr,"SARG: The URL at column 7 is too long.\n"); - return(-1); - } - if (getword_skip(MAXLEN,&gwarea,'/')<0) { - fprintf(stderr,"SARG: The URL at column 7 is too long.\n"); - return(-1); - } - if (getword(url,sizeof(url),&gwarea,'/')<0) { - fprintf(stderr,"SARG: The URL at column 7 is too long.\n"); - return(-1); - } - if (getword_skip(MAXLEN,&gwarea,' ')<0) { - fprintf(stderr,"SARG: The data at column 8 is too long.\n"); - return(-1); - } - if (getword(user,sizeof(user),&gwarea,' ')<0) { - fprintf(stderr,"SARG: The user at column 9 is too long.\n"); - return(-1); - } - } - - if(strncmp(user,"-",1) == 0 && strcmp(RealtimeUnauthRec,"ignore") == 0) - return(0); - - tt=atoi(dat); - t=localtime(&tt); - if(strncmp(DateFormat,"u",1) == 0) - strftime(tbuf, sizeof(tbuf), "%Y-%m-%d\t%H:%M", t); - else if(strncmp(DateFormat,"e",1) == 0) - strftime(tbuf, sizeof(tbuf), "%d-%m-%Y\t%H:%M", t); - - fprintf(ftmp,"%s\t%s\t%s\t%s\t%s\n",tbuf,ip,user,url,typ); - return(0); + puts("\n"); + puts("\n"); + puts("\n"); + if(realtime_refresh) + printf(" \n",realtime_refresh,CharSet); + else + printf(" \n",CharSet); + css(stdout); + puts("\n"); + printf("\n",FontFace,TitleFontSize,BgColor,BgImage); + puts("
\n"); + printf("\n",_("Realtime")); + printf("\n",_("Auto refresh"),realtime_refresh); + printf("\n",_("DATE/TIME"),_("IP/NAME"),_("USERID"),_("TYPE"),_("ACCESSED SITE")); } -static void datashow(const char *tmp) +static void datashow(struct RealtimeReadLogStruct *List,int Index,int Size) { - FILE *fin; - char buf[MAXLEN]; - struct getwordstruct gwarea; - - if((fin=fopen(tmp,"r"))==NULL) { - fprintf(stderr, "SARG: (realtime) open error %s - %s\n",tmp,strerror(errno)); - exit(1); - } - - header(); - - while(fgets(buf, sizeof(buf), fin)) { - fixendofline(buf); - getword_start(&gwarea,buf); - if (getword(dat,sizeof(dat),&gwarea,'\t')<0) { - printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",tmp); - exit(1); - } - if (getword(tim,sizeof(tim),&gwarea,'\t')<0) { - printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",tmp); - exit(1); - } - if (getword(ip,sizeof(ip),&gwarea,'\t')<0) { - printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",tmp); - exit(1); - } - if (getword(user,sizeof(user),&gwarea,'\t')<0) { - printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",tmp); - exit(1); - } - if(strlen(dat) < 3 || strlen(user) < 1) continue; - if (getword(url,sizeof(url),&gwarea,'\t')<0) { - printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",tmp); - exit(1); - } - if (getword(typ,sizeof(typ),&gwarea,'\t')<0) { - printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",tmp); - exit(1); - } - if(strstr(RealtimeTypes,typ) == 0) - continue; - - if(strcmp(ouser,user) == 0 && strcmp(ourl,url) == 0) - continue; - - if(userip) - strcpy(user,ip); - strcpy(u2,user); - if(Ip2Name) - ip2name(u2,sizeof(u2)); - user_find(name, sizeof(name), u2); - - if(dotinuser && strchr(name,'_')) { - subs(name,sizeof(name),"_","."); - } - - printf("\n",dat,tim,ip,name,typ,url,url); - strcpy(ouser,user); - strcpy(ourl,url); - } - - puts("
SARG %s
%s: %d s
%s%s%s%s%s
%s %s%s%s%s%s
\n
\n\n\n"); - fclose(fin); - unlink(tmp); - fflush(NULL); - + char tbuf[128]; + char user[MAX_USER_LEN]; + char name[MAX_USER_LEN]; + int i; + struct RealtimeReadLogStruct *entry; + + header(); + for (i=0 ; iIp); + else + strcpy(user,entry->User); + if(Ip2Name) + ip2name(user,sizeof(user)); + user_find(name, sizeof(name), user); + + if (df=='u') + strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M", &entry->EntryTime); + else if (df=='e') + strftime(tbuf, sizeof(tbuf), "%d-%m-%Y %H:%M", &entry->EntryTime); + + printf("%s%s%s%s%s\n", + tbuf,entry->Ip,name,entry->HttpMethod,entry->Url,entry->Url); + } + + puts("\n\n\n\n"); + fflush(NULL); } -static void header(void) +void realtime(void) { - puts("\n"); - puts("\n"); - puts("\n"); - if(realtime_refresh) - printf(" \n",realtime_refresh,CharSet); - else - printf(" \n",CharSet); - css(stdout); - puts("\n"); - printf(buf,"\n",FontFace,TitleFontSize,BgColor,BgImage); - puts("
\n"); - printf("\n",text[134]); - printf("\n",text[136],realtime_refresh); - printf("\n",text[110],text[111],text[98],text[135],text[91]); + FileObject *fp; + char file_name[2048]; + char *buf; + longline line; + struct ReadLogStruct log_entry; + enum ReadLogReturnCodeEnum log_entry_status; + struct LogLineStruct log_line; + struct RealtimeReadLogStruct *StoredLogEntries; + int StoreIndex=0; + int StoreSize=0; + int NextIndex=1; + + init_usertab(UserTabFile); + LogLine_Init(&log_line); + + /* + * Store one more entry to prepare the memory structure in place and reject it if + * it is about the same user and url as the last stored one. + */ + StoredLogEntries=calloc(realtime_access_log_lines+1,sizeof(struct RealtimeReadLogStruct)); + if (!StoredLogEntries) + { + debuga(__FILE__,__LINE__,_("Not enough memory to store %d records"),realtime_access_log_lines); + exit(EXIT_FAILURE); + } + /* + * Clear the url and user strings so that strcmp on the user and url are not + * satisfied and the first entry can be stored. + */ + memset(StoredLogEntries,0,sizeof(struct RealtimeReadLogStruct)); + + if (!GetLatestModified(file_name,sizeof(file_name))) + { + debuga(__FILE__,__LINE__,_("No log file to read the last %d lines from\n"),realtime_access_log_lines); + exit(EXIT_FAILURE); + } + fp = FileObject_Open(file_name); + if (!fp) { + debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),file_name,FileObject_GetLastOpenError()); + exit(EXIT_FAILURE); + } + + if ((line=longline_create())==NULL) { + debuga(__FILE__,__LINE__,_("Not enough memory to read file \"%s\"\n"),file_name); + exit(EXIT_FAILURE); + } + + while((buf=longline_read(fp,line)) != NULL ) + { + log_entry_status=LogLine_Parse(&log_line,&log_entry,buf); + if (log_entry_status==RLRC_Unknown) + { + continue; + } + if (log_entry_status==RLRC_Ignore) + { + continue; + } + if (log_entry.HttpMethod && strstr(RealtimeTypes,log_entry.HttpMethod)==0) + continue; + if (RealtimeUnauthRec==REALTIME_UNAUTH_REC_IGNORE && log_entry.User[0]=='-' && log_entry.User[1]=='\0') + continue; + StoreLogEntry(StoredLogEntries+NextIndex,&log_entry); + if (strcmp(StoredLogEntries[StoreIndex].User,StoredLogEntries[NextIndex].User)==0 && strcmp(StoredLogEntries[StoreIndex].Url,StoredLogEntries[NextIndex].Url)==0) + continue; + + StoreIndex=NextIndex; + NextIndex++; + if (NextIndex>StoreSize) StoreSize=NextIndex; + if (NextIndex>realtime_access_log_lines) NextIndex=0; + } + if (FileObject_Close(fp)) { + debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),file_name,FileObject_GetLastCloseError()); + exit(EXIT_FAILURE); + } + longline_destroy(&line); + + datashow(StoredLogEntries,StoreIndex,StoreSize); + free(StoredLogEntries); }
SARG %s
%s: %d s
%s%s%s%s%s