2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
6 * please look at http://sarg.sourceforge.net/donations.php
8 * http://sourceforge.net/projects/sarg/forums/forum/363374
9 * ---------------------------------------------------------------------
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.
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.
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.
27 #include "include/conf.h"
28 #include "include/defs.h"
30 static int getdata(char*, FILE*);
31 static void datashow(const char *);
32 static void getlog(void);
33 static void header(void);
40 static void getlog(void)
43 char template1
[255]="/var/tmp/sargtpl1.XXXXXX";
44 char template2
[255]="/var/tmp/sargtpl2.XXXXXX";
51 init_usertab(UserTabFile
);
54 fd2
= mkstemp(template2
);
56 debuga(_("Cannot create a temporary file name to produce the report: %s\n"),strerror(errno
));
59 fd1
= mkstemp(template1
);
61 buf
= mktemp(template2
);
63 debuga(_("Cannot create a temporary file name to produce the report: %s\n"),strerror(errno
));
67 fd1
= open(mktemp(template1
),O_RDWR
);
70 if((fd1
== -1 ) || ((tmp
= fdopen (fd1
, "w+" )) == NULL
) ) { /* failure, bail out */
71 debugapos("realtime",_("mkstemp error: %s\n"),strerror(errno
));
75 if ((line
=longline_create())==NULL
) {
76 debuga(_("Not enough memory to read the log file\n"));
80 sprintf(cmd
,"tail -%d \"%s\"",realtime_access_log_lines
,AccessLog
[0]);
83 debuga(_("Failed to get the %d trailing lines of \"%s\": %s\n"),realtime_access_log_lines
,AccessLog
[0],strerror(errno
));
84 debuga(_("Failed \"tail\" command: %s\n"),cmd
);
87 while((buf
=longline_read(fp
,line
)) != NULL
)
88 if (getdata(buf
,tmp
)<0) {
89 /* TRANSLATORS: The %s is the command returning the invalid data. */
90 debuga(_("Invalid data returned by %s\n"),cmd
);
95 longline_destroy(&line
);
97 if (fd2
!=-1) close(fd2
);//not safe at all but good enough for now.
98 if (snprintf(cmd
,sizeof(cmd
),"sort -t \"\t\" -r -n -k 1,1 -o \"%s\" \"%s\"",template2
,template1
)>=sizeof(cmd
)) {
99 debuga(_("Command too long: "));
100 debuga_more("sort -t \"\t\" -r -n -k 1,1 -o \"%s\" \"%s\"",template2
,template1
);
104 if (!WIFEXITED(cstatus
) || WEXITSTATUS(cstatus
)) {
105 debuga(_("sort command return status %d\n"),WEXITSTATUS(cstatus
));
106 debuga(_("sort command: %s\n"),cmd
);
109 if (!KeepTempLog
&& unlink(template1
)) {
110 debuga(_("Cannot delete \"%s\": %s\n"),template1
,strerror(errno
));
116 static int getdata(char *rec
, FILE *ftmp
)
121 char user
[MAX_USER_LEN
];
124 struct getwordstruct gwarea
;
126 getword_start(&gwarea
,rec
);
127 if (getword_atoi(&dat
,&gwarea
,'.')<0) {
128 debuga(_("The time stamp at column 1 is too long\n"));
131 if (getword_skip(10,&gwarea
,' ')<0) {
132 debuga(_("The time stamp decimal part at column 1 is too long\n"));
135 if (getword(warea
,sizeof(warea
),&gwarea
,' ')<0) {
136 debuga(_("The connection duration at column 2 is too long\n"));
139 while(strcmp(warea
,"") == 0 && gwarea
.current
[0] != '\0')
140 if (getword(warea
,sizeof(warea
),&gwarea
,' ')<0) {
143 if (getword(ip
,sizeof(ip
),&gwarea
,' ')<0) {
144 debuga(_("The IP address at column 3 is too long\n"));
147 if (getword_skip(MAXLEN
,&gwarea
,' ')<0) {
148 debuga(_("The status at column 4 is too long\n"));
151 if (getword_skip(MAXLEN
,&gwarea
,' ')<0) {
152 debuga(_("The size at column 5 is too long\n"));
155 if (getword(typ
,sizeof(typ
),&gwarea
,' ')<0) {
156 debuga(_("The action at column 6 is too long\n"));
159 if(strncmp(typ
,"CONNECT",7) == 0) {
160 if (getword_ptr(rec
,&url
,&gwarea
,' ')<0) {
161 debuga(_("The URL at column 7 is too long\n"));
164 if (getword(user
,sizeof(user
),&gwarea
,' ')<0) {
165 debuga(_("The user ID at column 8 is too long\n"));
169 if (getword_skip(MAXLEN
,&gwarea
,'/')<0) {
170 debuga(_("The URL at column 7 is too long\n"));
173 if (getword_skip(MAXLEN
,&gwarea
,'/')<0) {
174 debuga(_("The URL at column 7 is too long\n"));
177 if (getword_ptr(rec
,&url
,&gwarea
,'/')<0) {
178 debuga(_("The URL at column 7 is too long\n"));
181 if (getword_skip(MAXLEN
,&gwarea
,' ')<0) {
182 debuga(_("The data at column 8 is too long\n"));
185 if (getword(user
,sizeof(user
),&gwarea
,' ')<0) {
186 debuga(_("The user at column 9 is too long\n"));
191 if(strncmp(user
,"-",1) == 0 && RealtimeUnauthRec
==REALTIME_UNAUTH_REC_IGNORE
)
194 fprintf(ftmp
,"%d\t%s\t%s\t%s\t%s\n",dat
,ip
,user
,url
,typ
);
198 static void datashow(const char *tmp
)
208 char ouser
[MAX_USER_LEN
]="";
210 char user
[MAX_USER_LEN
];
211 char u2
[MAX_USER_LEN
];
215 struct getwordstruct gwarea
;
218 if((fin
=fopen(tmp
,"r"))==NULL
) {
219 debugapos("realtime",_("Cannot open file \"%s\": %s\n"),tmp
,strerror(errno
));
225 if ((line
=longline_create())==NULL
) {
226 debuga(_("Not enough memory to read the log file\n"));
230 while((buf
=longline_read(fin
,line
))!=NULL
) {
232 getword_start(&gwarea
,buf
);
233 if (getword_atoi(&dat
,&gwarea
,'\t')<0) {
234 debuga(_("Invalid time column in file %s\n"),tmp
);
237 if (getword(ip
,sizeof(ip
),&gwarea
,'\t')<0) {
238 debuga(_("Invalid IP address in file \"%s\"\n"),tmp
);
241 if (getword(user
,sizeof(user
),&gwarea
,'\t')<0) {
242 debuga(_("Invalid user in file \"%s\"\n"),tmp
);
245 if (strlen(user
) < 1) continue;
246 if (getword_ptr(buf
,&url
,&gwarea
,'\t')<0) {
247 debuga(_("Invalid url in file \"%s\"\n"),tmp
);
250 if (getword(typ
,sizeof(typ
),&gwarea
,'\t')<0) {
251 debuga(_("Invalid access type in file \"%s\"\n"),tmp
);
254 if(strstr(RealtimeTypes
,typ
) == 0)
257 if(strcmp(ouser
,user
) == 0 && ourl
&& strcmp(ourl
,url
) == 0)
264 ip2name(u2
,sizeof(u2
));
265 user_find(name
, sizeof(name
), u2
);
269 if(DateFormat
[0]=='u')
270 strftime(tbuf
, sizeof(tbuf
), "%Y-%m-%d %H:%M", t
);
271 else if(DateFormat
[0]=='e')
272 strftime(tbuf
, sizeof(tbuf
), "%d-%m-%Y %H:%M", t
);
274 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
);
278 if (!ourl
|| url_len
>=ourl_size
) {
280 ourl
=realloc(ourl
,ourl_size
);
282 debuga(_("Not enough memory to store the url\n"));
288 longline_destroy(&line
);
289 if (ourl
) free(ourl
);
291 puts("</table>\n</div>\n</body>\n</html>\n");
293 if (!KeepTempLog
&& unlink(tmp
)) {
294 debuga(_("Cannot delete \"%s\": %s\n"),tmp
,strerror(errno
));
300 static void header(void)
302 puts("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"");
303 puts(" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
307 printf(" <meta http-equiv=refresh content=\"%d\" url=\"sarg-php/sarg-realtime.php\"; charset=\"%s\">\n",realtime_refresh
,CharSet
);
309 printf(" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n",CharSet
);
312 printf("<body style=\"font-family:%s;font-size:%s;background-color:%s;background-image:url(%s)\">\n",FontFace
,TitleFontSize
,BgColor
,BgImage
);
313 puts("<div align=\"center\"><table cellpadding=\"1\" cellspacing=\"1\">\n");
314 printf("<tr><th class=\"title_l\" colspan=\"10\">SARG %s</th></tr>\n",_("Realtime"));
315 printf("<tr><th class=\"text\" colspan=\"10\">%s: %d s</th></tr>\n",_("Auto refresh"),realtime_refresh
);
316 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"));