]> git.ipfire.org Git - thirdparty/sarg.git/blame - realtime.c
Fix empty user reports
[thirdparty/sarg.git] / realtime.c
CommitLineData
d5c1b1c1 1/*
d5c1b1c1 2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
1164c474 3 * 1998, 2010
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"
d5c1b1c1 29
120d768c
FM
30static int getdata(char*, FILE*);
31static void datashow(const char *);
32e71fa4
FM
32static void getlog(void);
33static void header(void);
d5c1b1c1 34
32e71fa4 35void realtime(void)
d5c1b1c1 36{
9bd92830 37 getlog();
d5c1b1c1
GS
38}
39
32e71fa4 40static void getlog(void)
d5c1b1c1 41{
9bd92830
FM
42 FILE *tmp, *fp;
43 char template1[255]="/var/tmp/sargtpl1.XXXXXX";
44 char template2[255]="/var/tmp/sargtpl2.XXXXXX";
45 char cmd[512];
46 char *buf;
47 int fd1,fd2;
48 int cstatus;
49 longline line;
d6e703cc 50
9bd92830 51 init_usertab(UserTabFile);
d5c1b1c1 52
9bd92830
FM
53 fd1 = mkstemp(template1);
54 fd2 = mkstemp(template2);
d5c1b1c1 55
9bd92830
FM
56 if((fd1 == -1 ) || ((tmp = fdopen (fd1, "w+" )) == NULL) ) { /* failure, bail out */
57 debuga(_("(realtime) mkstemp error - %s\n"),strerror(errno));
58 exit(EXIT_FAILURE);
59 }
d5c1b1c1 60
9bd92830
FM
61 if ((line=longline_create())==NULL) {
62 debuga(_("Not enough memory to read the log file\n"));
63 exit(EXIT_FAILURE);
64 }
ac422f9b 65
9bd92830
FM
66 sprintf(cmd,"tail -%d \"%s\"",realtime_access_log_lines,AccessLog[0]);
67 fp = popen(cmd, "r");
68 if (!fp) {
69 debuga(_("Failed to get the %d trailing lines of %s: %s\n"),realtime_access_log_lines,AccessLog[0],strerror(errno));
70 debuga(_("tail command: %s\n"),cmd);
71 exit(EXIT_FAILURE);
72 }
73 while((buf=longline_read(fp,line)) != NULL )
74 if (getdata(buf,tmp)<0) {
75 debuga(_("Maybe a broken record or garbage was returned by %s\n"),cmd);
76 exit(EXIT_FAILURE);
77 }
78 pclose(fp);
79 fclose(tmp);
80 longline_destroy(&line);
d5c1b1c1 81
9bd92830
FM
82 sprintf(cmd,"sort -r -k 1,1 -k 2,2 -o \"%s\" \"%s\"",template2,template1);
83 cstatus=system(cmd);
84 if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
85 debuga(_("sort command return status %d\n"),WEXITSTATUS(cstatus));
86 debuga(_("sort command: %s\n"),cmd);
87 exit(EXIT_FAILURE);
88 }
08f9b029
FM
89 if (unlink(template1)) {
90 debuga(_("Cannot delete %s - %s\n"),template1,strerror(errno));
91 exit(EXIT_FAILURE);
92 }
9bd92830 93 datashow(template2);
d5c1b1c1
GS
94}
95
120d768c 96static int getdata(char *rec, FILE *ftmp)
d5c1b1c1 97{
9bd92830
FM
98 time_t tt;
99 struct tm *t;
100 char dat[128];
101 char tbuf[128];
102 char typ[128];
103 char warea[MAXLEN];
104 char user[MAX_USER_LEN];
105 char ip[25];
106 char *url;
107 struct getwordstruct gwarea;
d5c1b1c1 108
9bd92830
FM
109 getword_start(&gwarea,rec);
110 if (getword(dat,sizeof(dat),&gwarea,' ')<0) {
111 debuga(_("The time stamp at column 1 is too long\n"));
112 return(-1);
113 }
114 if (getword(warea,sizeof(warea),&gwarea,' ')<0) {
115 debuga(_("The connection duration at column 2 is too long\n"));
116 return(-1);
117 }
118 while(strcmp(warea,"") == 0 && gwarea.current[0] != '\0')
119 if (getword(warea,sizeof(warea),&gwarea,' ')<0) {
120 return(-1);
121 }
122 if (getword(ip,sizeof(ip),&gwarea,' ')<0) {
123 debuga(_("The IP address at column 3 is too long\n"));
124 return(-1);
125 }
126 if (getword_skip(MAXLEN,&gwarea,' ')<0) {
127 debuga(_("The status at column 4 is too long\n"));
128 return(-1);
129 }
130 if (getword_skip(MAXLEN,&gwarea,' ')<0) {
131 debuga(_("The size at column 5 is too long\n"));
132 return(-1);
133 }
134 if (getword(typ,sizeof(typ),&gwarea,' ')<0) {
135 debuga(_("The action at column 6 is too long\n"));
136 return(-1);
137 }
138 if(strncmp(typ,"CONNECT",7) == 0) {
139 if (getword_ptr(rec,&url,&gwarea,' ')<0) {
140 debuga(_("The URL at column 7 is too long\n"));
141 return(-1);
142 }
143 if (getword(user,sizeof(user),&gwarea,' ')<0) {
144 debuga(_("The user ID at column 8 is too long\n"));
145 return(-1);
146 }
147 }else {
148 if (getword_skip(MAXLEN,&gwarea,'/')<0) {
149 debuga(_("The URL at column 7 is too long\n"));
150 return(-1);
151 }
152 if (getword_skip(MAXLEN,&gwarea,'/')<0) {
153 debuga(_("The URL at column 7 is too long\n"));
154 return(-1);
155 }
156 if (getword_ptr(rec,&url,&gwarea,'/')<0) {
157 debuga(_("The URL at column 7 is too long\n"));
158 return(-1);
159 }
160 if (getword_skip(MAXLEN,&gwarea,' ')<0) {
161 debuga(_("The data at column 8 is too long\n"));
162 return(-1);
163 }
164 if (getword(user,sizeof(user),&gwarea,' ')<0) {
165 debuga(_("The user at column 9 is too long\n"));
166 return(-1);
167 }
168 }
d5c1b1c1 169
9bd92830
FM
170 if(strncmp(user,"-",1) == 0 && RealtimeUnauthRec==REALTIME_UNAUTH_REC_IGNORE)
171 return(0);
d5c1b1c1 172
9bd92830
FM
173 tt=atoi(dat);
174 t=localtime(&tt);
175 if(strncmp(DateFormat,"u",1) == 0)
176 strftime(tbuf, sizeof(tbuf), "%Y-%m-%d\t%H:%M", t);
177 else if(strncmp(DateFormat,"e",1) == 0)
178 strftime(tbuf, sizeof(tbuf), "%d-%m-%Y\t%H:%M", t);
d5c1b1c1 179
9bd92830
FM
180 fprintf(ftmp,"%s\t%s\t%s\t%s\t%s\n",tbuf,ip,user,url,typ);
181 return(0);
d5c1b1c1
GS
182}
183
120d768c 184static void datashow(const char *tmp)
d5c1b1c1 185{
9bd92830
FM
186 FILE *fin;
187 char dat[128];
188 char tim[128];
189 char *buf;
190 char *url;
191 char *ourl=NULL;
192 char ouser[MAX_USER_LEN]="";
193 char typ[128];
194 char user[MAX_USER_LEN];
195 char u2[MAX_USER_LEN];
196 char ip[25];
197 int url_len;
198 int ourl_size=0;
199 struct getwordstruct gwarea;
200 longline line;
d5c1b1c1 201
9bd92830
FM
202 if((fin=fopen(tmp,"r"))==NULL) {
203 debuga(_("(realtime) open error %s - %s\n"),tmp,strerror(errno));
204 exit(EXIT_FAILURE);
205 }
d5c1b1c1 206
9bd92830 207 header();
e5b2c6f0 208
9bd92830
FM
209 if ((line=longline_create())==NULL) {
210 debuga(_("Not enough memory to read the log file\n"));
211 exit(EXIT_FAILURE);
212 }
d5c1b1c1 213
9bd92830
FM
214 while((buf=longline_read(fin,line))!=NULL) {
215 fixendofline(buf);
216 getword_start(&gwarea,buf);
217 if (getword(dat,sizeof(dat),&gwarea,'\t')<0) {
218 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),tmp);
219 exit(EXIT_FAILURE);
220 }
221 if (getword(tim,sizeof(tim),&gwarea,'\t')<0) {
222 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),tmp);
223 exit(EXIT_FAILURE);
224 }
225 if (getword(ip,sizeof(ip),&gwarea,'\t')<0) {
226 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),tmp);
227 exit(EXIT_FAILURE);
228 }
229 if (getword(user,sizeof(user),&gwarea,'\t')<0) {
230 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),tmp);
231 exit(EXIT_FAILURE);
232 }
233 if(strlen(dat) < 3 || strlen(user) < 1) continue;
234 if (getword_ptr(buf,&url,&gwarea,'\t')<0) {
235 debuga(_("Maybe you have a broken url in your %s file\n"),tmp);
236 exit(EXIT_FAILURE);
237 }
238 if (getword(typ,sizeof(typ),&gwarea,'\t')<0) {
239 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),tmp);
240 exit(EXIT_FAILURE);
241 }
242 if(strstr(RealtimeTypes,typ) == 0)
243 continue;
d5c1b1c1 244
9bd92830
FM
245 if(strcmp(ouser,user) == 0 && ourl && strcmp(ourl,url) == 0)
246 continue;
d6e703cc 247
9bd92830
FM
248 if(UserIp)
249 strcpy(user,ip);
250 strcpy(u2,user);
251 if(Ip2Name)
252 ip2name(u2,sizeof(u2));
253 user_find(name, sizeof(name), u2);
e5b2c6f0 254
9bd92830
FM
255 printf("<tr><td class=\"data\">%s %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",dat,tim,ip,name,typ,url,url);
256 strcpy(ouser,user);
d5c1b1c1 257
9bd92830
FM
258 url_len=strlen(url);
259 if (!ourl || url_len>=ourl_size) {
260 ourl_size=url_len+1;
261 ourl=realloc(ourl,ourl_size);
262 if (!ourl) {
263 debuga(_("Not enough memory to store the url\n"));
264 exit(EXIT_FAILURE);
265 }
266 }
267 strcpy(ourl,url);
268 }
269 longline_destroy(&line);
270 if (ourl) free(ourl);
dfb337be 271
9bd92830
FM
272 puts("</table>\n</div>\n</body>\n</html>\n");
273 fclose(fin);
08f9b029
FM
274 if (unlink(tmp)) {
275 debuga(_("Cannot delete %s - %s\n"),tmp,strerror(errno));
276 exit(EXIT_FAILURE);
277 }
9bd92830 278 fflush(NULL);
d5c1b1c1
GS
279}
280
32e71fa4 281static void header(void)
d5c1b1c1 282{
9bd92830
FM
283 puts("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"");
284 puts(" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
285 puts("<html>\n");
286 puts("<head>\n");
287 if(realtime_refresh)
288 printf(" <meta http-equiv=refresh content=\"%d\" url=\"sarg-php/sarg-realtime.php\"; charset=\"%s\">\n",realtime_refresh,CharSet);
289 else
290 printf(" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n",CharSet);
291 css(stdout);
292 puts("</head>\n");
293 printf("<body style=\"font-family:%s;font-size:%s;background-color:%s;background-image:url(%s)\">\n",FontFace,TitleFontSize,BgColor,BgImage);
294 puts("<div align=\"center\"><table cellpadding=\"1\" cellspacing=\"1\">\n");
295 printf("<tr><th class=\"title_l\" colspan=\"10\">SARG %s</th></tr>\n",_("Realtime"));
296 printf("<tr><th class=\"text\" colspan=\"10\">%s: %d s</th></tr>\n",_("Auto refresh"),realtime_refresh);
297 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"));
d5c1b1c1 298}