]> git.ipfire.org Git - thirdparty/sarg.git/blame - realtime.c
Add support to decompress xz files
[thirdparty/sarg.git] / realtime.c
CommitLineData
d5c1b1c1 1/*
d5c1b1c1 2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
110ce984 3 * 1998, 2015
d5c1b1c1
GS
4 *
5 * SARG donations:
6 * please look at http://sarg.sourceforge.net/donations.php
1164c474
FM
7 * Support:
8 * http://sourceforge.net/projects/sarg/forums/forum/363374
d5c1b1c1
GS
9 * ---------------------------------------------------------------------
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
24 *
25 */
26
27#include "include/conf.h"
5f3cfd1d 28#include "include/defs.h"
6068ae56 29#include "include/filelist.h"
8b4e9578 30#include "include/readlog.h"
6068ae56 31
8b4e9578
FM
32//! Maximum length of the scheme plus host name from the url.
33#define MAX_URL_HOST_LEN 260
d5c1b1c1 34
8b4e9578
FM
35/*!
36\brief Data read from an input log file.
37*/
38struct RealtimeReadLogStruct
d5c1b1c1 39{
8b4e9578
FM
40 //! The time corresponding to the entry.
41 struct tm EntryTime;
42 //! The IP address connecting to internet.
43 char Ip[48];
44 //! The user's name.
45 char User[MAX_USER_LEN];
46 /*!
47 The URL of the visited site.
48
49 The pointer may be NULL if the URL doesn't exists in the log file.
50 */
51 char Url[MAX_URL_HOST_LEN];
52 //! HTTP method or NULL if the information is not stored in the log.
53 char HttpMethod[32];
54};
55
56extern FileListObject AccessLog;
d5c1b1c1 57
8b4e9578 58static bool GetLatestModified(char *file_name,int file_name_size)
d5c1b1c1 59{
6068ae56 60 FileListIterator FIter;
8b4e9578
FM
61 const char *file;
62 bool found=false;
63 struct stat st;
64 time_t latest;
ac422f9b 65
6068ae56 66 FIter=FileListIter_Open(AccessLog);
8b4e9578
FM
67 while ((file=FileListIter_Next(FIter))!=NULL)
68 {
69 if (stat(file,&st)==-1) {
af961877 70 debuga(__FILE__,__LINE__,_("Cannot stat \"%s\": %s\n"),file,strerror(errno));
8b4e9578
FM
71 }
72 if (!found)
73 {
74 found=true;
75 latest=st.st_mtime;
76 safe_strcpy(file_name,file,file_name_size);
77 }
78 else if (st.st_mtime>latest)
79 {
80 latest=st.st_mtime;
81 safe_strcpy(file_name,file,file_name_size);
82 }
9bd92830 83 }
6068ae56 84 FileListIter_Close(FIter);
8b4e9578
FM
85 return(found);
86}
d5c1b1c1 87
8b4e9578
FM
88/*!
89 * \brief Store a log entry.
90 *
91 * \param Dest A pointer to the list entry where to store the entry.
92 * \param Entry The entry to store.
93 */
94static void StoreLogEntry(struct RealtimeReadLogStruct *Dest,struct ReadLogStruct *Entry)
95{
96 memcpy(&Dest->EntryTime,&Entry->EntryTime,sizeof(Dest->EntryTime));
97 safe_strcpy(Dest->Ip,Entry->Ip,sizeof(Dest->Ip));
98 if (Entry->Url)
99 {
100 int i;
101 const char *url=Entry->Url;
102
103 // skip the scheme
104 for (i=0 ; i<8 && url[i] && (isalnum(url[i]) || url[i]=='+' || url[i]=='-' || url[i]=='.') ; i++);
105 if (url[i]==':' && url[i+1]=='/' && url[i+2]=='/')
106 {
107 url+=i+3;
108 for (i=0 ; url[i] && url[i]!='/' ; i++);
109 }
110 if (i>=sizeof(Dest->Url)) i=sizeof(Dest->Url)-1;
111 strncpy(Dest->Url,url,i);
112 Dest->Url[i]='\0';
08f9b029 113 }
8b4e9578
FM
114 safe_strcpy(Dest->User,Entry->User,sizeof(Dest->User));
115 safe_strcpy(Dest->HttpMethod,Entry->HttpMethod,sizeof(Dest->HttpMethod));
d5c1b1c1
GS
116}
117
8b4e9578 118static void header(void)
d5c1b1c1 119{
8b4e9578
FM
120 puts("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"");
121 puts(" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
122 puts("<html>\n");
123 puts("<head>\n");
124 if(realtime_refresh)
125 printf(" <meta http-equiv=refresh content=\"%d\" url=\"sarg-php/sarg-realtime.php\"; charset=\"%s\">\n",realtime_refresh,CharSet);
126 else
127 printf(" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n",CharSet);
128 css(stdout);
129 puts("</head>\n");
130 printf("<body style=\"font-family:%s;font-size:%s;background-color:%s;background-image:url(%s)\">\n",FontFace,TitleFontSize,BgColor,BgImage);
131 puts("<div align=\"center\"><table cellpadding=\"1\" cellspacing=\"1\">\n");
132 printf("<tr><th class=\"title_l\" colspan=\"10\">SARG %s</th></tr>\n",_("Realtime"));
133 printf("<tr><th class=\"text\" colspan=\"10\">%s: %d s</th></tr>\n",_("Auto refresh"),realtime_refresh);
134 printf("<tr><th class=\"header_c\">%s</th><th class=\"header_c\">%s</th><th class=\"header_c\">%s</th><th class=\"header_c\">%s</th><th class=\"header_l\">%s</th></tr>\n",_("DATE/TIME"),_("IP/NAME"),_("USERID"),_("TYPE"),_("ACCESSED SITE"));
135}
136
137static void datashow(struct RealtimeReadLogStruct *List,int Index,int Size)
138{
139 char tbuf[128];
9bd92830 140 char user[MAX_USER_LEN];
8b4e9578
FM
141 char name[MAX_USER_LEN];
142 int i;
143 struct RealtimeReadLogStruct *entry;
d5c1b1c1 144
8b4e9578
FM
145 header();
146 for (i=0 ; i<realtime_access_log_lines ; i++)
147 {
148 entry=List+Index;
149 Index--;
150 if (Index<0) Index=Size-1;
151
152 if (UserIp)
153 strcpy(user,entry->Ip);
154 else
155 strcpy(user,entry->User);
156 if(Ip2Name)
157 ip2name(user,sizeof(user));
158 user_find(name, sizeof(name), user);
d5c1b1c1 159
8b4e9578
FM
160 if (df=='u')
161 strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M", &entry->EntryTime);
162 else if (df=='e')
163 strftime(tbuf, sizeof(tbuf), "%d-%m-%Y %H:%M", &entry->EntryTime);
d5c1b1c1 164
8b4e9578
FM
165 printf("<tr><td class=\"data\">%s</td><td class=\"data3\">%s</td><td class=\"data3\">%s</td><td class=\"data3\">%s</td><td class=\"data2\"><a href=\"http://%s\">%s</td></tr>\n",
166 tbuf,entry->Ip,name,entry->HttpMethod,entry->Url,entry->Url);
167 }
168
169 puts("</table>\n</div>\n</body>\n</html>\n");
170 fflush(NULL);
d5c1b1c1
GS
171}
172
8b4e9578 173void realtime(void)
d5c1b1c1 174{
800eafb8 175 FileObject *fp;
8b4e9578 176 char file_name[2048];
9bd92830 177 char *buf;
9bd92830 178 longline line;
8b4e9578
FM
179 struct ReadLogStruct log_entry;
180 enum ReadLogReturnCodeEnum log_entry_status;
181 struct LogLineStruct log_line;
182 struct RealtimeReadLogStruct *StoredLogEntries;
183 int StoreIndex=0;
184 int StoreSize=0;
185 int NextIndex=1;
d5c1b1c1 186
8b4e9578
FM
187 init_usertab(UserTabFile);
188 LogLine_Init(&log_line);
e5b2c6f0 189
8b4e9578
FM
190 /*
191 * Store one more entry to prepare the memory structure in place and reject it if
192 * it is about the same user and url as the last stored one.
193 */
194 StoredLogEntries=calloc(realtime_access_log_lines+1,sizeof(struct RealtimeReadLogStruct));
195 if (!StoredLogEntries)
196 {
af961877 197 debuga(__FILE__,__LINE__,_("Not enough memory to store %d records"),realtime_access_log_lines);
8b4e9578
FM
198 exit(EXIT_FAILURE);
199 }
200 /*
201 * Clear the url and user strings so that strcmp on the user and url are not
202 * satisfied and the first entry can be stored.
203 */
204 memset(StoredLogEntries,0,sizeof(struct RealtimeReadLogStruct));
205
206 if (!GetLatestModified(file_name,sizeof(file_name)))
207 {
af961877 208 debuga(__FILE__,__LINE__,_("No log file to read the last %d lines from\n"),realtime_access_log_lines);
8b4e9578
FM
209 exit(EXIT_FAILURE);
210 }
800eafb8 211 fp = FileObject_Open(file_name);
8b4e9578 212 if (!fp) {
800eafb8 213 debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),file_name,FileObject_GetLastOpenError());
8b4e9578
FM
214 exit(EXIT_FAILURE);
215 }
720f3529
FM
216
217 if ((line=longline_create())==NULL) {
af961877 218 debuga(__FILE__,__LINE__,_("Not enough memory to read file \"%s\"\n"),file_name);
720f3529
FM
219 exit(EXIT_FAILURE);
220 }
221
8b4e9578
FM
222 while((buf=longline_read(fp,line)) != NULL )
223 {
224 log_entry_status=LogLine_Parse(&log_line,&log_entry,buf);
225 if (log_entry_status==RLRC_Unknown)
226 {
227 continue;
9bd92830 228 }
8b4e9578
FM
229 if (log_entry_status==RLRC_Ignore)
230 {
231 continue;
9bd92830 232 }
8b4e9578 233 if (log_entry.HttpMethod && strstr(RealtimeTypes,log_entry.HttpMethod)==0)
9bd92830 234 continue;
8b4e9578
FM
235 if (RealtimeUnauthRec==REALTIME_UNAUTH_REC_IGNORE && log_entry.User[0]=='-' && log_entry.User[1]=='\0')
236 continue;
237 StoreLogEntry(StoredLogEntries+NextIndex,&log_entry);
238 if (strcmp(StoredLogEntries[StoreIndex].User,StoredLogEntries[NextIndex].User)==0 && strcmp(StoredLogEntries[StoreIndex].Url,StoredLogEntries[NextIndex].Url)==0)
9bd92830 239 continue;
d6e703cc 240
8b4e9578
FM
241 StoreIndex=NextIndex;
242 NextIndex++;
243 if (NextIndex>StoreSize) StoreSize=NextIndex;
244 if (NextIndex>realtime_access_log_lines) NextIndex=0;
9bd92830 245 }
800eafb8
FM
246 if (FileObject_Close(fp)) {
247 debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),file_name,FileObject_GetLastCloseError());
204781f4
FM
248 exit(EXIT_FAILURE);
249 }
9bd92830 250 longline_destroy(&line);
d5c1b1c1 251
8b4e9578
FM
252 datashow(StoredLogEntries,StoreIndex,StoreSize);
253 free(StoredLogEntries);
d5c1b1c1 254}