version 0.44
[irssistats] / irssistats.c
old mode 100644 (file)
new mode 100755 (executable)
index b7a855c..832b239
@@ -1,4 +1,4 @@
-/* Usage: cat /path/to/file.log | ./irssistats channel maintainer language theme [nickfile] > /path/to/file.html */
+/* Usage: cat /path/to/file.log | ./irssistats \#channel maintainer language theme [nickfile] > /path/to/file.html */
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -6,8 +6,12 @@
 #include <string.h>
 #include <regex.h>
 
+/* Options */
+#define REFRESH_TIME 3600
+#define W3C_LINK
+
 /* Config */
-#define MAXUSERS 5000
+#define MAXUSERS 10000
 #define MAXNICKLENGTH 50
 #define MAXLINELENGTH 2000
 #define MAXQUOTELENGTH 100
@@ -19,8 +23,8 @@
 #define MINWORDLENGTH 5
 
 /* irssistats */
-#define VERSION "0.4"
-#define URL "http://royale.zerezo.com/programmation/irssistats/"
+#define VERSION "0.44"
+#define URL "http://royale.zerezo.com/irssistats/"
 
 /* Counters */
 #define D_SMILE     0
 char *counters[NBCOUNTERS]={"C_SMILE","C_FROWN","C_EXCLAM","C_QUESTION","C_ME","C_TOPIC","C_MODE","C_KICK","C_KICKED","C_URL","C_JOIN","C_NICK","C_MONOLOGUE"};
 
 /* Languages */
-#define NBLANGUAGES 4
+#define NBLANGUAGES 6
 #define NBKEYS 38
 char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and abbreviation */
 {
   { /* English language */
     { "English",      "en" },
-    { "HEADER",       "Statistics for #%s by %s" },
+    { "HEADER",       "Statistics for %s by %s" },
     { "LEGEND",       "Legend" },
     { "LASTDAYS",     "Lastdays statistics" },
     { "TOPHOURS",     "Hourly statistics" },
@@ -69,7 +73,7 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab
     { "OCCURRENCES",  "occurrences" },
     { "BIGNUMBERS",   "Some big numbers..." },
     { "NUMBERS",      "numbers" },
-    { "TIME",         "%d lines parsed in %d seconds" },
+    { "TIME",         "%d lines (%d days) parsed in %d seconds" },
     { "FOOTER",       "Statistics generated by" },
     { "C_SMILE",      "is often happy :)" },
     { "C_FROWN",      "is often sad :(" },
@@ -86,8 +90,8 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab
     { "C_MONOLOGUE",  "speaks a lot of monologues" }
   },
   { /* French language */
-    { "Français",     "fr" },
-    { "HEADER",       "Statistiques de #%s par %s" },
+    { "French",     "fr" },
+    { "HEADER",       "Statistiques de %s par %s" },
     { "LEGEND",       "L&eacute;gende" },
     { "LASTDAYS",     "Statistiques des derniers jours" },
     { "TOPHOURS",     "Statistiques horaires" },
@@ -98,7 +102,7 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab
     { "AVGLETTERS",   "lettres/lignes" },
     { "HOURS",        "heures" },
     { "QUOTE",        "message al&eacute;atoire" },
-    { "TOPUSERSTIME", "Personnes les plus actives par p&eacute;riode de la journ&eacutee" },
+    { "TOPUSERSTIME", "Personnes les plus actives par p&eacute;riode de la journ&eacute;e" },
     { "RANDTOPICS",   "Quelques topics" },
     { "CHANGEDBY",    "chang&eacute; par" },
     { "NEWTOPIC",     "nouveau topic" },
@@ -110,7 +114,7 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab
     { "OCCURRENCES",  "occurrences" },
     { "BIGNUMBERS",   "Quelques grands nombres..." },
     { "NUMBERS",      "nombres" },
-    { "TIME",         "%d lignes trait&eacute;es en %d secondes" },
+    { "TIME",         "%d lignes (%d jours) trait&eacute;es en %d secondes" },
     { "FOOTER",       "Statistiques g&eacute;n&eacute;r&eacute;es par" },
     { "C_SMILE",      "est souvent heureux :)" },
     { "C_FROWN",      "est souvent triste :(" },
@@ -129,7 +133,7 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab
   { /* German language */
     /* contributed by Valentin Gelhorn <valentin.gelhorn@web.de> */
     { "German",       "de" },
-    { "HEADER",       "Statistiken f&uuml;r #%s von %s" },
+    { "HEADER",       "Statistiken f&uuml;r %s von %s" },
     { "LEGEND",       "Legende" },
     { "LASTDAYS",     "Statistik der letzten Tage" },
     { "TOPHOURS",     "St&uuml;ndliche Statistik" },
@@ -152,7 +156,7 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab
     { "OCCURRENCES",  "Vorkommen" },
     { "BIGNUMBERS",   "Ein paar grosse Zahlen" },
     { "NUMBERS",      "Zahlen" },
-    { "TIME",         "%d Zeilen analysiert in %d Sekunden" },
+    { "TIME",         "%d Zeilen (%d Tage) analysiert in %d Sekunden" },
     { "FOOTER",       "Statistiken wurden erstellt von" },
     { "C_SMILE",      "ist oft gl&uuml;klich :)" },
     { "C_FROWN",      "ist oft traurig :(" },
@@ -171,7 +175,7 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab
   { /* Spanish language */
     /* contributed by Alex <ainaker@gmx.net> */
     { "Spanish",      "es" },
-    { "HEADER",       "Estad&iacute;sticas de #%s por %s" },
+    { "HEADER",       "Estad&iacute;sticas de %s por %s" },
     { "LEGEND",       "Leyenda" },
     { "LASTDAYS",     "Estad&iacute;sticas de los &uacute;ltimos d&iacute;as" },
     { "TOPHOURS",     "Estad&iacute;sticas por horas" },
@@ -194,7 +198,7 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab
     { "OCCURRENCES",  "Frecuencia" },
     { "BIGNUMBERS",   "Algunos datos..." },
     { "NUMBERS",      "N&uacute;mero de veces" },
-    { "TIME",         "%d lineas procesadas en %d segundos" },
+    { "TIME",         "%d lineas (%d d&iacute;as) procesadas en %d segundos" },
     { "FOOTER",       "Estad&iacute;sticas generadas por" },
     { "C_SMILE",      "Suele estar fel&iacute;z :)" },
     { "C_FROWN",      "Suele estar triste :(" },
@@ -209,6 +213,90 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab
     { "C_JOIN",       "No sabe si irse o quedarse" },
     { "C_NICK",       "Cambia mucho de nick" },
     { "C_MONOLOGUE",  "Habla solo" }
+  },
+  { /* Polish language */
+    /* contributed by Piotr Jarmuz <coreupper@yahoo.com> */
+    { "Polish",       "pl" },
+    { "HEADER",       "Statystyki dla %s przez %s" },
+    { "LEGEND",       "Legenda" },
+    { "LASTDAYS",     "Statystyki z ostatnich dni" },
+    { "TOPHOURS",     "Statystyki godzinne" },
+    { "TOPUSERS",     "Najaktywniejsi ludzie" },
+    { "OTHERS",       "Zostalo jeszcze %d nie sklasyfikowanych..." },
+    { "NBLINES",      "linie" },
+    { "NICK",         "nick" },
+    { "AVGLETTERS",   "litery/linie" },
+    { "HOURS",        "godziny" },
+    { "QUOTE",        "przypadkowa wiadomosc" },
+    { "TOPUSERSTIME", "Najaktywniejsi ludzie wedlug czasu dnia" },
+    { "RANDTOPICS",   "Pare tematow" },
+    { "CHANGEDBY",    "zmienione przez" },
+    { "NEWTOPIC",     "nowy temat" },
+    { "RANDURLS",     "Pare URL-i" },
+    { "POSTEDBY",     "wyslane przez" },
+    { "POSTEDURL",    "URL" },
+    { "TOPWORDS",     "Najczestsze slowa" },
+    { "WORD",         "slowo" },
+    { "OCCURRENCES",  "wystapienia" },
+    { "BIGNUMBERS",   "Pare wielkich liczb..." },
+    { "NUMBERS",      "liczby" },
+    { "TIME",         "%d linii (%d dni) sparsowanych w %d sekund" },
+    { "FOOTER",       "Statystyki wygenerowane przez" },
+    { "C_SMILE",      "jest czesto szczesliwy :)" },
+    { "C_FROWN",      "jest czesto smutny :(" },
+    { "C_EXCLAM",     "duzo krzyczy !" },
+    { "C_QUESTION",   "zadaje duzo pytan ?" },
+    { "C_ME",         "lubi /mnie polecenie" },
+    { "C_TOPIC",      "czesto zmienia temat" },
+    { "C_MODE",       "czesto zmienia tryb" },
+    { "C_KICK",       "lubi /kopac" },
+    { "C_KICKED",     "czesto go wykopuja" },
+    { "C_URL",        "wysyla duzo URL-i" },
+    { "C_JOIN",       "nie wie czy zostac czy wyjsc" },
+    { "C_NICK",       "czesto zmienia swojego nicka" },
+    { "C_MONOLOGUE",  "czesto mowi monologiem" }
+  },
+  { /* Finnish language */
+    /* contributed by Antti Huopana <ahuopana@ratol.fi> */
+    { "Finnish",      "fi" },
+    { "HEADER",       "Kanavan %s tilastot - %s" },
+    { "LEGEND",       "Merkkien selitykset" },
+    { "LASTDAYS",     "Viime päivien tilastot" },
+    { "TOPHOURS",     "Tilastot tunneittain" },
+    { "TOPUSERS",     "Aktiivisimmat ihmiset" },
+    { "OTHERS",       "Jäljelle jäi %d joita ei listattu..." },
+    { "NBLINES",      "rivit" },
+    { "NICK",         "nikki" },
+    { "AVGLETTERS",   "kirjainta/rivi" },
+    { "HOURS",        "tunnit" },
+    { "QUOTE",        "satunnainen viesti" },
+    { "TOPUSERSTIME", "Vuorokauden ajan mukaan aktiivisimmat" },
+    { "RANDTOPICS",   "Joitakin aiheita" },
+    { "CHANGEDBY",    "vaihtaja" },
+    { "NEWTOPIC",     "aihe" },
+    { "RANDURLS",     "Joitakin URLeja" },
+    { "POSTEDBY",     "lähettäjä" },
+    { "POSTEDURL",    "URL" },
+    { "TOPWORDS",     "Eniten käytettyjä sanoja" },
+    { "WORD",         "sana" },
+    { "OCCURRENCES",  "käytetty" },
+    { "BIGNUMBERS",   "Joitakin isoja lukuja..." },
+    { "NUMBERS",      "luvut" },
+    { "TIME",         "%d riviä (%d päivää) parsittu %d sekunnissa" },
+    { "FOOTER",       "Tilastot on generoinut" },
+    { "C_SMILE",      "on usein iloinen :)" },
+    { "C_FROWN",      "on usein surullinen :(" },
+    { "C_EXCLAM",     "möykkää paljon !" },
+    { "C_QUESTION",   "kyselee liikaa ?" },
+    { "C_ME",         "pitää itsestään" },
+    { "C_TOPIC",      "vaihtaa usein aihetta" },
+    { "C_MODE",       "haluaa elää muuttuvassa maailmassa" },
+    { "C_KICK",       "pitää potkimisesta" },
+    { "C_KICKED",     "tykkää tulla potkituksi" },
+    { "C_URL",        "surffailee liikaa" },
+    { "C_JOIN",       "ei tiedä ollakko vai eikö olla" },
+    { "C_NICK",       "kärsii identiteettiongelmista" },
+    { "C_MONOLOGUE",  "höpöttää paljon itsekseen" }
   }
 };
 
@@ -223,7 +311,7 @@ char *L(char *key)
 }
 
 /* Themes */
-#define NBTHEMES 5
+#define NBTHEMES 6
 #define NBCOLORS 9
 char *colors[NBTHEMES][NBCOLORS+1][2]= /* first key used for theme name/description and abbreviation */
 {
@@ -286,6 +374,18 @@ char *colors[NBTHEMES][NBCOLORS+1][2]= /* first key used for theme name/descript
     { "TITLE2",  "#FF7700" },
     { "BGTABLE", "#FFEEEE" },
     { "BGTITLE", "#FF7700" }
+  },
+  { /* Blue theme */
+    { "Blue theme...", "blue" },
+    { "BGCOLOR", "#FFFFFF" },
+    { "TEXT",    "#000000" },
+    { "LINK",    "#4444FF" },
+    { "VLINK",   "#8888FF" },
+    { "ALINK",   "#CCCCFF" },
+    { "TITLE1",  "#8888FF" },
+    { "TITLE2",  "#AAAAFF" },
+    { "BGTABLE", "#EEEEFF" },
+    { "BGTITLE", "#CCCCFF" }
   }
 };
 
@@ -312,6 +412,7 @@ struct
   int hours[4];
   char quote[MAXQUOTELENGTH+1];
   int counters[NBCOUNTERS];
+  int temp;
 } users[MAXUSERS];
 int nbusers=0;
 
@@ -439,6 +540,7 @@ int dichotomic(char *nick)
       for (j=0;j<4;j++) users[i].hours[j]=users[i-1].hours[j];
       strcpy(users[i].quote,users[i-1].quote);
       for (j=0;j<NBCOUNTERS;j++) users[i].counters[j]=users[i-1].counters[j];
+      users[i].temp=users[i-1].temp;
     }
     strcpy(users[start].nick,nick);
     users[start].lines=0;
@@ -446,6 +548,7 @@ int dichotomic(char *nick)
     for (j=0;j<4;j++) users[start].hours[j]=0;
     users[start].quote[0]='\0';
     for (j=0;j<NBCOUNTERS;j++) users[start].counters[j]=0;
+    users[start].temp=0;
   }
   return(start);
 }
@@ -468,7 +571,7 @@ int main(int argc,char *argv[])
   
   if ((argc<5) || (argc>6))
   {
-    fprintf(stderr,"Usage: cat /path/to/file.log | ./irssistats channel maintainer language theme [nickfile] > /path/to/file.html\n\n");
+    fprintf(stderr,"Usage: cat /path/to/file.log | ./irssistats \\#channel maintainer language theme [nickfile] > /path/to/file.html\n\n");
     fprintf(stderr,"Version :\nirssistats %s\n\n",VERSION);
     fprintf(stderr,"Supported languages :\n");
     for (i=0;i<NBLANGUAGES;i++) fprintf(stderr,"%s = %s\n",keys[i][0][1],keys[i][0][0]);
@@ -494,17 +597,17 @@ int main(int argc,char *argv[])
   /*** LOG ***/
   
   srand(debut=time(NULL));
-  fprintf(stderr,"working:");
+  fprintf(stderr,"working on %s : ",channel);
   while (!feof(stdin))
   {
     c=getchar();
     line[pos++]=c;
-    if (pos>=MAXLINELENGTH) { fprintf(stderr,"line too long\n"); exit(1); }
+    if (pos>=MAXLINELENGTH) { fprintf(stderr,"line %d is too long\n",totallines); exit(1); }
     if (c=='\n')
     {
       line[pos-1]='\0';
       totallines++;
-      if (totallines%10000==0) { fprintf(stderr,"."); fflush(stdout); }
+      if (totallines%10000==0) { fprintf(stderr,"."); fflush(stderr); }
       if (strncmp("--- Day changed",line,15)==0) /* --- Day changed Wed May 01 2002 */
       {
         for (i=30;i>0;i--)
@@ -635,7 +738,7 @@ int main(int argc,char *argv[])
       pos=0;
     }
   }
-  fprintf(stderr,"done\n");
+  fprintf(stderr," done\n");
 
   bestwords(words,0);
 
@@ -643,19 +746,19 @@ int main(int argc,char *argv[])
   
   if (argc==6)
   {
+    for (i=0;i<nbusers;i++) users[i].temp=users[i].lines;
     if ((fic=fopen(argv[5],"rt"))==NULL) { fprintf(stderr,"can't open nick file\n"); exit(1); }
     while (fscanf(fic,"%s",line)==1)
     {
       user=dichotomic(line);
       fscanf(fic,"%s",line);
       if (regcomp(&preg,line,0)!=0) { fprintf(stderr,"error in nick file"); exit(1); }
-      temp=users[user].lines;
       for (i=0;i<nbusers;i++) if ((i!=user) && (regexec(&preg,users[i].nick,0,0,0)==0) && (users[i].lines>=0))
       {
-        if (users[i].lines>temp) /* for nick alias, keep the random quote of the most used nick */
+        if (users[i].temp>users[user].temp) /* for nick alias, keep the random quote of the most used nick */
         {
           strcpy(users[user].quote,users[i].quote);
-          temp=users[i].lines;
+          users[user].temp=users[i].temp;
         }
         users[user].lines+=users[i].lines;
         users[user].letters+=users[i].letters;
@@ -670,56 +773,67 @@ int main(int argc,char *argv[])
       regfree(&preg);
     }
     fclose(fic);
+    /* "remove" the ignored nicks */
+    i=dichotomic("<NULL>");
+    users[i].lines=-1;
+    users[i].letters=-1;
+    for (j=0;j<4;j++) users[i].hours[j]=-1;
+    for (j=0;j<NBCOUNTERS;j++) users[i].counters[j]=-1;
   }
   
   /*** HTML ***/
 
   /* header */
+  printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n\n");
   printf("<!-- Generated by irssistats %s : %s -->\n\n",VERSION,URL);
-  printf("<html>\n\n<head>\n<base target=\"_blank\">\n<title>");
+  printf("<html>\n\n<head>\n<title>");
   printf(L("HEADER"),channel,maintainer);
-  printf("</title>\n</head>\n\n");
-  printf("<body bgcolor=\"%s\" text=\"%s\" link=\"%s\" vlink=\"%s\" alink=\"%s\">\n\n<center>\n\n<font color=\"%s\"><h1>",T("BGCOLOR"),T("TEXT"),T("LINK"),T("VLINK"),T("ALINK"),T("TITLE1"));
+  printf("</title>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">\n");
+#ifdef REFRESH_TIME
+  printf("<meta http-equiv=\"Refresh\" content=\"%d\">\n",REFRESH_TIME);
+#endif
+  printf("<base target=\"_blank\">\n</head>\n\n");
+  printf("<body bgcolor=\"%s\" text=\"%s\" link=\"%s\" vlink=\"%s\" alink=\"%s\">\n\n<center>\n\n<font color=\"%s\" size=\"+3\"><b>",T("BGCOLOR"),T("TEXT"),T("LINK"),T("VLINK"),T("ALINK"),T("TITLE1"));
   printf(L("HEADER"),channel,maintainer);
-  printf("</h1></font>\n%s<br>\n<br><br>\n\n",ctime(&debut));
+  printf("</b></font><br><br>\n%s<br>\n<br><br>\n\n",ctime(&debut));
 
   /* legend */
-  printf("<font color=\"%s\"><h3>%s</h3></font>\n<table bgcolor=%s>\n<tr>\n",T("TITLE2"),L("LEGEND"),T("BGTABLE"));
-  for (i=0;i<4;i++) printf("<td><img src=\"h%d.png\" width=\"40\" height=\"15\"></td><td> : %s %d-%d</td><td width=\"10\"></td>\n",i+1,L("HOURS"),i*6,i*6+5);
+  printf("<font color=\"%s\" size=\"+1\"><b>%s</b></font><br><br>\n<table bgcolor=\"%s\">\n<tr>\n",T("TITLE2"),L("LEGEND"),T("BGTABLE"));
+  for (i=0;i<4;i++) printf("<td><img src=\"h%d.png\" width=\"40\" height=\"15\" alt=\"\"></td><td> : %s %d-%d</td><td width=\"10\"></td>\n",i+1,L("HOURS"),i*6,i*6+5);
   printf("</tr>\n</table>\n<br><br>\n\n");
   
   /* last days */
-  printf("<font color=\"%s\"><h3>%s</h3></font>\n<table>\n<tr>\n",T("TITLE2"),L("LASTDAYS"));
+  printf("<font color=\"%s\" size=\"+1\"><b>%s</b></font><br><br>\n<table>\n<tr>\n",T("TITLE2"),L("LASTDAYS"));
   max=-1;
   for (i=30;i>=0;i--) if (lastdays[i].lines>max) max=lastdays[i].lines;
   for (i=30;i>=0;i--)
   {
     printf("<td width=\"15\" align=\"center\" valign=\"bottom\"><font size=\"-2\">%d</font><br>",lastdays[i].lines);
-    for (j=0;j<4;j++) if (lastdays[i].hours[j]!=0) printf("<img src=\"v%d.png\" width=\"15\" height=\"%d\"><br>",j+1,150*lastdays[i].hours[j]/max);
+    for (j=0;j<4;j++) if (lastdays[i].hours[j]!=0) printf("<img src=\"v%d.png\" width=\"15\" height=\"%d\" alt=\"\"><br>",j+1,150*lastdays[i].hours[j]/max);
     printf("</td>\n");
   }
   printf("</tr>\n<tr>\n");
   for (i=30;i>=0;i--)
-    printf("<td align=\"center\" valign=\"center\" bgcolor=\"%s\">%d</td>\n",T("BGTABLE"),i);
+    printf("<td align=\"center\" valign=\"middle\" bgcolor=\"%s\">%d</td>\n",T("BGTABLE"),i);
   printf("</tr>\n</table>\n<br><br>\n\n");
   
   /* top hours */
-  printf("<font color=\"%s\"><h3>%s</h3></font>\n<table>\n<tr>\n",T("TITLE2"),L("TOPHOURS"));
+  printf("<font color=\"%s\" size=\"+1\"><b>%s</b></font><br><br>\n<table>\n<tr>\n",T("TITLE2"),L("TOPHOURS"));
   max=-1;
   for (i=0;i<24;i++) if (hours[i]>max) max=hours[i];
   for (i=0;i<24;i++)
   {
     printf("<td width=\"15\" align=\"center\" valign=\"bottom\"><font size=\"-2\">%.1f%%</font><br>",lines!=0?(float)100*hours[i]/lines:0);
-    if (hours[i]!=0) printf("<img src=\"v%d.png\" width=\"15\" height=\"%d\"><br>",i/6+1,150*hours[i]/max);
+    if (hours[i]!=0) printf("<img src=\"v%d.png\" width=\"15\" height=\"%d\" alt=\"\"><br>",i/6+1,150*hours[i]/max);
     printf("</td>\n");
   }
   printf("</tr>\n<tr>\n");
   for (i=0;i<24;i++)
-    printf("<td align=\"center\" valign=\"center\" bgcolor=\"%s\">%d</td>\n",T("BGTABLE"),i);
+    printf("<td align=\"center\" valign=\"middle\" bgcolor=\"%s\">%d</td>\n",T("BGTABLE"),i);
   printf("</tr>\n</table>\n<br><br>\n\n");
   
   /* top users */
-  printf("<font color=\"%s\"><h3>%s</h3></font>\n",T("TITLE2"),L("TOPUSERS"));
+  printf("<font color=\"%s\" size=\"+1\"><b>%s</b></font><br><br>\n",T("TITLE2"),L("TOPUSERS"));
   printf("<table>\n<tr><td></td><td bgcolor=\"%s\">%s</td><td bgcolor=\"%s\">%s</td><td bgcolor=\"%s\">%s</td><td bgcolor=\"%s\" colspan=\"2\">%s</td><td bgcolor=\"%s\">%s</td>\n",T("BGTITLE"),L("NICK"),T("BGTITLE"),L("NBLINES"),T("BGTITLE"),L("HOURS"),T("BGTITLE"),L("AVGLETTERS"),T("BGTITLE"),L("QUOTE"));
   for (i=1;i<=NBUSERS;i++)
   {
@@ -729,8 +843,8 @@ int main(int argc,char *argv[])
     if (user!=-1)
     {
       printf("<tr><td bgcolor=\"%s\" align=\"right\">%d</td><td bgcolor=\"%s\">%s</td><td bgcolor=\"%s\">%d</td><td bgcolor=\"%s\">",T("BGTABLE"),i,T("BGTABLE"),users[user].nick,T("BGTABLE"),users[user].lines,T("BGTABLE"));
-      for (j=0;j<4;j++) if (users[user].hours[j]!=0) printf("<img src=\"h%d.png\" width=\"%d\" height=\"15\">",j+1,100*users[user].hours[j]/users[user].lines);
-      printf("</td><td bgcolor=\"%s\">%d</td><td bgcolor=\"%s\"><img src=\"hm.png\" width=\"%d\" height=\"15\"></td><td bgcolor=\"%s\">\"",T("BGTABLE"),users[user].lines!=0?users[user].letters/users[user].lines:0,T("BGTABLE"),users[user].lines!=0?users[user].letters/users[user].lines:0,T("BGTABLE"));
+      for (j=0;j<4;j++) if (users[user].hours[j]!=0) printf("<img src=\"h%d.png\" width=\"%d\" height=\"15\" alt=\"\">",j+1,100*users[user].hours[j]/users[user].lines);
+      printf("</td><td bgcolor=\"%s\">%d</td><td bgcolor=\"%s\"><img src=\"hm.png\" width=\"%d\" height=\"15\" alt=\"\"></td><td bgcolor=\"%s\">\"",T("BGTABLE"),users[user].lines!=0?users[user].letters/users[user].lines:0,T("BGTABLE"),users[user].lines!=0?users[user].letters/users[user].lines:0,T("BGTABLE"));
       printhtml(users[user].quote);
       printf("\"</td></tr>\n");
       users[user].lines=-1;
@@ -748,7 +862,7 @@ int main(int argc,char *argv[])
   printf("<br><br>\n\n");
   
   /* top users by time */
-  printf("<font color=\"%s\"><h3>%s</h3></font>\n",T("TITLE2"),L("TOPUSERSTIME"));
+  printf("<font color=\"%s\" size=\"+1\"><b>%s</b></font><br><br>\n",T("TITLE2"),L("TOPUSERSTIME"));
   printf("<table>\n<tr><td></td>");
   for (i=0;i<4;i++) printf("<td bgcolor=\"%s\" colspan=\"2\">%s %d-%d</td>",T("BGTITLE"),L("HOURS"),i*6,i*6+5);
   printf("</tr>\n");
@@ -772,7 +886,7 @@ int main(int argc,char *argv[])
   printf("</table>\n<br><br>\n\n");
 
   /* random topics */
-  printf("<font color=\"%s\"><h3>%s</h3></font>\n",T("TITLE2"),L("RANDTOPICS"));
+  printf("<font color=\"%s\" size=\"+1\"><b>%s</b></font><br><br>\n",T("TITLE2"),L("RANDTOPICS"));
   printf("<table>\n<tr><td bgcolor=\"%s\">%s</td><td bgcolor=\"%s\">%s</td></tr>\n",T("BGTITLE"),L("CHANGEDBY"),T("BGTITLE"),L("NEWTOPIC"));
   for (i=nbtopics<NBTOPICS?nbtopics-1:NBTOPICS-1;i>=0;i--)
   {
@@ -783,25 +897,27 @@ int main(int argc,char *argv[])
   printf("</table>\n<br><br>\n\n");
   
   /* random urls */
-  printf("<font color=\"%s\"><h3>%s</h3></font>\n",T("TITLE2"),L("RANDURLS"));
+  printf("<font color=\"%s\" size=\"+1\"><b>%s</b></font><br><br>\n",T("TITLE2"),L("RANDURLS"));
   printf("<table>\n<tr><td bgcolor=\"%s\">%s</td><td bgcolor=\"%s\">%s</td></tr>\n",T("BGTITLE"),L("POSTEDBY"),T("BGTITLE"),L("POSTEDURL"));
   for (i=nburls<NBURLS?nburls-1:NBURLS-1;i>=0;i--)
   {
-    printf("<tr><td bgcolor=\"%s\">%s</td><td bgcolor=\"%s\">\"<a href=\"%s\">",T("BGTABLE"),urls[i].nick,T("BGTABLE"),urls[i].url);
+    printf("<tr><td bgcolor=\"%s\">%s</td><td bgcolor=\"%s\">\"<a href=\"",T("BGTABLE"),urls[i].nick,T("BGTABLE"));
+    printhtml(urls[i].url);
+    printf("\">");
     printhtml(urls[i].shorturl);
     printf("</a>\"</td></tr>\n");
   }
   printf("</table>\n<br><br>\n\n");
   
   /* top words */
-  printf("<font color=\"%s\"><h3>%s</h3></font>\n",T("TITLE2"),L("TOPWORDS"));
+  printf("<font color=\"%s\" size=\"+1\"><b>%s</b></font><br><br>\n",T("TITLE2"),L("TOPWORDS"));
   printf("<table>\n<tr><td></td><td bgcolor=\"%s\">%s</td><td bgcolor=\"%s\">%s</td></tr>\n",T("BGTITLE"),L("WORD"),T("BGTITLE"),L("OCCURRENCES"));
   for (i=0;i<NBWORDS;i++)
     if (topwords[i].nb!=0) printf("<tr><td bgcolor=\"%s\" align=\"right\">%d</td><td bgcolor=\"%s\">\"%s\"</td><td bgcolor=\"%s\">%d</td></tr>\n",T("BGTABLE"),i+1,T("BGTABLE"),topwords[i].word,T("BGTABLE"),topwords[i].nb);
   printf("</table>\n<br><br>\n\n");
 
   /* big numbers */
-  printf("<font color=\"%s\"><h3>%s</h3></font>\n",T("TITLE2"),L("BIGNUMBERS"));
+  printf("<font color=\"%s\" size=\"+1\"><b>%s</b></font><br><br>\n",T("TITLE2"),L("BIGNUMBERS"));
   printf("<table>\n<tr><td bgcolor=\"%s\">%s</td><td bgcolor=\"%s\">%s</td><td bgcolor=\"%s\">%s</td></tr>\n",T("BGTITLE"),L("NICK"),T("BGTITLE"),L("NUMBERS"),T("BGTITLE"),L("NBLINES"));
   for (i=0;i<NBCOUNTERS;i++)
   {
@@ -813,8 +929,11 @@ int main(int argc,char *argv[])
   printf("</table>\n<br><br>\n\n");
   
   /* footer */
-  printf(L("TIME"),totallines,(int)(time(NULL)-debut));
+  printf(L("TIME"),totallines,days,(int)(time(NULL)-debut));
   printf("<br>\n%s <a href=\"%s\">irssistats %s</a>",L("FOOTER"),URL,VERSION);
+#ifdef W3C_LINK
+  printf("<br><br>\n\n<a href=\"http://validator.w3.org/check/referer\"><img src=\"valid-html401.gif\" border=\"0\" height=\"31\" width=\"88\"alt=\"Valid HTML 4.01!\"></a>");
+#endif
   printf("\n\n</center>\n\n</body>\n\n</html>\n");
   
   return(0);