sarg  2.4.0
About: SARG ia a Squid Analysis Report Generator.
  Fossies Dox: sarg-2.4.0.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

download.c
Go to the documentation of this file.
1 /*
2  * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
3  * 1998, 2015
4  *
5  * SARG donations:
6  * please look at http://sarg.sourceforge.net/donations.php
7  * Support:
8  * http://sourceforge.net/projects/sarg/forums/forum/363374
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"
28 #include "include/defs.h"
29 #include "include/readlog.h"
30 
36 /*@null@*/static char *DownloadSuffix=NULL;
37 
42 /*@null@*/static char **DownloadSuffixIndex=NULL;
43 
47 static int NDownloadSuffix=0;
48 
50 static char download_unsort[MAXLEN]="";
52 static FILE *fp_download=NULL;
54 static bool download_exists=false;
55 
61 void download_open(void)
62 {
63  if ((ReportType & REPORT_TYPE_DOWNLOADS) == 0) {
64  if (debugz>=LogLevel_Process) debugaz(__FILE__,__LINE__,_("Download report not produced as it is not requested\n"));
65  return;
66  }
67  if (Privacy) {
68  if (debugz>=LogLevel_Process) debugaz(__FILE__,__LINE__,_("Download report not produced because privacy option is active\n"));
69  return;
70  }
71 
72  format_path(__FILE__, __LINE__, download_unsort, sizeof(download_unsort), "%s/download.int_unsort", tmp);
73  if ((fp_download=MY_FOPEN(download_unsort,"w"))==NULL) {
74  debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),download_unsort,strerror(errno));
75  exit(EXIT_FAILURE);
76  }
77  return;
78 }
79 
86 void download_write(const struct ReadLogStruct *log_entry,const char *url)
87 {
88  char date[80];
89 
90  if (fp_download && strstr(log_entry->HttpCode,"DENIED") == 0) {
91  strftime(date,sizeof(date),"%d/%m/%Y\t%H:%M:%S",&log_entry->EntryTime);
92  fprintf(fp_download,"%s\t%s\t%s\t%s\n",date,log_entry->User,log_entry->Ip,url);
93  download_exists=true;
94  }
95 }
96 
100 void download_close(void)
101 {
102  if (fp_download)
103  {
104  if (fclose(fp_download)==EOF) {
105  debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),download_unsort,strerror(errno));
106  exit(EXIT_FAILURE);
107  }
108  fp_download=NULL;
109  }
110 }
111 
118 bool is_download(void)
119 {
120  return(download_exists);
121 }
122 
131 static void download_sort(const char *report_in)
132 {
133  int clen;
134  char csort[MAXLEN];
135  int cstatus;
136 
137  clen=snprintf(csort,sizeof(csort),"sort -T \"%s\" -t \"\t\" -k 3,3 -k 1,1 -k 2,2 -k 5,5 -o \"%s\" \"%s\"",
138  tmp, report_in, download_unsort);
139  if (clen>=sizeof(csort)) {
140  debuga(__FILE__,__LINE__,_("Path too long to sort file \"%s\"\n"),download_unsort);
141  exit(EXIT_FAILURE);
142  }
143  cstatus=system(csort);
144  if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
145  debuga(__FILE__,__LINE__,_("sort command return status %d\n"),WEXITSTATUS(cstatus));
146  debuga(__FILE__,__LINE__,_("sort command: %s\n"),csort);
147  exit(EXIT_FAILURE);
148  }
149  if (!KeepTempLog) {
150  if (unlink(download_unsort)) {
151  debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),download_unsort,strerror(errno));
152  exit(EXIT_FAILURE);
153  }
154  download_unsort[0]='\0';
155  }
156 }
157 
162 void download_report(void)
163 {
164  FileObject *fp_in = NULL;
165  FILE *fp_ou = NULL;
166 
167  char *buf;
168  char *url;
169  char report_in[MAXLEN];
170  char report[MAXLEN];
171  char ip[MAXLEN];
172  char oip[MAXLEN];
173  char user[MAXLEN];
174  char ouser[MAXLEN];
175  char ouser2[MAXLEN];
176  char data[15];
177  char hora[15];
178  int z=0;
179  int count=0;
180  int i;
181  int day,month,year;
182  bool new_user;
183  struct getwordstruct gwarea;
184  longline line;
185  struct userinfostruct *uinfo;
186  struct tm t;
187 
188  if (!download_exists) {
189  if (!KeepTempLog && download_unsort[0]!='\0' && unlink(download_unsort))
190  debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),download_unsort,strerror(errno));
191  download_unsort[0]='\0';
192  if (debugz>=LogLevel_Process) debugaz(__FILE__,__LINE__,_("No downloaded files to report\n"));
193  return;
194  }
195 
197  debuga(__FILE__,__LINE__,_("Creating download report...\n"));
198  ouser[0]='\0';
199  ouser2[0]='\0';
200 
201  // sort the raw file
202  format_path(__FILE__, __LINE__, report_in, sizeof(report_in), "%s/download.int_log", tmp);
203  download_sort(report_in);
204 
205  // produce the report.
206  format_path(__FILE__, __LINE__, report, sizeof(report), "%s/download.html", outdirname);
207 
208  if ((fp_in=FileObject_Open(report_in))==NULL) {
209  debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),report_in,FileObject_GetLastOpenError());
210  exit(EXIT_FAILURE);
211  }
212 
213  if ((fp_ou=MY_FOPEN(report,"w"))==NULL) {
214  debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),report,strerror(errno));
215  exit(EXIT_FAILURE);
216  }
217 
218  write_html_header(fp_ou,(IndexTree == INDEX_TREE_DATE) ? 3 : 1,_("Downloads"),HTML_JS_NONE);
219  fputs("<tr><td class=\"header_c\">",fp_ou);
220  fprintf(fp_ou,_("Period: %s"),period.html);
221  fputs("</td></tr>\n",fp_ou);
222  fprintf(fp_ou,"<tr><th class=\"header_c\">%s</th></tr>\n",_("Downloads"));
223  close_html_header(fp_ou);
224 
225  fputs("<div class=\"report\"><table cellpadding=\"0\" cellspacing=\"2\">\n",fp_ou);
226  fprintf(fp_ou,"<tr><th class=\"header_l\">%s</th><th class=\"header_l\">%s</th><th class=\"header_l\">%s</th><th class=\"header_l\">%s</th></tr>\n",_("USERID"),_("IP/NAME"),_("DATE/TIME"),_("ACCESSED SITE"));
227 
228  if ((line=longline_create())==NULL) {
229  debuga(__FILE__,__LINE__,_("Not enough memory to read file \"%s\"\n"),report_in);
230  exit(EXIT_FAILURE);
231  }
232 
233  while((buf=longline_read(fp_in,line))!=NULL) {
234  getword_start(&gwarea,buf);
235  if (getword(data,sizeof(data),&gwarea,'\t')<0 || getword(hora,sizeof(hora),&gwarea,'\t')<0 ||
236  getword(user,sizeof(user),&gwarea,'\t')<0 || getword(ip,sizeof(ip),&gwarea,'\t')<0) {
237  debuga(__FILE__,__LINE__,_("Invalid record in file \"%s\"\n"),report_in);
238  exit(EXIT_FAILURE);
239  }
240  if (getword_ptr(buf,&url,&gwarea,'\t')<0) {
241  debuga(__FILE__,__LINE__,_("Invalid url in file \"%s\"\n"),report_in);
242  exit(EXIT_FAILURE);
243  }
244  if (sscanf(data,"%d/%d/%d",&day,&month,&year)!=3) continue;
245  computedate(year,month,day,&t);
246  strftime(data,sizeof(data),"%x",&t);
247 
248  uinfo=userinfo_find_from_id(user);
249  if (!uinfo) {
250  debuga(__FILE__,__LINE__,_("Unknown user ID %s in file \"%s\"\n"),user,report_in);
251  exit(EXIT_FAILURE);
252  }
253  new_user=false;
254  if (!z) {
255  strcpy(ouser,user);
256  strcpy(oip,ip);
257  z++;
258  new_user=true;
259  } else {
260  if (strcmp(ouser,user) != 0) {
261  strcpy(ouser,user);
262  new_user=true;
263  }
264  if (strcmp(oip,ip) != 0) {
265  strcpy(oip,ip);
266  new_user=true;
267  }
268  }
269 
270  if (DownloadReportLimit) {
271  if (strcmp(ouser2,uinfo->label) == 0) {
272  count++;
273  } else {
274  count=1;
275  strcpy(ouser2,uinfo->label);
276  }
277  if (count >= DownloadReportLimit)
278  continue;
279  }
280 
281  for (i=strlen(url)-1 ; i>=0 && (unsigned char)url[i]<' ' ; i--) url[i]=0;
282 
283  fputs("<tr>",fp_ou);
284  if (new_user) {
285  if (uinfo->topuser)
286  fprintf(fp_ou,"<td class=\"data\"><a href=\"%s/%s.html\">%s</a></td><td class=\"data\">%s</td>",uinfo->filename,uinfo->filename,uinfo->label,ip);
287  else
288  fprintf(fp_ou,"<td class=\"data\">%s</td><td class=\"data\">%s</td>",uinfo->label,ip);
289  } else
290  fputs("<td class=\"data\"></td><td class=\"data\"></td>",fp_ou);
291  fprintf(fp_ou,"<td class=\"data\">%s-%s</td><td class=\"data2\">",data,hora);
292  if (BlockIt[0]!='\0' && url[0]!=ALIAS_PREFIX) {
293  fprintf(fp_ou,"<a href=\"%s%s?url=\"",wwwDocumentRoot,BlockIt);
294  output_html_url(fp_ou,url);
295  fprintf(fp_ou,"\"><img src=\"%s/sarg-squidguard-block.png\"></a>&nbsp;",ImageFile);
296  }
297  output_html_link(fp_ou,url,100);
298  fputs("</td></tr>\n",fp_ou);
299  }
300  if (FileObject_Close(fp_in)) {
301  debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),report_in,FileObject_GetLastCloseError());
302  exit(EXIT_FAILURE);
303  }
304  longline_destroy(&line);
305 
306  fputs("</table></div>\n",fp_ou);
307  write_html_trailer(fp_ou);
308  if (fclose(fp_ou)==EOF) {
309  debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),report,strerror(errno));
310  exit(EXIT_FAILURE);
311  }
312 
313  if (!KeepTempLog && unlink(report_in)) {
314  debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),report_in,strerror(errno));
315  exit(EXIT_FAILURE);
316  }
317 
318  return;
319 }
320 
324 void free_download(void)
325 {
326  if (DownloadSuffix) {
327  free(DownloadSuffix);
328  DownloadSuffix=NULL;
329  }
330  if (DownloadSuffixIndex) {
331  free(DownloadSuffixIndex);
332  DownloadSuffixIndex=NULL;
333  }
334  NDownloadSuffix=0;
335 }
336 
345 void set_download_suffix(const char *list)
346 {
347  char *str;
348  int i, j, k;
349  int cmp;
350 
351  free_download();
352 
353  DownloadSuffix=strdup(list);
354  if (!DownloadSuffix) {
355  debuga(__FILE__,__LINE__,_("Download suffix list too long\n"));
356  exit(EXIT_FAILURE);
357  }
358  j = 1;
359  for (i=0 ; list[i] ; i++)
360  if (list[i] == ',') j++;
361  DownloadSuffixIndex=malloc(j*sizeof(char *));
362  if (!DownloadSuffixIndex) {
363  debuga(__FILE__,__LINE__,_("Too many download suffixes\n"));
364  exit(EXIT_FAILURE);
365  }
366 
367  str = DownloadSuffix;
368  for (i=0 ; DownloadSuffix[i] ; i++) {
369  if (DownloadSuffix[i] == ',') {
370  DownloadSuffix[i] = '\0';
371  if (*str) {
372  cmp = -1;
373  for (j=0 ; j<NDownloadSuffix && (cmp=strcasecmp(str,DownloadSuffixIndex[j]))>0 ; j++);
374  if (cmp != 0) {
375  for (k=NDownloadSuffix ; k>j ; k--)
377  NDownloadSuffix++;
378  DownloadSuffixIndex[j]=str;
379  }
380  }
381  str=DownloadSuffix+i+1;
382  }
383  }
384 
385  if (*str) {
386  cmp = -1;
387  for (j=0 ; j<NDownloadSuffix && (cmp=strcasecmp(str,DownloadSuffixIndex[j]))>0 ; j++);
388  if (cmp != 0) {
389  for (k=NDownloadSuffix ; k>j ; k--)
391  NDownloadSuffix++;
392  DownloadSuffixIndex[j]=str;
393  }
394  }
395 }
396 
414 bool is_download_suffix(const char *url)
415 {
416  int urllen;
417  int i;
418  int down, up, center;
419  const char *suffix;
420  int cmp;
421  const int max_suffix=10;
422 
423  if (DownloadSuffix == NULL || NDownloadSuffix == 0) return(false);
424 
425  urllen=strlen(url)-1;
426  if (urllen<=0) return(false);
427  if (url[urllen] == '.') return(false); //reject a single trailing dot
428  for (i=0 ; i<urllen && (url[i]!='/' || url[i+1]=='/') && url[i]!='?' ; i++);
429  if (i>=urllen) return(false); // url is a hostname without any path or file to download
430 
431  for (i=0 ; i<=max_suffix && i<urllen && url[urllen-i]!='.' ; i++)
432  if (url[urllen-i] == '/' || url[urllen-i] == '?') return(false);
433  if (i>max_suffix || i>=urllen) return(false);
434 
435  suffix=url+urllen-i+1;
436  down=0;
437  up=NDownloadSuffix-1;
438  while (down<=up) {
439  center=(down+up)/2;
440  cmp=strcasecmp(suffix,DownloadSuffixIndex[center]);
441  if (cmp == 0) return(true);
442  if (cmp < 0)
443  up = center-1;
444  else
445  down = center+1;
446  }
447  return(false);
448 }
449 
454 {
455  if (fp_download) {
456  if (fclose(fp_download)==EOF) {
457  debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),download_unsort,strerror(errno));
458  exit(EXIT_FAILURE);
459  }
460  fp_download=NULL;
461  }
462  if (download_unsort[0]) {
463  if (unlink(download_unsort)==-1)
464  debuga(__FILE__,__LINE__,_("Failed to delete \"%s\": %s\n"),download_unsort,strerror(errno));
465  }
466 }
ReadLogStruct::EntryTime
struct tm EntryTime
The time corresponding to the entry.
Definition: readlog.h:27
userinfostruct::topuser
int topuser
True if this user is in the topuser list.
Definition: defs.h:93
getword_start
void getword_start(struct getwordstruct *gwarea, const char *line)
Definition: util.c:74
write_html_header
void write_html_header(FILE *fp_ou, int depth, const char *title, int javascript)
Definition: util.c:2144
debuga
void debuga(const char *File, int Line, const char *msg,...)
Definition: util.c:601
output_html_url
void output_html_url(FILE *fp_ou, const char *url)
Definition: util.c:2194
ReadLogStruct::HttpCode
char * HttpCode
HTTP code returned to the user for the entry.
Definition: readlog.h:43
userinfostruct
What is known about a user.
Definition: defs.h:78
DownloadSuffixIndex
static char ** DownloadSuffixIndex
Definition: download.c:42
longline_read
char * longline_read(FileObject *fp_in, longline line)
Definition: longline.c:97
format_path
int format_path(const char *file, int line, char *output_buffer, int buffer_size, const char *format,...)
Definition: util.c:2665
FileObject_GetLastCloseError
const char * FileObject_GetLastCloseError(void)
Definition: fileobject.c:263
download_open
void download_open(void)
Definition: download.c:61
longlinestruct
Definition: longline.c:56
KeepTempLog
bool KeepTempLog
True to keep the temporary files for inspection.
Definition: conf.h:505
FileObject_GetLastOpenError
const char * FileObject_GetLastOpenError(void)
Definition: fileobject.c:236
MY_FOPEN
#define MY_FOPEN
Definition: conf.h:129
_
#define _(String)
Definition: conf.h:155
MAXLEN
#define MAXLEN
Definition: conf.h:176
download_report
void download_report(void)
Definition: download.c:162
DownloadSuffix
static char * DownloadSuffix
Definition: download.c:36
is_download
bool is_download(void)
Definition: download.c:118
NDownloadSuffix
static int NDownloadSuffix
Definition: download.c:47
INDEX_TREE_DATE
#define INDEX_TREE_DATE
Definition: conf.h:240
HTML_JS_NONE
#define HTML_JS_NONE
Value to exclude all the javascripts from the html page.
Definition: conf.h:285
userinfo_find_from_id
struct userinfostruct * userinfo_find_from_id(const char *id)
Definition: userinfo.c:218
ReadLogStruct::Ip
const char * Ip
The IP address connecting to internet.
Definition: readlog.h:29
userinfostruct::label
const char * label
The name of the user to display in the report.
Definition: defs.h:89
wwwDocumentRoot
char wwwDocumentRoot[20000]
Definition: conf.h:411
ReportType
unsigned long int ReportType
Definition: conf.h:332
close_html_header
void close_html_header(FILE *fp_ou)
Definition: util.c:2152
getword_ptr
int getword_ptr(char *orig_line, char **word, struct getwordstruct *gwarea, char stop)
Definition: util.c:343
computedate
void computedate(int year, int month, int day, struct tm *t)
Definition: util.c:892
IndexTree
unsigned long int IndexTree
How to display the index of the reports.
Definition: conf.h:416
ImageFile
char ImageFile[255]
Definition: conf.h:443
set_download_suffix
void set_download_suffix(const char *list)
Definition: download.c:345
ReadLogStruct
Data read from an input log file.
Definition: readlog.h:24
periodstruct::html
char html[90]
The HTML representation of the date.
Definition: conf.h:307
ReadLogStruct::User
const char * User
The user's name.
Definition: readlog.h:31
getword
int getword(char *word, int limit, struct getwordstruct *gwarea, char stop)
Definition: util.c:90
download_exists
static bool download_exists
True if at least one downloaded entry exists.
Definition: download.c:54
FileObject_Open
FileObject * FileObject_Open(const char *FileName)
Definition: fileobject.c:104
is_download_suffix
bool is_download_suffix(const char *url)
Definition: download.c:414
conf.h
Include headers and define global variables. */.
ALIAS_PREFIX
#define ALIAS_PREFIX
The character prefixed in front of the host names that are aliased.
Definition: conf.h:290
download_write
void download_write(const struct ReadLogStruct *log_entry, const char *url)
Definition: download.c:86
free_download
void free_download(void)
Definition: download.c:324
longline_create
longline longline_create(void)
Definition: longline.c:70
DownloadReportLimit
int DownloadReportLimit
Definition: conf.h:493
userinfostruct::filename
const char * filename
The mangled name to use in file names of that user.
Definition: defs.h:91
download_unsort
static char download_unsort[20000]
Name of the file containing the unsorted downloaded entries.
Definition: download.c:50
readlog.h
Privacy
bool Privacy
Definition: conf.h:372
getwordstruct
Definition: defs.h:26
REPORT_TYPE_DOWNLOADS
#define REPORT_TYPE_DOWNLOADS
Definition: conf.h:199
longline_destroy
void longline_destroy(longline *line_ptr)
Definition: longline.c:168
download_cleanup
void download_cleanup(void)
Definition: download.c:453
debugaz
void debugaz(const char *File, int Line, const char *msg,...)
Definition: util.c:646
download_close
void download_close(void)
Definition: download.c:100
write_html_trailer
void write_html_trailer(FILE *fp_ou)
Definition: util.c:2157
tmp
char tmp[20000]
Definition: conf.h:315
fp_download
static FILE * fp_download
The file handle to write the entries.
Definition: download.c:52
defs.h
Declaration of the structures and functions.
outdirname
char outdirname[20000]
Definition: conf.h:311
BlockIt
char BlockIt[255]
Definition: conf.h:413
debugz
int debugz
Definition: conf.h:490
period
struct periodstruct period
Definition: conf.h:312
download_sort
static void download_sort(const char *report_in)
Definition: download.c:131
FileObject_Close
int FileObject_Close(FileObject *File)
Definition: fileobject.c:206
FileObjectStruct
Definition: fileobject.h:4
output_html_link
void output_html_link(FILE *fp_ou, const char *url, int maxlen)
Definition: util.c:2214
LogLevel_Process
@ LogLevel_Process
Process informational messages.
Definition: defs.h:15