"Fossies" - the Fresh Open Source Software Archive 
Member "sarg-2.4.0/topuser.c" (24 Dec 2019, 26983 Bytes) of package /linux/privat/sarg-2.4.0.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "topuser.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
2.3.11_vs_2.4.0.
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/filelist.h"
30
31 struct TopUserStatistics
32 {
33 long long int ttnbytes;
34 long long int ttnacc;
35 long long int ttnelap;
36 long long int ttnincache;
37 long long int ttnoucache;
38 int totuser;
39 };
40
41 struct SortInfoStruct
42 {
43 const char *sort_field;
44 const char *sort_order;
45 };
46
47 extern struct globalstatstruct globstat;
48 extern bool smartfilter;
49
50 /*!
51 Save the total number of users. The number is written in sarg-users and set
52 in a global variable for further reference.
53
54 \param totuser The total number of users.
55 */
56 static void set_total_users(int totuser)
57 {
58 char tusr[1024];
59 FILE *fp_ou;
60
61 format_path(__FILE__, __LINE__, tusr, sizeof(tusr), "%s/sarg-users", outdirname);
62 if ((fp_ou=fopen(tusr,"w"))==NULL) {
63 debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),tusr,strerror(errno));
64 exit(EXIT_FAILURE);
65 }
66 fprintf(fp_ou,"%d\n",totuser);
67 if (fclose(fp_ou)==EOF) {
68 debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),tusr,strerror(errno));
69 exit(EXIT_FAILURE);
70 }
71 globstat.totuser=totuser;
72 }
73
74 /*!
75 * Generate a HTML report with the users downloading the most.
76 *
77 * \param ListFile Name of the file with the sorted list of users.
78 * \param Statis Statistics about the data collected from the log file.
79 * \param SortInfo Strings explaining how the list was sorted.
80 */
81 static void TopUser_HtmlReport(const char *ListFile,struct TopUserStatistics *Statis,struct SortInfoStruct *SortInfo)
82 {
83 FileObject *fp_top1 = NULL;
84 FILE *fp_top3 = NULL;
85 long long int nbytes;
86 long long int nacc;
87 long long int elap, incac, oucac;
88 double perc=0.00;
89 double perc2=0.00;
90 double inperc=0.00, ouperc=0.00;
91 int posicao=0;
92 char top3[MAXLEN];
93 char user[MAX_USER_LEN];
94 char title[80];
95 char *warea;
96 bool ntopuser=false;
97 int topcount=0;
98 struct getwordstruct gwarea;
99 longline line;
100 struct userinfostruct *uinfo;
101
102 if ((fp_top1=FileObject_Open(ListFile))==NULL) {
103 debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),ListFile,FileObject_GetLastOpenError());
104 exit(EXIT_FAILURE);
105 }
106
107 format_path(__FILE__, __LINE__, top3, sizeof(top3), "%s/"INDEX_HTML_FILE, outdirname);
108 if ((fp_top3=fopen(top3,"w"))==NULL) {
109 debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),top3,strerror(errno));
110 exit(EXIT_FAILURE);
111 }
112
113 snprintf(title,sizeof(title),_("SARG report for %s"),period.text);
114 write_html_header(fp_top3,(IndexTree == INDEX_TREE_DATE) ? 3 : 1,title,HTML_JS_SORTTABLE);
115 fputs("<tr><td class=\"header_c\">",fp_top3);
116 fprintf(fp_top3,_("Period: %s"),period.html);
117 fputs("</td></tr>\n",fp_top3);
118 if ((ReportType & REPORT_TYPE_TOPUSERS) != 0) {
119 fputs("<tr><td class=\"header_c\">",fp_top3);
120 fprintf(fp_top3,_("Sort: %s, %s"),SortInfo->sort_field,SortInfo->sort_order);
121 fputs("</td></tr>\n",fp_top3);
122 fprintf(fp_top3,"<tr><th class=\"header_c\">%s</th></tr>\n",_("Top users"));
123 } else {
124 /* TRANSLATORS: This is the title of the main report page when no
125 * top users list are requested.
126 */
127 fprintf(fp_top3,"<tr><th class=\"header_c\">%s</th></tr>\n",_("Table of content"));
128 }
129 close_html_header(fp_top3);
130
131 if (!indexonly) {
132 fputs("<div class=\"report\"><table cellpadding=\"1\" cellspacing=\"2\">\n",fp_top3);
133 if ((ReportType & REPORT_TYPE_TOPSITES) != 0 && !Privacy) fprintf(fp_top3,"<tr><td class=\"link\" colspan=\"0\"><a href=\"topsites.html\">%s</a></td></tr>\n",_("Top sites"));
134 if ((ReportType & REPORT_TYPE_SITES_USERS) != 0 && !Privacy) fprintf(fp_top3,"<tr><td class=\"link\" colspan=\"0\"><a href=\"siteuser.html\">%s</a></td></tr>\n",_("Sites & Users"));
135 if (dansguardian_count) fprintf(fp_top3,"<tr><td class=\"link\" colspan=\"0\"><a href=\"dansguardian.html\">%s</a></td></tr>\n",_("DansGuardian"));
136 if (redirector_count) fprintf(fp_top3,"<tr><td class=\"link\" colspan=\"0\"><a href=\"redirector.html\">%s</a></td></tr>\n",_("Redirector"));
137 if (is_download()) fprintf(fp_top3,"<tr><td class=\"link\" colspan=\"0\"><a href=\"download.html\">%s</a></td></tr>\n",_("Downloads"));
138 if (is_denied()) fprintf(fp_top3,"<tr><td class=\"link\" colspan=\"0\"><a href=\"denied.html\">%s</a></td></tr>\n",_("Denied accesses"));
139 if (is_authfail()) fprintf(fp_top3,"<tr><td class=\"link\" colspan=\"0\"><a href=\"authfail.html\">%s</a></td></tr>\n",_("Authentication Failures"));
140 if (smartfilter) fprintf(fp_top3,"<tr><td class=\"link\" colspan=\"0\"><a href=\"smartfilter.html\">%s</a></td></tr>\n",_("SmartFilter"));
141 if (useragent_count) fprintf(fp_top3,"<tr><td class=\"link\" colspan=\"0\"><a href=\"useragent.html\">%s</a></td></tr>\n",_("Useragent"));
142 fputs("<tr><td></td></tr>\n</table></div>\n",fp_top3);
143 }
144
145 if ((ReportType & REPORT_TYPE_TOPUSERS) == 0) {
146 fputs("</body>\n</html>\n",fp_top3);
147 if (fclose (fp_top3)==EOF) {
148 debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),top3,strerror(errno));
149 exit(EXIT_FAILURE);
150 }
151 if (debugz>=LogLevel_Process) debugaz(__FILE__,__LINE__,_("No top users report because it is not configured in report_type\n"));
152 return;
153 }
154
155 fputs("<div class=\"report\"><table cellpadding=\"1\" cellspacing=\"2\"",fp_top3);
156 if (SortTableJs[0])
157 fputs(" class=\"sortable\"",fp_top3);
158 fputs(">\n<thead><tr>",fp_top3);
159
160 if ((TopUserFields & TOPUSERFIELDS_NUM) != 0)
161 fprintf(fp_top3,"<th class=\"header_l\">%s</th>",_("NUM"));
162 if ((TopUserFields & TOPUSERFIELDS_DATE_TIME) !=0 && (ReportType & REPORT_TYPE_DATE_TIME) != 0 && !indexonly) {
163 fputs("<th class=\"header_l",fp_top3);
164 if (SortTableJs[0]) fputs(" sorttable_nosort",fp_top3);
165 fputs("\"></th>",fp_top3);
166 }
167 if ((TopUserFields & TOPUSERFIELDS_USERID) != 0) {
168 fputs("<th class=\"header_l",fp_top3);
169 if (SortTableJs[0]) fputs(" sorttable_alpha",fp_top3);
170 fprintf(fp_top3,"\">%s</th>",_("USERID"));
171 }
172 if ((TopUserFields & TOPUSERFIELDS_USERIP) != 0) {
173 fputs("<th class=\"header_l",fp_top3);
174 if (SortTableJs[0]) fputs(" sorttable_alpha",fp_top3);
175 fprintf(fp_top3,"\">%s</th>",_("USERIP"));
176 }
177 if ((TopUserFields & TOPUSERFIELDS_CONNECT) != 0)
178 fprintf(fp_top3,"<th class=\"header_l\">%s</th>",_("CONNECT"));
179 if ((TopUserFields & TOPUSERFIELDS_BYTES) != 0)
180 fprintf(fp_top3,"<th class=\"header_l\">%s</th>",_("BYTES"));
181 if ((TopUserFields & TOPUSERFIELDS_SETYB) != 0)
182 fprintf(fp_top3,"<th class=\"header_l\">%%%s</th>",_("BYTES"));
183 if ((TopUserFields & TOPUSERFIELDS_IN_CACHE_OUT) != 0)
184 fprintf(fp_top3,"<th class=\"header_c\" colspan=\"2\">%s</th><th style=\"display:none;\"></th>",_("IN-CACHE-OUT"));
185 if ((TopUserFields & TOPUSERFIELDS_USED_TIME) != 0)
186 fprintf(fp_top3,"<th class=\"header_l\">%s</th>",_("ELAPSED TIME"));
187 if ((TopUserFields & TOPUSERFIELDS_MILISEC) != 0)
188 fprintf(fp_top3,"<th class=\"header_l\">%s</th>",_("MILLISEC"));
189 if ((TopUserFields & TOPUSERFIELDS_PTIME) != 0)
190 fprintf(fp_top3,"<th class=\"header_l\">%%%s</th>",pgettext("duration","TIME"));
191
192 fputs("</tr></thead>\n",fp_top3);
193
194 greport_prepare();
195
196 if ((line=longline_create())==NULL) {
197 debuga(__FILE__,__LINE__,_("Not enough memory to read file \"%s\"\n"),ListFile);
198 exit(EXIT_FAILURE);
199 }
200
201 while ((warea=longline_read(fp_top1,line))!=NULL) {
202 getword_start(&gwarea,warea);
203 if (getword(user,sizeof(user),&gwarea,'\t')<0) {
204 debuga(__FILE__,__LINE__,_("Invalid user in file \"%s\"\n"),ListFile);
205 exit(EXIT_FAILURE);
206 }
207 if (getword_atoll(&nbytes,&gwarea,'\t')<0) {
208 debuga(__FILE__,__LINE__,_("Invalid number of bytes in file \"%s\"\n"),ListFile);
209 exit(EXIT_FAILURE);
210 }
211 if (getword_atoll(&nacc,&gwarea,'\t')<0) {
212 debuga(__FILE__,__LINE__,_("Invalid number of accesses in file \"%s\"\n"),ListFile);
213 exit(EXIT_FAILURE);
214 }
215 if (getword_atoll(&elap,&gwarea,'\t')<0) {
216 debuga(__FILE__,__LINE__,_("Invalid elapsed time in file \"%s\"\n"),ListFile);
217 exit(EXIT_FAILURE);
218 }
219 if (getword_atoll(&incac,&gwarea,'\t')<0) {
220 debuga(__FILE__,__LINE__,_("Invalid in-cache size in file \"%s\"\n"),ListFile);
221 exit(EXIT_FAILURE);
222 }
223 if (getword_atoll(&oucac,&gwarea,'\n')<0) {
224 debuga(__FILE__,__LINE__,_("Invalid out-of-cache size in file \"%s\"\n"),ListFile);
225 exit(EXIT_FAILURE);
226 }
227 if (nacc < 1)
228 continue;
229 ntopuser=true;
230 if (TopUsersNum>0 && topcount>=TopUsersNum) break;
231
232 uinfo=userinfo_find_from_id(user);
233 if (!uinfo) {
234 debuga(__FILE__,__LINE__,_("Unknown user ID %s in file \"%s\"\n"),user,ListFile);
235 exit(EXIT_FAILURE);
236 }
237 uinfo->topuser=1;
238
239 fputs("<tr>",fp_top3);
240
241 posicao++;
242 if ((TopUserFields & TOPUSERFIELDS_NUM) != 0)
243 fprintf(fp_top3,"<td class=\"data\">%d</td>",posicao);
244
245 if (!indexonly) {
246 if ((TopUserFields & TOPUSERFIELDS_DATE_TIME) !=0 && (ReportType & REPORT_TYPE_DATE_TIME) != 0) {
247 fputs("<td class=\"data2\">",fp_top3);
248 #ifdef HAVE_GD
249 if (Graphs && GraphFont[0]!='\0') {
250 greport_day(uinfo);
251 //fprintf(fp_top3,"<a href=\"%s/graph_day.png\"><img src=\"%s/graph.png\" title=\"%s\" alt=\"G\"></a> ",uinfo->filename,ImageFile,_("Graphic"));
252 fprintf(fp_top3,"<a href=\"%s/graph.html\"><img src=\"%s/graph.png\" title=\"%s\" alt=\"G\"></a> ",uinfo->filename,ImageFile,_("Graphic"));
253 }
254 #endif
255 report_day(uinfo);
256 fprintf(fp_top3,"<a href=\"%s/d%s.html\"><img src=\"%s/datetime.png\" title=\"%s\" alt=\"T\"></a></td>",uinfo->filename,uinfo->filename,ImageFile,_("date/time report"));
257 day_deletefile(uinfo);
258 }
259 }
260 if ((TopUserFields & TOPUSERFIELDS_USERID) != 0) {
261 if ((ReportType & REPORT_TYPE_USERS_SITES) == 0 || indexonly)
262 fprintf(fp_top3,"<td class=\"data2\">%s</td>",uinfo->label);
263 else
264 fprintf(fp_top3,"<td class=\"data2\"><a href=\"%s/%s.html\">%s</a></td>",uinfo->filename,uinfo->filename,uinfo->label);
265 }
266 if ((TopUserFields & TOPUSERFIELDS_USERIP) != 0) {
267 fprintf(fp_top3,"<td class=\"data2\">%s</td>",uinfo->ip);
268 }
269 if ((TopUserFields & TOPUSERFIELDS_CONNECT) != 0) {
270 fputs("<td class=\"data\"",fp_top3);
271 if (SortTableJs[0]) fprintf(fp_top3," sorttable_customkey=\"%"PRId64"\"",(int64_t)nacc);
272 fprintf(fp_top3,">%s</td>",fixnum(nacc,1));
273 }
274 if ((TopUserFields & TOPUSERFIELDS_BYTES) != 0) {
275 fputs("<td class=\"data\"",fp_top3);
276 if (SortTableJs[0]) fprintf(fp_top3," sorttable_customkey=\"%"PRId64"\"",(int64_t)nbytes);
277 fprintf(fp_top3,">%s</td>",fixnum(nbytes,1));
278 }
279 if ((TopUserFields & TOPUSERFIELDS_SETYB) != 0) {
280 perc=(Statis->ttnbytes) ? nbytes * 100. / Statis->ttnbytes : 0.;
281 fprintf(fp_top3,"<td class=\"data\">%3.2lf%%</td>",perc);
282 }
283 if ((TopUserFields & TOPUSERFIELDS_IN_CACHE_OUT) != 0) {
284 inperc=(nbytes) ? incac * 100. / nbytes : 0.;
285 ouperc=(nbytes) ? oucac * 100. / nbytes : 0.;
286 fprintf(fp_top3,"<td class=\"data\">%3.2lf%%</td><td class=\"data\">%3.2lf%%</td>",inperc,ouperc);
287 #ifdef ENABLE_DOUBLE_CHECK_DATA
288 if ((inperc!=0. || ouperc!=0.) && fabs(inperc+ouperc-100.)>=0.01) {
289 debuga(__FILE__,__LINE__,_("The total of the in-cache and cache-miss is not 100%% at position %d (user %s)\n"),posicao,uinfo->label);
290 }
291 #endif
292 }
293 if ((TopUserFields & TOPUSERFIELDS_USED_TIME) != 0) {
294 fputs("<td class=\"data\"",fp_top3);
295 if (SortTableJs[0]) fprintf(fp_top3," sorttable_customkey=\"%"PRId64"\"",(int64_t)elap);
296 fprintf(fp_top3,">%s</td>",buildtime(elap));
297 }
298 if ((TopUserFields & TOPUSERFIELDS_MILISEC) != 0) {
299 fputs("<td class=\"data\"",fp_top3);
300 if (SortTableJs[0]) fprintf(fp_top3," sorttable_customkey=\"%"PRId64"\"",(int64_t)elap);
301 fprintf(fp_top3,">%s</td>",fixnum2(elap,1));
302 }
303 if ((TopUserFields & TOPUSERFIELDS_PTIME) != 0) {
304 perc2=(Statis->ttnelap) ? elap * 100. / Statis->ttnelap : 0.;
305 fprintf(fp_top3,"<td class=\"data\">%3.2lf%%</td>",perc2);
306 }
307
308 fputs("</tr>\n",fp_top3);
309
310 topcount++;
311 }
312 if (FileObject_Close(fp_top1)) {
313 debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),ListFile,FileObject_GetLastCloseError());
314 exit(EXIT_FAILURE);
315 }
316 if (!KeepTempLog && unlink(ListFile)) {
317 debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),ListFile,strerror(errno));
318 exit(EXIT_FAILURE);
319 }
320 longline_destroy(&line);
321
322 if ((TopUserFields & TOPUSERFIELDS_TOTAL) != 0) {
323 fputs("<tfoot><tr>",fp_top3);
324 if ((TopUserFields & TOPUSERFIELDS_NUM) != 0)
325 fputs("<td></td>",fp_top3);
326 if ((TopUserFields & TOPUSERFIELDS_DATE_TIME) !=0 && (ReportType & REPORT_TYPE_DATE_TIME) != 0 && !indexonly)
327 fputs("<td></td>",fp_top3);
328 if ((TopUserFields & TOPUSERFIELDS_USERIP) != 0)
329 fprintf(fp_top3,"<th class=\"header_l\" colspan=\"2\">%s</th>",_("TOTAL"));
330 else
331 fprintf(fp_top3,"<th class=\"header_l\">%s</th>",_("TOTAL"));
332
333 if ((TopUserFields & TOPUSERFIELDS_CONNECT) != 0)
334 fprintf(fp_top3,"<th class=\"header_r\">%s</th>",fixnum(Statis->ttnacc,1));
335 if ((TopUserFields & TOPUSERFIELDS_BYTES) != 0)
336 fprintf(fp_top3,"<th class=\"header_r\">%15s</th>",fixnum(Statis->ttnbytes,1));
337 if ((TopUserFields & TOPUSERFIELDS_SETYB) != 0)
338 fputs("<td></td>",fp_top3);
339 if ((TopUserFields & TOPUSERFIELDS_IN_CACHE_OUT) != 0)
340 {
341 inperc=(Statis->ttnbytes) ? Statis->ttnincache * 100. / Statis->ttnbytes : 0.;
342 ouperc=(Statis->ttnbytes) ? Statis->ttnoucache *100. / Statis->ttnbytes : 0.;
343 fprintf(fp_top3,"<th class=\"header_r\">%3.2lf%%</th><th class=\"header_r\">%3.2lf%%</th>",inperc,ouperc);
344 #ifdef ENABLE_DOUBLE_CHECK_DATA
345 if (fabs(inperc+ouperc-100.)>=0.01) {
346 debuga(__FILE__,__LINE__,_("The total of the in-cache and cache-miss is not 100%%\n"));
347 }
348 #endif
349 }
350 if ((TopUserFields & TOPUSERFIELDS_USED_TIME) != 0)
351 fprintf(fp_top3,"<th class=\"header_r\">%s</th>",buildtime(Statis->ttnelap));
352 if ((TopUserFields & TOPUSERFIELDS_MILISEC) != 0)
353 fprintf(fp_top3,"<th class=\"header_r\">%s</th>",fixnum2(Statis->ttnelap,1));
354
355 fputs("</tr>\n",fp_top3);
356 }
357 greport_cleanup();
358
359 if (ntopuser && (TopUserFields & TOPUSERFIELDS_AVERAGE) != 0) {
360 fputs("<tr>",fp_top3);
361 if ((TopUserFields & TOPUSERFIELDS_NUM) != 0)
362 fputs("<td></td>",fp_top3);
363 if ((TopUserFields & TOPUSERFIELDS_DATE_TIME) !=0 && (ReportType & REPORT_TYPE_DATE_TIME) != 0 && !indexonly)
364 fputs("<td></td>",fp_top3);
365 if ((TopUserFields & TOPUSERFIELDS_USERIP) != 0)
366 fprintf(fp_top3,"<th class=\"header_l\" colspan=\"2\">%s</th>",_("AVERAGE"));
367 else
368 fprintf(fp_top3,"<th class=\"header_l\">%s</th>",_("AVERAGE"));
369
370 if ((TopUserFields & TOPUSERFIELDS_CONNECT) != 0)
371 fprintf(fp_top3,"<th class=\"header_r\">%s</th>",fixnum(Statis->ttnacc/Statis->totuser,1));
372 if ((TopUserFields & TOPUSERFIELDS_BYTES) != 0) {
373 nbytes=(Statis->totuser) ? Statis->ttnbytes / Statis->totuser : 0;
374 fprintf(fp_top3,"<th class=\"header_r\">%15s</th>",fixnum(nbytes,1));
375 }
376 if ((TopUserFields & TOPUSERFIELDS_SETYB) != 0)
377 fputs("<td></td>",fp_top3);
378 if ((TopUserFields & TOPUSERFIELDS_IN_CACHE_OUT) != 0)
379 fputs("<td></td><td></td>",fp_top3);
380 if ((TopUserFields & TOPUSERFIELDS_USED_TIME) != 0)
381 fprintf(fp_top3,"<th class=\"header_r\">%s</th>",buildtime(Statis->ttnelap/Statis->totuser));
382 if ((TopUserFields & TOPUSERFIELDS_MILISEC) != 0)
383 fprintf(fp_top3,"<th class=\"header_r\">%s</th>",fixnum2(Statis->ttnelap/Statis->totuser,1));
384 fputs("</tr></tfoot>\n",fp_top3);
385 }
386
387 fputs("</table></div>\n",fp_top3);
388 write_html_trailer(fp_top3);
389 if (fclose(fp_top3)==EOF) {
390 debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),top3,strerror(errno));
391 exit(EXIT_FAILURE);
392 }
393 }
394
395 /*!
396 Generate the top user email report.
397 */
398 static void TopUser_TextEmail(const char *ListFile,struct TopUserStatistics *Statis,struct SortInfoStruct *SortInfo)
399 {
400 FileObject *fp_top1;
401 FILE *fp_mail;
402 longline line;
403 struct getwordstruct gwarea;
404 char *warea;
405 char user[MAX_USER_LEN];
406 char strip1[MAXLEN], strip2[MAXLEN], strip3[MAXLEN], strip4[MAXLEN], strip5[MAXLEN], strip6[MAXLEN], strip7[MAXLEN];
407 long long int nbytes;
408 long long int nacc;
409 long long int elap, incac, oucac;
410 double perc=0.00;
411 double perc2=0.00;
412 long long int tnbytes=0;
413 long long int avgacc, avgelap;
414 int topcount=0;
415 struct userinfostruct *uinfo;
416 time_t t;
417 struct tm *local;
418 const char *Subject;
419
420 if ((fp_top1=FileObject_Open(ListFile))==NULL) {
421 debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),ListFile,FileObject_GetLastOpenError());
422 exit(EXIT_FAILURE);
423 }
424
425 fp_mail=Email_OutputFile("topuser");
426
427 if ((line=longline_create())==NULL) {
428 debuga(__FILE__,__LINE__,_("Not enough memory to read file \"%s\"\n"),ListFile);
429 exit(EXIT_FAILURE);
430 }
431
432 safe_strcpy(strip1,_("Squid User Access Report"),sizeof(strip1));
433 strip_latin(strip1);
434 fprintf(fp_mail,"%s\n",strip1);
435
436 snprintf(strip1,sizeof(strip1),_("Sort: %s, %s"),SortInfo->sort_field,SortInfo->sort_order);
437 strip_latin(strip1);
438 fprintf(fp_mail,"%s\n",strip1);
439
440 snprintf(strip1,sizeof(strip1),_("Period: %s"),period.text);
441 strip_latin(strip1);
442 fprintf(fp_mail,"%s\n\n",strip1);
443
444 safe_strcpy(strip1,_("NUM"),sizeof(strip1));
445 strip_latin(strip1);
446 safe_strcpy(strip2,_("USERID"),sizeof(strip2));
447 strip_latin(strip2);
448 safe_strcpy(strip3,_("CONNECT"),sizeof(strip3));
449 strip_latin(strip3);
450 safe_strcpy(strip4,_("BYTES"),sizeof(strip4));
451 strip_latin(strip4);
452 safe_strcpy(strip5,_("ELAPSED TIME"),sizeof(strip5));
453 strip_latin(strip5);
454 safe_strcpy(strip6,_("MILLISEC"),sizeof(strip6));
455 strip_latin(strip6);
456 safe_strcpy(strip7,pgettext("duration","TIME"),sizeof(strip7));
457 strip_latin(strip7);
458
459 fprintf(fp_mail,"%-7s %-20s %-9s %-15s %%%-6s %-11s %-10s %%%-7s\n------- -------------------- -------- --------------- ------- ---------- ---------- -------\n",strip1,strip2,strip3,strip4,strip4,strip5,strip6,strip7);
460
461
462 while ((warea=longline_read(fp_top1,line))!=NULL) {
463 getword_start(&gwarea,warea);
464 if (getword(user,sizeof(user),&gwarea,'\t')<0) {
465 debuga(__FILE__,__LINE__,_("Invalid user in file \"%s\"\n"),ListFile);
466 exit(EXIT_FAILURE);
467 }
468 if (getword_atoll(&nbytes,&gwarea,'\t')<0) {
469 debuga(__FILE__,__LINE__,_("Invalid number of bytes in file \"%s\"\n"),ListFile);
470 exit(EXIT_FAILURE);
471 }
472 if (getword_atoll(&nacc,&gwarea,'\t')<0) {
473 debuga(__FILE__,__LINE__,_("Invalid number of accesses in file \"%s\"\n"),ListFile);
474 exit(EXIT_FAILURE);
475 }
476 if (getword_atoll(&elap,&gwarea,'\t')<0) {
477 debuga(__FILE__,__LINE__,_("Invalid elapsed time in file \"%s\"\n"),ListFile);
478 exit(EXIT_FAILURE);
479 }
480 if (getword_atoll(&incac,&gwarea,'\t')<0) {
481 debuga(__FILE__,__LINE__,_("Invalid in-cache size in file \"%s\"\n"),ListFile);
482 exit(EXIT_FAILURE);
483 }
484 if (getword_atoll(&oucac,&gwarea,'\n')<0) {
485 debuga(__FILE__,__LINE__,_("Invalid out-of-cache size in file \"%s\"\n"),ListFile);
486 exit(EXIT_FAILURE);
487 }
488 if (nacc < 1)
489 continue;
490 if (TopUsersNum>0 && topcount>=TopUsersNum) break;
491
492 uinfo=userinfo_find_from_id(user);
493 if (!uinfo) {
494 debuga(__FILE__,__LINE__,_("Unknown user ID %s in file \"%s\"\n"),user,ListFile);
495 exit(EXIT_FAILURE);
496 }
497 uinfo->topuser=1;
498
499 perc=(Statis->ttnbytes) ? nbytes * 100. / Statis->ttnbytes : 0;
500 perc2=(Statis->ttnelap) ? elap * 100. / Statis->ttnelap : 0;
501
502 topcount++;
503
504 #if defined(__FreeBSD__)
505 fprintf(fp_mail,"%7d %20s %8lld %15s %5.2lf%% %10s %10qu %3.2lf%%\n",topcount,uinfo->label,nacc,fixnum(nbytes,1),perc,buildtime(elap),elap,perc2);
506 #else
507 fprintf(fp_mail,"%7d %20s %8"PRIu64" %15s %6.2lf%% %10s %10"PRIu64" %3.2lf%%\n",topcount,uinfo->label,(uint64_t)nacc,fixnum(nbytes,1),perc,buildtime(elap),(uint64_t)elap,perc2);
508 #endif
509 }
510 if (FileObject_Close(fp_top1)) {
511 debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),ListFile,FileObject_GetLastCloseError());
512 exit(EXIT_FAILURE);
513 }
514 if (!KeepTempLog && unlink(ListFile)) {
515 debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),ListFile,strerror(errno));
516 exit(EXIT_FAILURE);
517 }
518 longline_destroy(&line);
519
520 // output total
521 fputs("------- -------------------- -------- --------------- ------- ---------- ---------- -------\n",fp_mail);
522 #if defined(__FreeBSD__)
523 fprintf(fp_mail,"%-7s %20s %8qu %15s %8s %9s %10qu\n",_("TOTAL")," ",Statis->ttnacc,fixnum(Statis->ttnbytes,1)," ",buildtime(Statis->ttnelap),Statis->ttnelap);
524 #else
525 fprintf(fp_mail,"%-7s %20s %8"PRIu64" %15s %8s %9s %10"PRIu64"\n",_("TOTAL")," ",(uint64_t)Statis->ttnacc,fixnum(Statis->ttnbytes,1)," ",buildtime(Statis->ttnelap),(uint64_t)Statis->ttnelap);
526 #endif
527
528 // compute and write average
529 if (Statis->totuser>0) {
530 tnbytes=Statis->ttnbytes / Statis->totuser;
531 avgacc=Statis->ttnacc/Statis->totuser;
532 avgelap=Statis->ttnelap/Statis->totuser;
533 } else {
534 tnbytes=0;
535 avgacc=0;
536 avgelap=0;
537 }
538
539 safe_strcpy(strip1,_("AVERAGE"),sizeof(strip1));
540 strip_latin(strip1);
541 #if defined(__FreeBSD__)
542 fprintf(fp_mail,"%-7s %20s %8qu %15s %8s %9s %10qu\n",strip1," ",avgacc,fixnum(tnbytes,1)," ",buildtime(avgelap),avgelap);
543 #else
544 fprintf(fp_mail,"%-7s %20s %8"PRIu64" %15s %8s %9s %10"PRIu64"\n",strip1," ",(uint64_t)avgacc,fixnum(tnbytes,1)," ",buildtime(avgelap),(uint64_t)avgelap);
545 #endif
546
547 t = time(NULL);
548 local = localtime(&t);
549 fprintf(fp_mail, "\n%s\n", asctime(local));
550
551 /* TRANSLATORS: This is the e-mail subject. */
552 Subject=_("Sarg: top user report");
553 Email_Send(fp_mail,Subject);
554 }
555
556 /*!
557 * Produce a report with the user downloading the most data.
558 */
559 void topuser(void)
560 {
561 FileObject *fp_in = NULL;
562 FILE *fp_top2;
563 char wger[MAXLEN];
564 char top1[MAXLEN];
565 char top2[MAXLEN];
566 longline line;
567 long long int tnacc=0;
568 long long int tnbytes=0, tnelap=0;
569 long long int tnincache=0, tnoucache=0;
570 char *warea;
571 struct generalitemstruct item;
572 char olduser[MAX_USER_LEN], csort[MAXLEN];
573 const char *sfield="-n -k 2,2";
574 const char *order;
575 int cstatus;
576 struct TopUserStatistics Statis;
577 struct SortInfoStruct SortInfo;
578
579 if (debugz>=LogLevel_Process)
580 debuga(__FILE__,__LINE__,_("Creating top users report...\n"));
581
582 memset(&Statis,0,sizeof(Statis));
583
584 format_path(__FILE__, __LINE__, wger, sizeof(wger), "%s/sarg-general", outdirname);
585 if ((fp_in=FileObject_Open(wger))==NULL) {
586 debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),wger,FileObject_GetLastOpenError());
587 exit(EXIT_FAILURE);
588 }
589
590 format_path(__FILE__, __LINE__, top2, sizeof(top2), "%s/top.tmp", outdirname);
591 if ((fp_top2=fopen(top2,"w"))==NULL) {
592 debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),top2,strerror(errno));
593 exit(EXIT_FAILURE);
594 }
595
596 olduser[0]='\0';
597
598 if ((line=longline_create())==NULL) {
599 debuga(__FILE__,__LINE__,_("Not enough memory to read file \"%s\"\n"),wger);
600 exit(EXIT_FAILURE);
601 }
602
603 while ((warea=longline_read(fp_in,line))!=NULL) {
604 ger_read(warea,&item,wger);
605 if (item.total) continue;
606 if (strcmp(olduser,item.user) != 0) {
607 Statis.totuser++;
608
609 if (olduser[0] != '\0') {
610 /*
611 This complicated printf is due to Microsoft's inability to comply with any standard. Msvcrt is unable
612 to print a long long int unless it is exactly 64-bits long.
613 */
614 fprintf(fp_top2,"%s\t%"PRIu64"\t%"PRIu64"\t%"PRIu64"\t%"PRIu64"\t%"PRIu64"\n",olduser,(uint64_t)tnbytes,(uint64_t)tnacc,(uint64_t)tnelap,(uint64_t)tnincache,(uint64_t)tnoucache);
615
616 Statis.ttnbytes+=tnbytes;
617 Statis.ttnacc+=tnacc;
618 Statis.ttnelap+=tnelap;
619 Statis.ttnincache+=tnincache;
620 Statis.ttnoucache+=tnoucache;
621 }
622 safe_strcpy(olduser,item.user,sizeof(olduser));
623 tnbytes=0;
624 tnacc=0;
625 tnelap=0;
626 tnincache=0;
627 tnoucache=0;
628 }
629
630 tnbytes+=item.nbytes;
631 tnacc+=item.nacc;
632 tnelap+=item.nelap;
633 tnincache+=item.incache;
634 tnoucache+=item.oucache;
635 }
636 if (FileObject_Close(fp_in)) {
637 debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),wger,FileObject_GetLastCloseError());
638 exit(EXIT_FAILURE);
639 }
640 longline_destroy(&line);
641
642 if (olduser[0] != '\0') {
643 /*
644 This complicated printf is due to Microsoft's inability to comply with any standard. Msvcrt is unable
645 to print a long long int unless it is exactly 64-bits long.
646 */
647 fprintf(fp_top2,"%s\t%"PRIu64"\t%"PRIu64"\t%"PRIu64"\t%"PRIu64"\t%"PRIu64"\n",olduser,(uint64_t)tnbytes,(uint64_t)tnacc,(uint64_t)tnelap,(uint64_t)tnincache,(uint64_t)tnoucache);
648
649 Statis.ttnbytes+=tnbytes;
650 Statis.ttnacc+=tnacc;
651 Statis.ttnelap+=tnelap;
652 Statis.ttnincache+=tnincache;
653 Statis.ttnoucache+=tnoucache;
654 }
655 if (fclose(fp_top2)==EOF) {
656 debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),top2,strerror(errno));
657 exit(EXIT_FAILURE);
658 }
659
660 #ifdef ENABLE_DOUBLE_CHECK_DATA
661 if (Statis.ttnacc!=globstat.nacc || Statis.ttnbytes!=globstat.nbytes || Statis.ttnelap!=globstat.elap ||
662 Statis.ttnincache!=globstat.incache || Statis.ttnoucache!=globstat.oucache) {
663 debuga(__FILE__,__LINE__,_("Total statistics mismatch when reading \"%s\" to produce the top users\n"),wger);
664 exit(EXIT_FAILURE);
665 }
666 #endif
667
668 set_total_users(Statis.totuser);
669
670 if ((TopuserSort & TOPUSER_SORT_USER) != 0) {
671 sfield="-k 1,1";
672 SortInfo.sort_field=_("user");
673 } else if ((TopuserSort & TOPUSER_SORT_CONNECT) != 0) {
674 sfield="-n -k 3,3";
675 SortInfo.sort_field=_("connect");
676 } else if ((TopuserSort & TOPUSER_SORT_TIME) != 0) {
677 sfield="-n -k 4,4";
678 SortInfo.sort_field=pgettext("duration","time");
679 } else {
680 SortInfo.sort_field=_("bytes");
681 }
682
683 if ((TopuserSort & TOPUSER_SORT_REVERSE) == 0) {
684 order="";
685 SortInfo.sort_order=_("normal");
686 } else {
687 order="-r";
688 SortInfo.sort_order=_("reverse");
689 }
690
691 format_path(__FILE__, __LINE__, top1, sizeof(top1), "%s/top", outdirname);
692 if (snprintf(csort,sizeof(csort),"sort -T \"%s\" -t \"\t\" %s %s -o \"%s\" \"%s\"", tmp, order, sfield, top1, top2)>=sizeof(csort)) {
693 debuga(__FILE__,__LINE__,_("Sort command too long when sorting file \"%s\" to \"%s\"\n"),top2,top1);
694 exit(EXIT_FAILURE);
695 }
696 cstatus=system(csort);
697 if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
698 debuga(__FILE__,__LINE__,_("sort command return status %d\n"),WEXITSTATUS(cstatus));
699 debuga(__FILE__,__LINE__,_("sort command: %s\n"),csort);
700 exit(EXIT_FAILURE);
701 }
702
703 if (!KeepTempLog && unlink(top2)) {
704 debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),top2,strerror(errno));
705 exit(EXIT_FAILURE);
706 }
707
708 if (email[0])
709 TopUser_TextEmail(top1,&Statis,&SortInfo);
710 else
711 TopUser_HtmlReport(top1,&Statis,&SortInfo);
712 }