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"
29 #include "include/filelist.h"
30 #include "include/readlog.h"
32 //! Maximum length of the scheme plus host name from the url.
33 #define MAX_URL_HOST_LEN 260
36 \brief Data read from an input log file.
38 struct RealtimeReadLogStruct
40 //! The time corresponding to the entry.
42 //! The IP address connecting to internet.
45 char User
[MAX_USER_LEN
];
47 The URL of the visited site.
49 The pointer may be NULL if the URL doesn't exists in the log file.
51 char Url
[MAX_URL_HOST_LEN
];
52 //! HTTP method or NULL if the information is not stored in the log.
56 extern FileListObject AccessLog
;
58 static bool GetLatestModified(char *file_name
,int file_name_size
)
60 FileListIterator FIter
;
66 FIter
=FileListIter_Open(AccessLog
);
67 while ((file
=FileListIter_Next(FIter
))!=NULL
)
69 if (stat(file
,&st
)==-1) {
70 debuga(__FILE__
,__LINE__
,_("Cannot stat \"%s\": %s\n"),file
,strerror(errno
));
76 safe_strcpy(file_name
,file
,file_name_size
);
78 else if (st
.st_mtime
>latest
)
81 safe_strcpy(file_name
,file
,file_name_size
);
84 FileListIter_Close(FIter
);
89 * \brief Store a log entry.
91 * \param Dest A pointer to the list entry where to store the entry.
92 * \param Entry The entry to store.
94 static void StoreLogEntry(struct RealtimeReadLogStruct
*Dest
,struct ReadLogStruct
*Entry
)
96 memcpy(&Dest
->EntryTime
,&Entry
->EntryTime
,sizeof(Dest
->EntryTime
));
97 safe_strcpy(Dest
->Ip
,Entry
->Ip
,sizeof(Dest
->Ip
));
101 const char *url
=Entry
->Url
;
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]=='/')
108 for (i
=0 ; url
[i
] && url
[i
]!='/' ; i
++);
110 if (i
>=sizeof(Dest
->Url
)) i
=sizeof(Dest
->Url
)-1;
111 strncpy(Dest
->Url
,url
,i
);
114 safe_strcpy(Dest
->User
,Entry
->User
,sizeof(Dest
->User
));
115 safe_strcpy(Dest
->HttpMethod
,Entry
->HttpMethod
,sizeof(Dest
->HttpMethod
));
118 static void header(void)
120 puts("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"");
121 puts(" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
125 printf(" <meta http-equiv=refresh content=\"%d\" url=\"sarg-php/sarg-realtime.php\"; charset=\"%s\">\n",realtime_refresh
,CharSet
);
127 printf(" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n",CharSet
);
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"));
137 static void datashow(struct RealtimeReadLogStruct
*List
,int Index
,int Size
)
140 char user
[MAX_USER_LEN
];
141 char name
[MAX_USER_LEN
];
143 struct RealtimeReadLogStruct
*entry
;
146 for (i
=0 ; i
<realtime_access_log_lines
; i
++)
150 if (Index
<0) Index
=Size
-1;
153 strcpy(user
,entry
->Ip
);
155 strcpy(user
,entry
->User
);
157 ip2name(user
,sizeof(user
));
158 user_find(name
, sizeof(name
), user
);
161 strftime(tbuf
, sizeof(tbuf
), "%Y-%m-%d %H:%M", &entry
->EntryTime
);
163 strftime(tbuf
, sizeof(tbuf
), "%d-%m-%Y %H:%M", &entry
->EntryTime
);
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
);
169 puts("</table>\n</div>\n</body>\n</html>\n");
176 char file_name
[2048];
179 struct ReadLogStruct log_entry
;
180 enum ReadLogReturnCodeEnum log_entry_status
;
181 struct LogLineStruct log_line
;
182 struct RealtimeReadLogStruct
*StoredLogEntries
;
187 init_usertab(UserTabFile
);
188 LogLine_Init(&log_line
);
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.
194 StoredLogEntries
=calloc(realtime_access_log_lines
+1,sizeof(struct RealtimeReadLogStruct
));
195 if (!StoredLogEntries
)
197 debuga(__FILE__
,__LINE__
,_("Not enough memory to store %d records"),realtime_access_log_lines
);
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.
204 memset(StoredLogEntries
,0,sizeof(struct RealtimeReadLogStruct
));
206 if (!GetLatestModified(file_name
,sizeof(file_name
)))
208 debuga(__FILE__
,__LINE__
,_("No log file to read the last %d lines from\n"),realtime_access_log_lines
);
211 fp
= FileObject_Open(file_name
);
213 debuga(__FILE__
,__LINE__
,_("Cannot open file \"%s\": %s\n"),file_name
,FileObject_GetLastOpenError());
217 if ((line
=longline_create())==NULL
) {
218 debuga(__FILE__
,__LINE__
,_("Not enough memory to read file \"%s\"\n"),file_name
);
222 while((buf
=longline_read(fp
,line
)) != NULL
)
224 log_entry_status
=LogLine_Parse(&log_line
,&log_entry
,buf
);
225 if (log_entry_status
==RLRC_Unknown
)
229 if (log_entry_status
==RLRC_Ignore
)
233 if (log_entry
.HttpMethod
&& strstr(RealtimeTypes
,log_entry
.HttpMethod
)==0)
235 if (RealtimeUnauthRec
==REALTIME_UNAUTH_REC_IGNORE
&& log_entry
.User
[0]=='-' && log_entry
.User
[1]=='\0')
237 StoreLogEntry(StoredLogEntries
+NextIndex
,&log_entry
);
238 if (strcmp(StoredLogEntries
[StoreIndex
].User
,StoredLogEntries
[NextIndex
].User
)==0 && strcmp(StoredLogEntries
[StoreIndex
].Url
,StoredLogEntries
[NextIndex
].Url
)==0)
241 StoreIndex
=NextIndex
;
243 if (NextIndex
>StoreSize
) StoreSize
=NextIndex
;
244 if (NextIndex
>realtime_access_log_lines
) NextIndex
=0;
246 if (FileObject_Close(fp
)) {
247 debuga(__FILE__
,__LINE__
,_("Read error in \"%s\": %s\n"),file_name
,FileObject_GetLastCloseError());
250 longline_destroy(&line
);
252 datashow(StoredLogEntries
,StoreIndex
,StoreSize
);
253 free(StoredLogEntries
);