]> git.ipfire.org Git - thirdparty/sarg.git/commitdiff
Add dynamic sorting of some tables
authorFrédéric Marchal <fmarchal@users.sourceforge.net>
Sat, 20 Nov 2010 22:07:40 +0000 (22:07 +0000)
committerFrédéric Marchal <fmarchal@users.sourceforge.net>
Sat, 20 Nov 2010 22:07:40 +0000 (22:07 +0000)
Allow the use of a javascript script to dynamically sort some tables.

The code is tailored for sorttable.js by Stuart Langridge found at
http://www.kryogenix.org/code/browser/sorttable/.

13 files changed:
ChangeLog
documentation/util.txt
getconf.c
html.c
include/conf.h
include/defs.h
index.c
log.c
sarg.conf
siteuser.c
topsites.c
topuser.c
util.c

index e4ab1bda5f0260a2e0acf48c239128018b275a5f..c6159c30f9638b385ad721f576a73f7b4e8319fb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 SARG ChangeLog
 
+Nov-20-2010 Version 2.3.2-pre1
+               - Add support for sorttable.js (http://www.kryogenix.org/code/browser/sorttable/) to dynamically sort some tables.
+
 Sep-18-2010 Version 2.3.1
                - Remove the distinct printf for the alpha architecture as it doesn't work anymore and is not necessary anyway.
                - Don't abort if "onload" or "script" is found in the user agent string.
index 97588715a0d50b09c9684c6b9f633354358e87a9..41772b2d4877f85a219f854270a4ca5eec0b42be 100644 (file)
@@ -416,15 +416,15 @@ the <tt>sarg-users</tt> file of the report data's directory.
 
 
 
-/*! \fn void obttotal(const char *dirname, const char *name, char *tbytes, int nuser, char *media)
+/*! \fn void obttotal(const char *dirname, const char *name, int nuser, long long int *tbytes, long long int *media)
 Count the total size transfered in a report directory and compute the average number of bytes
 per entry.
 
 \param dirname The directory containing the reports.
 \param name The name of the report directory whose <tt>sarg-general</tt> file must be read.
-\param tbytes A buffer to store the total number of bytes from this report.
 \param nuser The number of entries in the report directory.
-\param media A buffer to store the average number of bytes per entry.
+\param tbytes A variable to store the total number of bytes from this report.
+\param media A variable to store the average number of bytes per entry.
 */
 
 
index a5029780d0cd733f8c9d75442ae91d9d82835d34..e85a3ca15792efe58620c1a91e7ae158e40aca38 100644 (file)
--- a/getconf.c
+++ b/getconf.c
@@ -726,6 +726,8 @@ static void parmtest(char *buf)
 
    if (getparam_string("graph_font",buf,GraphFont,sizeof(GraphFont))>0) return;
 
+   if (getparam_string("sorttable",buf,SortTableJs,sizeof(SortTableJs))>0) return;
+
    if(strstr(buf,"squid24") != 0) {
       squid24=true;
       return;
diff --git a/html.c b/html.c
index 4611ebcf8d78b4692c950e9bf4991aa9b7a801df..b84093a40c8b9af25acfeef8f2f1178cbce020f7 100644 (file)
--- a/html.c
+++ b/html.c
@@ -234,13 +234,20 @@ void htmlrel(void)
       fprintf(fp_ou,"<tr><th class=\"header_c\">%s</th></tr>\n",_("User report"));
       close_html_header(fp_ou);
 
-      fputs("<div class=\"report\"><table cellpadding=\"2\" cellspacing=\"1\">\n",fp_ou);
+      fputs("<div class=\"report\"><table cellpadding=\"2\" cellspacing=\"1\"",fp_ou);
+      if (SortTableJs[0]) fputs(" class=\"sortable\"",fp_ou);
+      fputs(">\n",fp_ou);
 
+      /*! \bug This line lays before the header of the table and is therefore invalid
+      HTML. It will also break the sorttable script. Beside, I suspect it serves no purpose.
+      */
       if(denied_report[0]!='\0') {
          fprintf(fp_ou,"<tr><td class=\"header_l\" colspan=\"11\"><a href=\"denied_%s.html\">%s</a> %s</td></tr>\n",denied_report,_("SmartFilter"),_("Report"));
       }
 
-      fprintf(fp_ou,"<tr><th></th><th class=\"header_l\">%s</th>",_("ACCESSED SITE"));
+      fputs("<thead><tr><th class=\"sorttable_nosort\"></th><th class=\"header_l",fp_ou);
+      if (SortTableJs[0]) fputs(" sorttable_alpha",fp_ou);
+      fprintf(fp_ou,"\">%s</th>",_("ACCESSED SITE"));
 
       if((UserReportFields & USERREPORTFIELDS_CONNECT) != 0)
          fprintf(fp_ou,"<th class=\"header_l\">%s</th>",_("CONNECT"));
@@ -249,7 +256,7 @@ void htmlrel(void)
       if((UserReportFields & USERREPORTFIELDS_SETYB) != 0)
          fprintf(fp_ou,"<th class=\"header_l\">%%%s</th>",_("BYTES"));
       if((UserReportFields & USERREPORTFIELDS_IN_CACHE_OUT) != 0)
-         fprintf(fp_ou,"<th class=\"header_c\" colspan=\"2\">%s</th>",_("IN-CACHE-OUT"));
+         fprintf(fp_ou,"<th class=\"header_c\" colspan=\"2\">%s</th><th style=\"display:none;\"></th>",_("IN-CACHE-OUT"));
       if((UserReportFields & USERREPORTFIELDS_USED_TIME) != 0)
          fprintf(fp_ou,"<th class=\"header_l\">%s</th>",_("ELAPSED TIME"));
       if((UserReportFields & USERREPORTFIELDS_MILISEC) != 0)
@@ -257,7 +264,7 @@ void htmlrel(void)
       if((UserReportFields & USERREPORTFIELDS_PTIME) != 0)
          fprintf(fp_ou,"<th class=\"header_l\">%%%s</th>",_("TIME"));
 
-      fputs("</tr>\n",fp_ou);
+      fputs("</tr></thead>\n",fp_ou);
 
       if(debug) {
          debuga(_("Making report: %s\n"),uinfo->id);
@@ -325,10 +332,16 @@ void htmlrel(void)
                fputs("</a></td>",fp_ou);
             }
 
-            if((UserReportFields & USERREPORTFIELDS_CONNECT) != 0)
-               fprintf(fp_ou,"<td class=\"data\">%s</td>",fixnum(twork,1));
-            if((UserReportFields & USERREPORTFIELDS_BYTES) != 0)
-               fprintf(fp_ou,"<td class=\"data\">%s</td>",fixnum(nnbytes,1));
+            if((UserReportFields & USERREPORTFIELDS_CONNECT) != 0) {
+               fputs("<td class=\"data\"",fp_ou);
+               if (SortTableJs[0]) fprintf(fp_ou," sorttable_customkey=\"%"PRId64"\"",(int64_t)twork);
+               fprintf(fp_ou,">%s</td>",fixnum(twork,1));
+            }
+            if((UserReportFields & USERREPORTFIELDS_BYTES) != 0) {
+               fputs("<td class=\"data\"",fp_ou);
+               if (SortTableJs[0]) fprintf(fp_ou," sorttable_customkey=\"%"PRId64"\"",(int64_t)nnbytes);
+               fprintf(fp_ou,">%s</td>",fixnum(nnbytes,1));
+            }
             if((UserReportFields & USERREPORTFIELDS_SETYB) != 0) {
                perc=(tnbytes) ? nnbytes * 100. / tnbytes : 0.;
                fprintf(fp_ou,"<td class=\"data\">%3.2lf%%</td>",perc);
@@ -338,8 +351,11 @@ void htmlrel(void)
                ouperc=(nnbytes) ? oucache * 100. / nnbytes : 0.;
                fprintf(fp_ou,"<td class=\"data\">%3.2lf%%</td><td class=\"data\">%3.2lf%%</td>",inperc,ouperc);
             }
-            if((UserReportFields & USERREPORTFIELDS_USED_TIME) != 0)
-               fprintf(fp_ou,"<td class=\"data\">%s</td>",buildtime(nnelap));
+            if((UserReportFields & USERREPORTFIELDS_USED_TIME) != 0) {
+               fputs("<td class=\"data\"",fp_ou);
+               if (SortTableJs[0]) fprintf(fp_ou," sorttable_customkey=\"%"PRId64"\"",(int64_t)nnelap);
+               fprintf(fp_ou,">%s</td>",buildtime(nnelap));
+            }
             if((UserReportFields & USERREPORTFIELDS_MILISEC) != 0)
                fprintf(fp_ou,"<td class=\"data\">%s</td>",fixnum2(nnelap,1));
             if((UserReportFields & USERREPORTFIELDS_PTIME) != 0) {
@@ -505,6 +521,9 @@ void htmlrel(void)
          unlink(arqip);
       unlink(arqin);
 
+      if ((UserReportFields & (USERREPORTFIELDS_TOTAL | USERREPORTFIELDS_AVERAGE)) != 0)
+         fputs("<tfoot>",fp_ou);
+
       if((UserReportFields & USERREPORTFIELDS_TOTAL) != 0) {
          fprintf(fp_ou,"<tr><th></th><th class=\"header_l\">%s</th>",_("TOTAL"));
          if((UserReportFields & USERREPORTFIELDS_CONNECT) != 0)
@@ -589,6 +608,9 @@ void htmlrel(void)
          fputs("</tr>\n",fp_ou);
       }
 
+      if ((UserReportFields & (USERREPORTFIELDS_TOTAL | USERREPORTFIELDS_AVERAGE)) != 0)
+         fputs("</tfoot>",fp_ou);
+
       fputs("</table></div>\n",fp_ou);
       if (write_html_trailer(fp_ou)<0)
          debuga(_("Write error in file %s\n"),arqou);
index 96b0c9dba574bbb37817b750db526fc04aadda48..01133649c41a9b90a621af0e3f6850c1a4b17c42 100755 (executable)
@@ -390,9 +390,6 @@ char val8[MAXLEN];
 char val9[MAXLEN];
 char val10[MAXLEN];
 char val11[MAXLEN];
-char wwork1[MAXLEN];
-char wwork2[MAXLEN];
-char wwork3[MAXLEN];
 char mask[MAXLEN];
 char site[MAXLEN];
 char us[50];
@@ -415,6 +412,8 @@ char LDAPBaseSearch[255];
 char LDAPFilterSearch[512];
 char LDAPTargetAttr[64];
 char GraphFont[MAXLEN];
+//! The full path to sorttable.js if the table in the reports must be dynamicaly sorted.
+char SortTableJs[256];
 
 int  idate;
 int  smartfilter;
index 6bfe6562895c4d59451a2a7f5222fbf2e2a93d6d..ee237f9020150960ba986d73e421afe68a8e3c48 100755 (executable)
@@ -231,7 +231,7 @@ void obtdate(const char *dirname, const char *name, char *data);
 void formatdate(char *date,int date_size,int year,int month,int day,int hour,int minute,int second,int dst);
 void computedate(int year,int month,int day,struct tm *t);
 int obtuser(const char *dirname, const char *name);
-void obttotal(const char *dirname, const char *name, char *tbytes, int nuser, char *media);
+void obttotal(const char *dirname, const char *name, int nuser, long long int *tbytes, long long int *media);
 void version(void);
 int vercode(const char *code);
 void load_excludecodes(const char *ExcludeCodes);
diff --git a/index.c b/index.c
index 8529b092ba3d59f6f42f175618e3f9a073a576a6..25daa19a4e68bd97ca20589e442ffb5b3b495113 100644 (file)
--- a/index.c
+++ b/index.c
@@ -292,10 +292,10 @@ static void make_file_index(void)
    struct dirent *direntp;
    char wdir[MAXLEN];
    char data[80];
-   char tbytes[20];
-   char media[20];
    char ftime[128];
    char day[6], mon[8], year[40], hour[10];
+   long long int tbytes;
+   long long int media;
    int iyear, imonth, iday, ihour, iminute, isecond, idst;
    int nsort;
    int nallocated;
@@ -412,16 +412,30 @@ static void make_file_index(void)
    }
    write_html_header(fp_ou,0,ngettext("SARG report","SARG reports",nsort));
    close_html_header(fp_ou);
-   fputs("<div class=\"index\"><table cellpadding=\"1\" cellspacing=\"2\">\n<tr><td></td><td></td></tr>\n",fp_ou);
-   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><th class=\"header_l\">%s</th></tr>\n",_("FILE/PERIOD"),_("CREATION DATE"),_("USERS"),_("BYTES"),_("AVERAGE"));
+   fputs("<div class=\"index\"><table cellpadding=\"1\" cellspacing=\"2\"",fp_ou);
+   if (SortTableJs[0]) fputs(" class=\"sortable\"",fp_ou);
+   fputs(">\n",fp_ou);
+   fprintf(fp_ou,"<thead><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><th class=\"header_l\">%s</th></tr></thead>\n",_("FILE/PERIOD"),_("CREATION DATE"),_("USERS"),_("BYTES"),_("AVERAGE"));
    for (i=0 ; i<nsort ; i++) {
       if (order>0)
          item=sortlist[i];
       else
          item=sortlist[nsort-i-1];
       tuser=obtuser(outdir,item->dirname);
-      obttotal(outdir,item->dirname,tbytes,tuser,media);
-      fprintf(fp_ou,"<tr><td class=\"data2\"><a href='%s/%s'>%s</a></td><td class=\"data2\">%s</td><td class=\"data\">%d</td><td class=\"data\">%s</td><td class=\"data\">%s</td></tr>\n",item->dirname,ReplaceIndex,item->dirname,item->date,tuser,tbytes,media);
+      obttotal(outdir,item->dirname,tuser,&tbytes,&media);
+      fputs("<tr><td class=\"data2\"",fp_ou);
+      if (SortTableJs[0]) fprintf(fp_ou," sorttable_customkey=\"%d\"",item->sortnum);
+      fprintf(fp_ou,"><a href='%s/%s'>%s</a></td>",item->dirname,ReplaceIndex,item->dirname);
+      fputs("<td class=\"data2\"",fp_ou);
+      if (SortTableJs[0]) fprintf(fp_ou," sorttable_customkey=\"%s\"",item->creationdate);
+      fprintf(fp_ou,">%s</td>",item->date);
+      fprintf(fp_ou,"<td class=\"data\">%d</td>",tuser);
+      fputs("<td class=\"data\"",fp_ou);
+      if (SortTableJs[0]) fprintf(fp_ou," sorttable_customkey=\"%"PRId64"\"",(int64_t)tbytes);
+      fprintf(fp_ou,">%s</td>",fixnum(tbytes,1));
+      fputs("<td class=\"data\"",fp_ou);
+      if (SortTableJs[0]) fprintf(fp_ou," sorttable_customkey=\"%"PRId64"\"",(int64_t)media);
+      fprintf(fp_ou,">%s</td></tr>\n",fixnum(media,1));
    }
    fputs("</table></div>\n",fp_ou);
    if (write_html_trailer(fp_ou)<0)
diff --git a/log.c b/log.c
index e5868ed20231660e2e12765d18ba5b7d5cc260b5..46485ed72cf18923d94821d1a12b50417a06ef2a 100644 (file)
--- a/log.c
+++ b/log.c
@@ -290,6 +290,7 @@ int main(int argc,char *argv[])
    LDAPBaseSearch[0]='\0';
    strcpy(LDAPFilterSearch, "(uid=%s)");
    strcpy(LDAPTargetAttr, "cn");
+   SortTableJs[0]='\0';
 
    dia[0]='\0';
    mes[0]='\0';
index 3d72522ba5af59cab0e57c04a8c69eb4aa187325..7bee12607a7266e0cb92c96b74cd40ba9c8a422d 100644 (file)
--- a/sarg.conf
+++ b/sarg.conf
 #      Compatilibity with squid version <= 2.4 when using emulate_http_log on
 #
 # squid24 off
+
+# TAG: sorttable path
+#      The full path to a javascript script to dynamically sort the tables.
+#      The path is the path a browser must follow to find the script.
+#      If this entry is set, each sortable table will have the "sortable" class set.
+#      You may have a look at http://www.kryogenix.org/code/browser/sorttable/
+#      for such as implementation.
+#
+# sorttable /sorttable.js
index 36e53f1417c7c34862c5b2bc288c5ac48a1dd6de..e1e6c284b434e5d1afc2e379faf6ee65fa0db92a 100644 (file)
@@ -86,11 +86,16 @@ void siteuser(void)
    fprintf(fp_ou,"<tr><th class=\"header_c\">%s</th></tr>\n",_("Sites & Users"));
    close_html_header(fp_ou);
 
-   fputs("<div class=\"report\"><table cellpadding=\"0\" cellspacing=\"2\">\n",fp_ou);
+   fputs("<div class=\"report\"><table cellpadding=\"0\" cellspacing=\"2\"",fp_ou);
+   if (SortTableJs[0]) fputs(" class=\"sortable\"",fp_ou);
+   fprintf(fp_ou,">\n<thead><tr><th class=\"header_l\">%s</th><th class=\"header_l",_("NUM"));
+   if (SortTableJs[0]) fputs(" sorttable_alpha",fp_ou);
+   fprintf(fp_ou,"\">%s</th>",_("ACCESSED SITE"));
    if(BytesInSitesUsersReport)
-      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",_("NUM"),_("ACCESSED SITE"),_("BYTES"),_("USERS"));
-   else
-      fprintf(fp_ou,"<tr><th class=\"header_l\">%s</th><th class=\"header_l\">%s</th><th class=\"header_l\">%s</th></tr>\n",_("NUM"),_("ACCESSED SITE"),_("USERS"));
+      fprintf(fp_ou,"<th class=\"header_l\">%s</th>",_("BYTES"));
+   fputs("<th class=\"header_l",fp_ou);
+   if (SortTableJs[0]) fputs(" sorttable_alpha",fp_ou);
+   fprintf(fp_ou,"\">%s</th></tr></thead>\n",_("USERS"));
 
    ourl=NULL;
    ourl_size=0;
@@ -161,8 +166,11 @@ void siteuser(void)
          output_html_string(fp_ou,ourl,100);
          fputs("</a></td>",fp_ou);
 
-         if(BytesInSitesUsersReport)
-            fprintf(fp_ou,"<td class=\"data\">%s</td>",fixnum(obytes,1));
+         if (BytesInSitesUsersReport) {
+            fputs("<td class=\"data\"",fp_ou);
+            if (SortTableJs[0]) fprintf(fp_ou," sorttable_customkey=\"%"PRId64"\"",(int64_t)obytes);
+            fprintf(fp_ou,">%s</td>",fixnum(obytes,1));
+         }
          fprintf(fp_ou,"<td class=\"data2\">%s</td></tr>\n",users);
 
          regs++;
@@ -198,7 +206,9 @@ void siteuser(void)
       output_html_string(fp_ou,ourl,100);
       fputs("</a></td>",fp_ou);
       if (BytesInSitesUsersReport) {
-         fprintf(fp_ou,"<td class=\"data\">%s</td>",fixnum(obytes,1));
+         fputs("<td class=\"data\"",fp_ou);
+         if (SortTableJs[0]) fprintf(fp_ou," sorttable_customkey=\"%"PRId64"\"",(int64_t)obytes);
+         fprintf(fp_ou,">%s</td>",fixnum(obytes,1));
       }
       fprintf(fp_ou,"<td class=\"data2\">%s</td></tr>\n",users);
    }
index 7207b4de906af535693b8e797a76e32b81f76568..0cea0a5a00842634a83923537950a0b903dcccb4 100644 (file)
@@ -194,8 +194,12 @@ void topsites(void)
    fputs("</th></tr>\n",fp_ou);
    close_html_header(fp_ou);
 
-   fputs("<div class=\"report\"><table cellpadding=\"1\" cellspacing=\"2\">\n",fp_ou);
-   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><th class=\"header_l\">%s</th></tr>\n",_("NUM"),_("ACCESSED SITE"),_("CONNECT"),_("BYTES"),_("TIME"));
+   fputs("<div class=\"report\"><table cellpadding=\"1\" cellspacing=\"2\"",fp_ou);
+   if (SortTableJs[0]) fputs(" class=\"sortable\"",fp_ou);
+   fputs(">\n",fp_ou);
+   fprintf(fp_ou,"<thead><tr><th class=\"header_l\">%s</th><th class=\"header_l",_("NUM"));
+   if (SortTableJs[0]) fputs(" sorttable_alpha",fp_ou);
+   fprintf(fp_ou,"\">%s</th><th class=\"header_l\">%s</th><th class=\"header_l\">%s</th><th class=\"header_l\">%s</th></tr></thead>\n",_("ACCESSED SITE"),_("CONNECT"),_("BYTES"),_("TIME"));
 
    regs=0;
    ntopsites = 0;
@@ -225,10 +229,6 @@ void topsites(void)
       twork2=nbytes;
       twork3=ntime;
 
-      strcpy(wwork1,fixnum(twork1,1));
-      strcpy(wwork2,fixnum(twork2,1));
-      strcpy(wwork3,fixtime(twork3));
-
       fprintf(fp_ou,"<tr><td class=\"data\">%d</td><td class=\"data2 link\">",++regs);
 
       if(BlockIt[0] != '\0') {
@@ -241,7 +241,15 @@ void topsites(void)
       output_html_url(fp_ou,url);
       fputs("\">",fp_ou);
       output_html_string(fp_ou,url,100);
-      fprintf(fp_ou,"</a></td><td class=\"data\">%s</td><td class=\"data\">%s</td><td class=\"data\">%s</td></tr>\n",wwork1,wwork2,wwork3);
+      fputs("</a></td><td class=\"data\"",fp_ou);
+      if (SortTableJs[0]) fprintf(fp_ou," sorttable_customkey=\"%"PRId64"\"",(uint64_t)twork1);
+      fprintf(fp_ou,">%s</td>",fixnum(twork1,1));
+      fputs("<td class=\"data\"",fp_ou);
+      if (SortTableJs[0]) fprintf(fp_ou," sorttable_customkey=\"%"PRId64"\"",(uint64_t)twork2);
+      fprintf(fp_ou,">%s</td>",fixnum(twork2,1));
+      fputs("<td class=\"data\"",fp_ou);
+      if (SortTableJs[0]) fprintf(fp_ou," sorttable_customkey=\"%"PRId64"\"",(uint64_t)twork3);
+      fprintf(fp_ou,">%s</td></tr>\n",fixtime(twork3));
    }
    fclose(fp_in);
    longline_destroy(&line);
index 37082b7d62b8d36634365544efd1da6428ded513..d4245f13f75667f6306b6d1e362b5a4bf9d99dbb 100644 (file)
--- a/topuser.c
+++ b/topuser.c
@@ -207,15 +207,23 @@ void topuser(void)
       return;
    }
 
-   fputs("<div class=\"report\"><table cellpadding=\"1\" cellspacing=\"2\">\n",fp_top3);
-   fputs("<tr>",fp_top3);
+   fputs("<div class=\"report\"><table cellpadding=\"1\" cellspacing=\"2\"",fp_top3);
+   if (SortTableJs[0])
+      fputs(" class=\"sortable\"",fp_top3);
+   fputs(">\n<thead><tr>",fp_top3);
 
    if((TopUserFields & TOPUSERFIELDS_NUM) != 0)
       fprintf(fp_top3,"<th class=\"header_l\">%s</th>",_("NUM"));
-   if((TopUserFields & TOPUSERFIELDS_DATE_TIME) !=0 && (ReportType & REPORT_TYPE_DATE_TIME) != 0)
-      fputs("<th class=\"header_l\"></th>",fp_top3);
-   if((TopUserFields & TOPUSERFIELDS_USERID) != 0)
-      fprintf(fp_top3,"<th class=\"header_l\">%s</th>",_("USERID"));
+   if((TopUserFields & TOPUSERFIELDS_DATE_TIME) !=0 && (ReportType & REPORT_TYPE_DATE_TIME) != 0) {
+      fputs("<th class=\"header_l",fp_top3);
+      if (SortTableJs[0]) fputs(" sorttable_nosort",fp_top3);
+      fputs("\"></th>",fp_top3);
+   }
+   if((TopUserFields & TOPUSERFIELDS_USERID) != 0) {
+      fputs("<th class=\"header_l",fp_top3);
+      if (SortTableJs[0]) fputs(" sorttable_alpha",fp_top3);
+      fprintf(fp_top3,"\">%s</th>",_("USERID"));
+   }
    if((TopUserFields & TOPUSERFIELDS_CONNECT) != 0)
       fprintf(fp_top3,"<th class=\"header_l\">%s</th>",_("CONNECT"));
    if((TopUserFields & TOPUSERFIELDS_BYTES) != 0)
@@ -223,7 +231,7 @@ void topuser(void)
    if((TopUserFields & TOPUSERFIELDS_SETYB) != 0)
       fprintf(fp_top3,"<th class=\"header_l\">%%%s</th>",_("BYTES"));
    if((TopUserFields & TOPUSERFIELDS_IN_CACHE_OUT) != 0)
-      fprintf(fp_top3,"<th class=\"header_c\" colspan=\"2\">%s</th>",_("IN-CACHE-OUT"));
+      fprintf(fp_top3,"<th class=\"header_c\" colspan=\"2\">%s</th><th style=\"display:none;\"></th>",_("IN-CACHE-OUT"));
    if((TopUserFields & TOPUSERFIELDS_USED_TIME) != 0)
       fprintf(fp_top3,"<th class=\"header_l\">%s</th>",_("ELAPSED TIME"));
    if((TopUserFields & TOPUSERFIELDS_MILISEC) != 0)
@@ -231,7 +239,7 @@ void topuser(void)
    if((TopUserFields & TOPUSERFIELDS_PTIME) != 0)
       fprintf(fp_top3,"<th class=\"header_l\">%%%s</th>",_("TIME"));
 
-   fputs("</tr>\n",fp_top3);
+   fputs("</tr></thead>\n",fp_top3);
 
    ntopuser = 0;
 
@@ -304,10 +312,16 @@ void topuser(void)
          else
             fprintf(fp_top3,"<td class=\"data2\"><a href=\"%s/%s.html\">%s</a></td>",uinfo->filename,uinfo->filename,uinfo->label);
       }
-      if((TopUserFields & TOPUSERFIELDS_CONNECT) != 0)
-         fprintf(fp_top3,"<td class=\"data\">%s</td>",fixnum(nacc,1));
-      if((TopUserFields & TOPUSERFIELDS_BYTES) != 0)
-         fprintf(fp_top3,"<td class=\"data\">%s</td>",fixnum(tnbytes,1));
+      if((TopUserFields & TOPUSERFIELDS_CONNECT) != 0) {
+         fputs("<td class=\"data\"",fp_top3);
+         if (SortTableJs[0]) fprintf(fp_top3," sorttable_customkey=\"%"PRId64"\"",(int64_t)nacc);
+         fprintf(fp_top3,">%s</td>",fixnum(nacc,1));
+      }
+      if((TopUserFields & TOPUSERFIELDS_BYTES) != 0) {
+         fputs("<td class=\"data\"",fp_top3);
+         if (SortTableJs[0]) fprintf(fp_top3," sorttable_customkey=\"%"PRId64"\"",(int64_t)tnbytes);
+         fprintf(fp_top3,">%s</td>",fixnum(tnbytes,1));
+      }
       if((TopUserFields & TOPUSERFIELDS_SETYB) != 0) {
          perc=(ttnbytes) ? tnbytes * 100. / ttnbytes : 0.;
          fprintf(fp_top3,"<td class=\"data\">%3.2lf%%</td>",perc);
@@ -322,8 +336,11 @@ void topuser(void)
          }
 #endif
       }
-      if((TopUserFields & TOPUSERFIELDS_USED_TIME) != 0)
-         fprintf(fp_top3,"<td class=\"data\">%s</td>",buildtime(tnelap));
+      if((TopUserFields & TOPUSERFIELDS_USED_TIME) != 0) {
+         fputs("<td class=\"data\"",fp_top3);
+         if (SortTableJs[0]) fprintf(fp_top3," sorttable_customkey=\"%"PRId64"\"",(int64_t)tnelap);
+         fprintf(fp_top3,">%s</td>",buildtime(tnelap));
+      }
       if((TopUserFields & TOPUSERFIELDS_MILISEC) != 0)
          fprintf(fp_top3,"<td class=\"data\">%s</td>",fixnum2(tnelap,1));
       if((TopUserFields & TOPUSERFIELDS_PTIME) != 0) {
@@ -340,7 +357,7 @@ void topuser(void)
    longline_destroy(&line);
 
    if((TopUserFields & TOPUSERFIELDS_TOTAL) != 0) {
-      fputs("<tr>",fp_top3);
+      fputs("<tfoot><tr>",fp_top3);
       if((TopUserFields & TOPUSERFIELDS_NUM) != 0)
          fputs("<td></td>",fp_top3);
       if((TopUserFields & TOPUSERFIELDS_DATE_TIME) !=0 && (ReportType & REPORT_TYPE_DATE_TIME) != 0)
@@ -394,7 +411,7 @@ void topuser(void)
          fprintf(fp_top3,"<th class=\"header_r\">%s</th>",buildtime(ttnelap/totuser));
       if((TopUserFields & TOPUSERFIELDS_MILISEC) != 0)
          fprintf(fp_top3,"<th class=\"header_r\">%s</th>",fixnum2(ttnelap/totuser,1));
-      fputs("</tr>\n",fp_top3);
+      fputs("</tr></tfoot>\n",fp_top3);
    }
 
    fputs("</table></div>\n",fp_top3);
diff --git a/util.c b/util.c
index 9cb4f31db16889830d59f6b8920179dcdb8083ba..a0bb63ccafa927d63ea9d3dfedc09e1fdc375833 100644 (file)
--- a/util.c
+++ b/util.c
@@ -681,21 +681,18 @@ int obtuser(const char *dirname, const char *name)
 }
 
 
-void obttotal(const char *dirname, const char *name, char *tbytes, int nuser, char *media)
+void obttotal(const char *dirname, const char *name, int nuser, long long int *tbytes, long long int *media)
 {
    FILE *fp_in;
    char *buf;
    char wdir[MAXLEN];
    char user[MAX_USER_LEN];
    char sep;
-   long long int med=0;
-   long long int twork=0;
    struct getwordstruct gwarea;
    longline line;
 
-   twork=0;
-   tbytes[0]='\0';
-   media[0]='\0';
+   *tbytes=0;
+   *media=0;
 
    sprintf(wdir,"%s%s/sarg-general",dirname,name);
    if ((fp_in = fopen(wdir, "r")) == 0) {
@@ -728,24 +725,19 @@ void obttotal(const char *dirname, const char *name, char *tbytes, int nuser, ch
          debuga(_("There a broken total number of access in file %s\n"),wdir);
          exit(EXIT_FAILURE);
       }
-      if (getword_atoll(&twork,&gwarea,sep)<0) {
+      if (getword_atoll(tbytes,&gwarea,sep)<0) {
          debuga(_("There is a broken number of bytes in file %s\n"),wdir);
          exit(EXIT_FAILURE);
       }
-      strcpy(tbytes,fixnum(twork,1));
       break;
    }
    fclose(fp_in);
    longline_destroy(&line);
 
-   if(nuser <= 0) {
-      strcpy(media,"0");
+   if (nuser <= 0)
       return;
-   }
-
-   med=twork / nuser;
-   strcpy(media,fixnum(med,1));
 
+   *media=*tbytes / nuser;
    return;
 }
 
@@ -1614,6 +1606,8 @@ void write_html_head(FILE *fp_ou, const char *page_title)
    fprintf(fp_ou, "<head>\n  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n",CharSet);
    if (page_title) fprintf(fp_ou,"<title>%s</title>\n",page_title);
    css(fp_ou);
+   if (SortTableJs[0])
+      fprintf(fp_ou,"<script type=\"text/javascript\" src=\"%s\"></script>\n",SortTableJs);
    fputs("</head>\n<body>\n",fp_ou);
 }