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