X-Git-Url: http://royale.zerezo.com/git/?p=irssistats;a=blobdiff_plain;f=irssistats.c;h=2ac92a7227b3c950f8a2909be4b635ebc3ec62a3;hp=7bb52cf9614cd61b63f73fe7dc15800aff02c718;hb=d07bc64a1481a9048d32ece28844cf3d087ca922;hpb=cfcf15a6f6799d424044c81c81bf92a907cae095 diff --git a/irssistats.c b/irssistats.c index 7bb52cf..2ac92a7 100644 --- a/irssistats.c +++ b/irssistats.c @@ -1,5 +1,5 @@ /* - * irssistats version 0.6 + * irssistats version 0.75 * * This tool generates IRC stats based on irssi logs. * Usage: irssistats [/path/to/file.conf] @@ -20,7 +20,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ + */ #include @@ -28,7 +28,13 @@ #include #include #include +#include +#ifdef __WIN32__ +#define GLOBALCONF "irssistats.conf" +#else +#define GLOBALCONF "/etc/irssistats.conf" #include +#endif /* Config */ #define BASEUSERS 1000 @@ -43,7 +49,7 @@ #define MINWORDLENGTH 5 /* irssistats */ -#define VERSION "0.6" +#define VERSION "0.75" #define URL "http://royale.zerezo.com/irssistats/" /* Counters */ @@ -64,8 +70,8 @@ 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 9 -#define NBKEYS 39 +#define NBLANGUAGES 11 +#define NBKEYS 41 char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and abbreviation */ { { /* English language */ @@ -73,7 +79,9 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab { "CHARSET", "ISO-8859-1" }, { "HEADER", "Statistics for %s by %s" }, { "LEGEND", "Legend" }, - { "LASTDAYS", "Lastdays statistics" }, + { "LASTDAYS", "Last days statistics" }, + { "LASTWEEKS", "Last weeks statistics" }, + { "LASTMONTHS", "Last months statistics" }, { "TOPHOURS", "Hourly statistics" }, { "TOPUSERS", "Most active people" }, { "OTHERS", "There are %d left not ranked..." }, @@ -116,6 +124,8 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab { "HEADER", "Statistiques de %s par %s" }, { "LEGEND", "Légende" }, { "LASTDAYS", "Statistiques des derniers jours" }, + { "LASTWEEKS", "Statistiques des dernières semaines" }, + { "LASTMONTHS", "Statistiques des derniers mois" }, { "TOPHOURS", "Statistiques horaires" }, { "TOPUSERS", "Personnes les plus actives" }, { "OTHERS", "Il reste %d personnes non classées..." }, @@ -159,6 +169,8 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab { "HEADER", "Statistiken für %s von %s" }, { "LEGEND", "Legende" }, { "LASTDAYS", "Statistik der letzten Tage" }, + { "LASTWEEKS", "Last weeks statistics" }, + { "LASTMONTHS", "Last months statistics" }, { "TOPHOURS", "Stündliche Statistik" }, { "TOPUSERS", "Die aktivsten Personen" }, { "OTHERS", "Es bleiben noch %d uneingetragene" }, @@ -186,7 +198,7 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab { "C_EXCLAM", "schreit oft !" }, { "C_QUESTION", "stellt viele Fragen ?" }, { "C_ME", "mag /me'en" }, - { "C_TOPIC", "aendert oft das Topico" }, + { "C_TOPIC", "aendert oft das Topic" }, { "C_MODE", "aendert oft die Modes" }, { "C_KICK", "mag /kick'en" }, { "C_KICKED", "wird oft gekickt"}, @@ -202,6 +214,8 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab { "HEADER", "Estadísticas de %s por %s" }, { "LEGEND", "Leyenda" }, { "LASTDAYS", "Estadísticas de los últimos días" }, + { "LASTWEEKS", "Last weeks statistics" }, + { "LASTMONTHS", "Last months statistics" }, { "TOPHOURS", "Estadísticas por horas" }, { "TOPUSERS", "Los que más escriben" }, { "OTHERS", "Hay %d más que no llegaron..." }, @@ -245,6 +259,8 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab { "HEADER", "Statystyki dla %s zebrane przez %s" }, { "LEGEND", "Legenda" }, { "LASTDAYS", "Statystyki z ostatnich dni" }, + { "LASTWEEKS", "Last weeks statistics" }, + { "LASTMONTHS", "Last months statistics" }, { "TOPHOURS", "Statystyki godzinowe" }, { "TOPUSERS", "Najaktywniejsi" }, { "OTHERS", "Jest jeszcze %d nie sklasyfikowanych..." }, @@ -288,6 +304,8 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab { "HEADER", "Statystyki dla %s przez %s" }, { "LEGEND", "Legenda" }, { "LASTDAYS", "Statystyki z ostatnich dni" }, + { "LASTWEEKS", "Last weeks statistics" }, + { "LASTMONTHS", "Last months statistics" }, { "TOPHOURS", "Statystyki godzinne" }, { "TOPUSERS", "Najaktywniejsi ludzie" }, { "OTHERS", "Zostalo jeszcze %d nie sklasyfikowanych..." }, @@ -331,6 +349,8 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab { "HEADER", "Kanavan %s tilastot - %s" }, { "LEGEND", "Merkkien selitykset" }, { "LASTDAYS", "Viime päivien tilastot" }, + { "LASTWEEKS", "Last weeks statistics" }, + { "LASTMONTHS", "Last months statistics" }, { "TOPHOURS", "Tilastot tunneittain" }, { "TOPUSERS", "Aktiivisimmat ihmiset" }, { "OTHERS", "Jäljelle jäi %d joita ei listattu..." }, @@ -374,6 +394,8 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab { "HEADER", "Statistiche per il canale %s di %s" }, { "LEGEND", "Legenda" }, { "LASTDAYS", "Statistiche degli ultimi giorni" }, + { "LASTWEEKS", "Last weeks statistics" }, + { "LASTMONTHS", "Last months statistics" }, { "TOPHOURS", "Statistiche in ore" }, { "TOPUSERS", "Utenti più attivi" }, { "OTHERS", "Ci sono %d utenti non classificati..." }, @@ -412,14 +434,17 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab }, { /* Dutch language */ /* contributed by Jeroen Ubbink */ + /* updated by Wouter Horré */ { "Dutch", "nl" }, { "CHARSET", "ISO-8859-1" }, { "HEADER", "Statistieken voor %s door %s" }, { "LEGEND", "Legenda" }, { "LASTDAYS", "Statistieken van de laatste dagen" }, + { "LASTWEEKS", "Last weeks statistics" }, + { "LASTMONTHS", "Last months statistics" }, { "TOPHOURS", "Statistieken per uur" }, { "TOPUSERS", "Meest actieve mensen" }, - { "OTHERS", "Er zijn nog %d niet in de top..." }, + { "OTHERS", "Er zijn nog %d mensen die de top niet haalden..." }, { "NBLINES", "regels" }, { "NICK", "nick" }, { "AVGLETTERS", "letters/lijn" }, @@ -438,7 +463,7 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab { "BIGNUMBERS", "Enkele grote aantallen..." }, { "NUMBERS", "numbers" }, { "TIME", "%d regels (%d dagen) verwerkt in %d seconden" }, - { "FOOTER", "Statistieken gegenereert door" }, + { "FOOTER", "Statistieken gegenereerd door" }, { "C_SMILE", "is vaak vrolijk :)" }, { "C_FROWN", "is vaak droevig :(" }, { "C_EXCLAM", "schreeuwt veel !" }, @@ -452,7 +477,97 @@ char *keys[NBLANGUAGES][NBKEYS+1][2]= /* first key used for language name and ab { "C_JOIN", "twijfelt tussen blijven of gaan" }, { "C_NICK", "verandert vaak van nick" }, { "C_MONOLOGUE", "spreekt veel monologen" } - } + }, + { /* Russian language */ + /* contributed by kamikaze */ + { "Russian", "ru" }, + { "CHARSET", "KOI8-R" }, + { "HEADER", "óÔÁÔÉÓÔÉËÁ ÄÌÑ %s ÏÔ %s" }, + { "LEGEND", "ïÂÏÚÎÁÞÅÎÉÑ" }, + { "LASTDAYS", "óÔÁÔÉÓÔÉËÁ ÐÏÓÌÅÄÎÉÈ ÄÎÅÊ" }, + { "LASTWEEKS", "Last weeks statistics" }, + { "LASTMONTHS", "Last months statistics" }, + { "TOPHOURS", "ðÏÞÁÓÏ×ÁÑ ÓÔÁÔÉÓÔÉËÁ" }, + { "TOPUSERS", "áËÔÉ×ÎÅÊÛÉÅ ÌÀÄÉ" }, + { "OTHERS", "ïÓÔÁÌÏÓØ %d ÎÅÐÏÄÓÞÉÔÁÎÙÈ..." }, + { "NBLINES", "ÓÔÒÏËÉ" }, + { "NICK", "ÎÉË" }, + { "AVGLETTERS", "ÂÕË×Ù/ÓÔÒÏËÉ" }, + { "HOURS", "ÞÁÓÙ" }, + { "QUOTE", "ÓÌÕÞÁÊÎÏÅ ÓÏÏÂÝÅÎÉÅ" }, + { "TOPUSERSTIME", "áËÔÉ×ÎÅÊÛÉÅ ÌÀÄÉ ÐÏ ×ÒÅÍÅÎÉ ÄÎÑ" }, + { "RANDTOPICS", "îÅÓËÏÌØËÏ ÔÏÐÉËÏ×" }, + { "CHANGEDBY", "ÉÚÍÅΣÎ" }, + { "NEWTOPIC", "ÎÏ×ÙÊ ÔÏÐÉË" }, + { "RANDURLS", "îÅÓËÏÌØËÏ URLÏ×" }, + { "POSTEDBY", "ÏÐÕÂÌÉËÏ×ÁÌ" }, + { "POSTEDURL", "URL" }, + { "TOPWORDS", "þÁÓÔÏ ÉÓÐÏÌØÚÕÅÍÙÅ ÓÌÏ×Á" }, + { "WORD", "ÓÌÏ×Ï" }, + { "OCCURRENCES", "ÐÒÏÉÛÅÓÔ×ÉÑ" }, + { "BIGNUMBERS", "îÅÓËÏÌØËÏ ÂÏÌØÛÉÈ ÞÉÓÅÌ..." }, + { "NUMBERS", "ÞÉÓÌÁ" }, + { "TIME", "%d ÓÔÒÏË (%d ÄÎÅÊ) ÏÂÒÁÂÏÔÁÎÏ ÚÁ %d ÓÅËÕÎÄ" }, + { "FOOTER", "óÔÁÔÉÓÔÉËÁ ÓÇÅÎÅÒÉÒÏ×ÁÎÁ" }, + { "C_SMILE", "ÞÁÓÔÏ ÓÞÁÓÌÉ× :)" }, + { "C_FROWN", "ÞÁÓÔÏ ÎÅÓÞÁÓÔÅÎ :(" }, + { "C_EXCLAM", "ÍÎÏÇÏ ×ÏÓËÌÉÃÁÅÔ !" }, + { "C_QUESTION", "ÚÁÄÁ£Ô ÍÎÏÇÏ ×ÏÐÒÏÓÏ× ?" }, + { "C_ME", "ÌÀÂÉÔ /me command" }, + { "C_TOPIC", "ÞÁÓÔÏ ÍÅÎÑÅÔ ÔÏÐÉË" }, + { "C_MODE", "ÞÁÓÔÏ ÍÅÎÑÅÔ ÒÅÖÉÍÙ" }, + { "C_KICK", "ÌÀÂÉÔ /kick" }, + { "C_KICKED", "ÞÁÓÔÏ ×ÙËÉÄÙ×ÁÀÔ" }, + { "C_URL", "ÐÕÂÌÉËÕÅÔ ÍÎÏÇÏ URLÏ×" }, + { "C_JOIN", "ÎÅ ÚÎÁÅÔ - ÏÓÔÁÔØÓÑ ÉÌÉ ÕÊÔÉ" }, + { "C_NICK", "ÞÁÓÔÏ ÍÅÎÑÅÔ Ó×ÏÊ ÎÉË" }, + { "C_MONOLOGUE", "éÓÐÏÌØÚÕÅÔ ÍÎÏÇÏ ÍÏÎÏÌÏÇÏ×" } + }, + { /* Estonian language */ + /* contributed by Martin Vool */ + { "Estonian", "et" }, + { "CHARSET", "ISO-8859-4" }, + { "HEADER", "Statistika kanalile %s on koostanud %s" }, + { "LEGEND", "Legend" }, + { "LASTDAYS", "Viimaste päevade statistika" }, + { "LASTWEEKS", "Last weeks statistics" }, + { "LASTMONTHS", "Last months statistics" }, + { "TOPHOURS", "Tunni statistika" }, + { "TOPUSERS", "Kõige aktiivsemad inimesed" }, + { "OTHERS", "%d inimest on rääkinud" }, + { "NBLINES", "rida" }, + { "NICK", "nimi" }, + { "AVGLETTERS", "tähte/rida" }, + { "HOURS", "kell" }, + { "QUOTE", "suvaline teade" }, + { "TOPUSERSTIME", "Kõige aktiivsemad inimesed päeva aja järgi" }, + { "RANDTOPICS", "Mõned topicud" }, + { "CHANGEDBY", "muutis" }, + { "NEWTOPIC", "topicud" }, + { "RANDURLS", "Mõned aadressid" }, + { "POSTEDBY", "postitas" }, + { "POSTEDURL", "URL" }, + { "TOPWORDS", "Enim kasutatud sõnad" }, + { "WORD", "sõna" }, + { "OCCURRENCES", "sagedus" }, + { "BIGNUMBERS", "Mõned suured numbrid" }, + { "NUMBERS", "iseloom" }, + { "TIME", "%d rida (%d päeva) on möödunud %d sekundit" }, + { "FOOTER", "Statistika on koostanud" }, + { "C_SMILE", "on tihti õnnelik :)" }, + { "C_FROWN", "on tihti kurb :(" }, + { "C_EXCLAM", "põrnitseb palju" }, + { "C_QUESTION", "küsib palju küsimusi" }, + { "C_ME", "/me manjakk" }, + { "C_TOPIC", "vahetab tihti topicut" }, + { "C_MODE", "vahetab tihti modesid" }, + { "C_KICK", "kickib palju" }, + { "C_KICKED", "saab tihti kicke" }, + { "C_URL", "reklaamib palju" }, + { "C_JOIN", "sõelub sisse ja välja" }, + { "C_NICK", "vahetab pidevalt nime" }, + { "C_MONOLOGUE", "räägib palju monolooge" } + } }; int language=0; /* default to english */ @@ -470,9 +585,10 @@ char *L(char *key) int debug=1; /* 0 = none ; 1 = normal ; 2 = verbose */ char channel[MAXLINELENGTH]="set_channel_in_config_file"; char maintainer[MAXLINELENGTH]="set_maintainer_in_config_file"; -char theme[MAXLINELENGTH]="default,blue,dark,grayscale,namour,pisg,zeduel,zerezo"; +char theme[MAXLINELENGTH]="default,biseau,blue,dark,damier,grayscale,namour,niflheim,pisg,zeduel,zerezo"; int refresh_time=0; /* 0 = disabled */ int w3c_link=1; /* 0 = disabled */ +int logo=1; /* 0 = disabled */ char header[MAXLINELENGTH]="none"; char footer[MAXLINELENGTH]="none"; int totallines=0; @@ -480,6 +596,9 @@ time_t debut; int top_words=1; /* 0 = disabled */ int ranking=0; /* 0 = lines ; 1 = words ; 2 = letters */ int quarter=0; /* 1 = enabled */ +int months=0; /* 1 = enabled */ +int weeks=0; /* 1 = enabled */ +int photo_size=60; struct user { @@ -490,6 +609,7 @@ struct user int hours[4]; char quote[MAXQUOTELENGTH+1]; int counters[NBCOUNTERS]; + char *photo; int temp; } *users; int nbusers=0; @@ -514,8 +634,10 @@ struct { int lines; int hours[4]; -} lastdays[31]; +} lastdays[31], lastweeks[31], lastmonths[31]; int days=0; +char currday[16]; +int currwday=-1, currmon=-1; int hours[24*4]; int lines=0; @@ -532,8 +654,89 @@ struct char word[MAXLINELENGTH]; } topwords[NBWORDS]; +struct rusletter +{ + int nb; + struct rusletter *next[33]; +} ruswords; + #define isletter(c) (((c>='a')&&(c<='z'))||((c>='A')&&(c<='Z'))) #define lowercase(c) (((c>='A')&&(c<='Z'))?c-'A'+'a':c) +//#define lowercase(c) (c | 0x20) +#define isrusletter(c) (memchr(koi,c,66)==NULL?0:1) + +const char koi[] = { +193,194,215,199,196,197,163,214,218,201,202,203,204,205,206,207,208,210, +211,212,213,198,200,195,222,219,221,216,223,217,220,192,209, +225,226,247,231,228,229,179,246,250,233,234,235,236,237,238,239,240,242, +243,244,245,230,232,227,254,251,253,248,255,249,252,224,241 +}; +int lowruscase(char c) +{ + char *ctmp_p; + int ch=0; + if (memchr(koi,c,66)==NULL) return koi[0]; + ch=strlen(koi)-strlen(memchr(koi,c,66)); + if (ch>33) return ch-33; else return ch; +} +/* cp1251 for encoding into koi8-r +const char win[] = { +224,225,226,227,228,229,184,230,231,232,233,234,235,236,237,238,239,240, +241,242,243,244,245,246,247,248,249,252,250,251,253,254,255, +192,193,194,195,196,197,168,198,199,200,201,202,203,204,205,206,207,208, +209,210,211,212,213,214,215,216,217,220,218,219,221,222,223 +};*/ + + + +int findruswords(char *message) +{ + int i,c,n=0; + //char *tmp_p; + struct rusletter *pos,*tmp; + for (;;) + { + while (!isrusletter(*message)) if (*message=='\0') return n; else message++; + pos=&ruswords; + while (isrusletter(*message)) + { + c=lowruscase(*message); + /*tmp_p=memchr(koi,message[0],33); + if (tmp_p==NULL) return n; + c=strlen(koi)-strlen(tmp_p);*/ + if (pos->next[(int)c]==NULL) + { + tmp=malloc(sizeof(struct rusletter)); + if (tmp==NULL) + { + fprintf(stderr, "findruswords(): malloc failure\n"); + exit(1); + } + tmp->nb=0; + for (i=0;i<33;i++) tmp->next[i]=NULL; + pos->next[(int)c]=tmp; + } + pos=pos->next[(int)c]; + message++; + } + pos->nb++; + n++; + } + return n; +} + + +void freeruswords(struct rusletter *pos) +{ + int i; + for (i=0;i<33;i++) if (pos->next[i]!=NULL) + { + freeruswords(pos->next[i]); + free(pos->next[i]); + (*pos).next[i]=NULL; + } +} + int findwords(char *message) { int i,c,n=0; @@ -589,6 +792,28 @@ void bestwords(struct letter pos,int cur) tempword[cur]='\0'; } +void bestruswords(struct rusletter pos,int cur) +{ + int i,j; + if ((cur>=MINWORDLENGTH)&&(pos.nb>topwords[NBWORDS-1].nb)) + { + for (i=0;pos.nbi;j--) + { + topwords[j].nb=topwords[j-1].nb; + strcpy(topwords[j].word,topwords[j-1].word); + } + topwords[i].nb=pos.nb; + strcpy(topwords[i].word,tempword); + } + for (i=0;i<33;i++) if (pos.next[i]!=NULL) + { + tempword[cur]=koi[i]; + bestruswords(*(pos.next[i]),cur+1); + } + tempword[cur]='\0'; +} + void freewords(struct letter *pos) { int i; @@ -643,6 +868,7 @@ int dichotomic(char *nick) strcpy(users[i].quote,users[i-1].quote); for (j=0;j0;i--) + { + lastdays[i].lines=lastdays[i-1].lines; + for (j=0;j<4;j++) lastdays[i].hours[j]=lastdays[i-1].hours[j]; + } + lastdays[0].lines=0; + for (j=0;j<4;j++) lastdays[0].hours[j]=0; + days++; + } + memcpy(currday, newday, 15); + if (debug==2) + fprintf(stderr, "day %d changed to: %s\n", days, currday); + + /* try to parse the date for weeks/months stats */ + if (strptime(currday, "%a %b %d %Y", &currdate)) + { + /* each monday we change the week number */ + if (currdate.tm_wday == 1) + { + for (i=30;i>0;i--) + { + lastweeks[i].lines=lastweeks[i-1].lines; + for (j=0;j<4;j++) lastweeks[i].hours[j]=lastweeks[i-1].hours[j]; + } + lastweeks[0].lines=0; + for (j=0;j<4;j++) lastweeks[0].hours[j]=0; + } + /* if the month has changed */ + if (currdate.tm_mon != currmon && currmon > 0) + { + for (i=30;i>0;i--) + { + lastmonths[i].lines=lastmonths[i-1].lines; + for (j=0;j<4;j++) lastmonths[i].hours[j]=lastmonths[i-1].hours[j]; + } + lastmonths[0].lines=0; + for (j=0;j<4;j++) lastmonths[0].hours[j]=0; + } + currwday = currdate.tm_wday; + currmon = currdate.tm_mon; + + } + } else { + if (debug==2) + fprintf(stderr, "but day did not change\n"); + } +} + void parse_log(char *logfile) { FILE *fic; @@ -664,160 +956,245 @@ void parse_log(char *logfile) int i,j; char *nick,*message; int nickstart; - int mononick,monolines; + int mononick=-1,monolines=0; int temp,hour; + int timelen; if ((fic=fopen(logfile,"rt"))==NULL) { fprintf(stderr,"can't open log file \"%s\"\n",logfile); exit(1); } if (debug) printf("working on %s : ",channel); while (fgets(line,MAXLINELENGTH,fic)!=NULL) { /* remove \n */ - for (i=0;line[i]!=0;i++); - if (i>=MAXLINELENGTH-1) { fprintf(stderr,"line %d is too long\n",totallines); exit(1); } + for (i=0;line[i]!=0 && i=MAXLINELENGTH-1) { + if(debug){ + fprintf(stderr,"line %d is too long, skipping\n",totallines+1); + } + continue; + } + if (i<8) { + if(debug) { + fprintf(stderr, "line %d is too short to be valid, skipping\n",totallines+1); + } + continue; + } line[i-1]='\0'; pos=0; totallines++; if (totallines%10000==0 && debug) { printf("."); fflush(stdout); } - if (strncmp("--- Day changed",line,15)==0) /* --- Day changed Wed May 01 2002 */ + if (strncmp("--- Log opened",line,14)==0) /* --- Log opened Wed May 01 00:00 2002 */ { - for (i=30;i>0;i--) - { - lastdays[i].lines=lastdays[i-1].lines; - for (j=0;j<4;j++) lastdays[i].hours[j]=lastdays[i-1].hours[j]; - } - lastdays[0].lines=0; - for (j=0;j<4;j++) lastdays[0].hours[j]=0; - days++; + if (debug==2) + fprintf(stderr, "log %s opened, ", logfile); + day_changed(line+15); } - else if (strncmp("-!- mode/",&line[6],9)==0) /* 00:00 -!- mode/#channel [...] by (Nick, Nick2, )Nick3 */ + if (strncmp("--- Day changed",line,15)==0) /* --- Day changed Wed May 01 2002 */ { - for (i=strlen(line);line[i]!=' ';i--); - nick=&line[i+1]; - users[dichotomic(nick)].counters[D_MODE]++; + if (debug==2) + fprintf(stderr, "within log file, "); + day_changed(line+16); } - else if (strncmp("-!-",&line[6],3)==0) /* 00:00 -!- Nick something... */ + else { - for (i=10;line[i]!=' ';i++); - line[i]='\0'; - nick=&line[10]; - message=&line[i+1]; - if (strncmp("changed the topic of",message,20)==0) /* 00:00 -!- Nick changed the topic of #channel to: new topic */ + /* timelen is number of characters occupied by time 00:00.. plus any space */ + timelen = 5; + if (line[timelen] == ':' && isdigit(line[timelen+1]) && isdigit(line[timelen+2])) + timelen += 3; + if (line[timelen] == ' ') + timelen++; + if (strncmp("-!- mode/",&line[timelen],9)==0) /* 00:00 -!- mode/#channel [...] by (Nick, Nick2, )Nick3 */ { - users[dichotomic(nick)].counters[D_TOPIC]++; - for (i=21;message[i]!=':';i++); - message=&message[i+2]; - nbtopics++; - if ((nbtopics<=NBTOPICS) || (rand()%(nbtopics/NBTOPICS)==0)) - { - temp=nbtopics<=NBTOPICS?nbtopics-1:rand()%NBTOPICS; - strcpy(topics[temp].nick,nick); - strncpy(topics[temp].topic,message,MAXQUOTELENGTH); - } + for (i=strlen(line);line[i]!=' ';i--); + nick=&line[i+1]; + users[dichotomic(nick)].counters[D_MODE]++; } - else if (strncmp("was kicked from",message,15)==0) /* 00:00 -!- Nick was kicked from #channel by Nick [Reason] */ + else if (strncmp("-!-",&line[timelen],3)==0) /* 00:00 -!- Nick something... */ { - users[dichotomic(nick)].counters[D_KICKED]++; - for (i=16;message[i]!=' ';i++); - message=&message[i+4]; - for (i=0;message[i]!=' ';i++); - message[i]='\0'; - users[dichotomic(message)].counters[D_KICK]++; - } - else if (strncmp("is now known as",message,15)==0) /* 00:00 -!- Nick is now known as Nick */ - users[dichotomic(nick)].counters[D_NICK]++; - else if (message[0]=='[') /* 00:00 -!- Nick [user@host] something... */ - { - for (i=0;message[i]!=']';i++); - message=&message[i+2]; - if (strncmp("has joined",message,10)==0) /* 00:00 -!- Nick [user@host] has joined #channel */ - users[dichotomic(nick)].counters[D_JOIN]++; - else if (strncmp("has quit",message,8)==0); /* 00:00 -!- Nick [user@host] has quit [Reason] */ - else if (strncmp("has left",message,8)==0); /* 00:00 -!- Nick [user@host] has left #channel [Reason] */ - else; - } - } - else if ((line[6]=='<') || (line[7]=='*')) - { - line[2]='\0'; - hour=atoi(line); - if (line[7]=='*') /* 00:00 * Nick the message */ - { - for (i=9;line[i]!=' ';i++); - nick=&line[9]; + for (i=10;line[i]!=' ' && i <= 10 + MAXNICKLENGTH;i++); + if(i > 10 + MAXNICKLENGTH) { + if(debug) { + fprintf(stderr,"nick on line %d is too long, skipping line\n",totallines); + } + continue; + } + line[i]='\0'; + nick=&line[timelen+4]; message=&line[i+1]; + if (strncmp("changed the topic of",message,20)==0) /* 00:00 -!- Nick changed the topic of #channel to: new topic */ + { + users[dichotomic(nick)].counters[D_TOPIC]++; + for (i=21;message[i]!=':';i++); + message=&message[i+2]; + nbtopics++; + if ((nbtopics<=NBTOPICS) || (rand()%(nbtopics/NBTOPICS)==0)) + { + temp=nbtopics<=NBTOPICS?nbtopics-1:rand()%NBTOPICS; + strcpy(topics[temp].nick,nick); + strncpy(topics[temp].topic,message,MAXQUOTELENGTH); + } + } + else if (strncmp("was kicked from",message,15)==0) /* 00:00 -!- Nick was kicked from #channel by Nick [Reason] */ + { + users[dichotomic(nick)].counters[D_KICKED]++; + for (i=16;message[i]!=' ';i++); + message=&message[i+4]; + for (i=0;message[i]!=' ';i++); + message[i]='\0'; + users[dichotomic(message)].counters[D_KICK]++; + } + else if (strncmp("is now known as",message,15)==0) /* 00:00 -!- Nick is now known as Nick */ + users[dichotomic(nick)].counters[D_NICK]++; + else if (message[0]=='[') /* 00:00 -!- Nick [user@host] something... */ + { + for (i=0;message[i]!=']';i++); + message=&message[i+2]; + if (strncmp("has joined",message,10)==0) /* 00:00 -!- Nick [user@host] has joined #channel */ + users[dichotomic(nick)].counters[D_JOIN]++; + else if (strncmp("has quit",message,8)==0); /* 00:00 -!- Nick [user@host] has quit [Reason] */ + else if (strncmp("has left",message,8)==0); /* 00:00 -!- Nick [user@host] has left #channel [Reason] */ + else; + } } - else if (line[7]=='>') /* 00:00 <>>>?Nick<<<> the personal message */ - /* 00:00 <>>?Nick<<> the personal message */ - { - for (i=10;line[i]!='<';i++); - nick=&line[10]; - if (line[9]=='>') nick++; - message=&line[i+5]; - } - else /* 00:00 the message */ + else if ((line[timelen]=='<') || (line[timelen+1]=='*')) { + line[2]='\0'; + hour=atoi(line); + if (line[timelen+1]=='*') /* 00:00 * Nick the message */ + { + for (i=timelen+3;line[i]!=' ' && i <= timelen+3+MAXNICKLENGTH;i++); + if(i > timelen+3+MAXNICKLENGTH) { + if(debug) { + fprintf(stderr,"nick on line %d is too long, skipping line\n",totallines); + } + continue; + } + nick=&line[timelen+3]; + message=&line[i+1]; + } + else if (line[timelen+1]=='>') /* 00:00 <>>>?Nick<<<> the personal message */ + /* 00:00 <>>?Nick<<> the personal message */ + { + for (i=timelen+4;line[i]!='<' && i <= timelen+4+MAXNICKLENGTH;i++); + if(i > timelen+4+MAXNICKLENGTH) { + if(debug) { + fprintf(stderr,"nick on line %d is too long, skipping line\n",totallines); + } + continue; + } + nick=&line[timelen+4]; + if (line[timelen+3]=='>') nick++; + message=&line[i+5]; + } + else /* 00:00 the message */ + { - /* - * Irssi doesn't log channel mode with show_nickmode = OFF - * the following covers op, half-op, voice and show_nickmode_empty - */ - if (line[7]=='@' || line[7]=='%' || line[7]=='+' || line[7]==' ') { - nickstart = 8; - } else { - nickstart = 7; + /* + * Irssi doesn't log channel mode with show_nickmode = OFF + * the following covers op, half-op, voice and show_nickmode_empty + */ + switch (line[timelen+1]) + { + case '@': + case '%': + case '+': + case '&': + case '~': + case ' ': + nickstart = timelen+2; + break; + default: + nickstart = timelen+1; + break; + } + + for (i=nickstart;line[i]!='>' && i <= nickstart + MAXNICKLENGTH;i++); + if(i > nickstart + MAXNICKLENGTH) { + if(debug) { + fprintf(stderr,"nick on line %d is too long, skipping line\n",totallines); + } + continue; + } + nick=&line[nickstart]; + message=&line[i+2]; } - - for (i=nickstart;line[i]!='>';i++); - nick=&line[nickstart]; - message=&line[i+2]; - } - line[i]='\0'; - i=dichotomic(nick); - if (line[7]=='*') users[i].counters[D_ME]++; - if (i==mononick) - { - monolines++; - if (monolines==5) users[i].counters[D_MONOLOGUE]++; - } - else - { - mononick=i; - monolines=1; - } - j=strlen(message); - users[i].lines++; - if (top_words || ranking==1) users[i].words+=findwords(message); - users[i].letters+=j; - users[i].hours[hour/6]++; - lastdays[0].lines++; - lastdays[0].hours[hour/6]++; - lines++; - if (quarter) - { - line[5]='\0'; - hour=hour*4+atoi(&line[3])/15; - } - hours[hour]++; - if (message[j-1]=='?') users[i].counters[D_QUESTION]++; - else if (message[j-1]=='!') users[i].counters[D_EXCLAM]++; - else if ((message[j-3]==' ')&&(message[j-2]==':')) - { - if (message[j-1]==')') users[i].counters[D_SMILE]++; - else if (message[j-1]=='(') users[i].counters[D_FROWN]++; - } - if (rand()%users[i].lines==0) strncpy(users[i].quote,message,MAXQUOTELENGTH); - if (strncmp("http://",message,7)==0) - { - users[i].counters[D_URL]++; - for (i=0;(message[i]!=' ') && (i 25 && len < 70 ) + { + strncpy(users[i].quote,message,MAXQUOTELENGTH); + } else { + int len2 = strlen(users[i].quote); + if ( !(len2 > 25 && len2 < 70 )) { + strncpy(users[i].quote,message,MAXQUOTELENGTH); + } + } + } + + if (strncmp("http://",message,7)==0) + { + users[i].counters[D_URL]++; + for (i=0;(message[i]!=' ') && (i\n\n",L("CHARSET")); if (refresh_time) fprintf(fic,"\n",refresh_time); - subtheme=strtok(theme,","); + strcpy(line, theme); + subtheme=strtok(line,","); fprintf(fic,"\n",subtheme,subtheme); while ((subtheme=strtok(NULL,","))!=NULL) fprintf(fic,"\n",subtheme,subtheme); @@ -916,6 +1316,42 @@ void gen_xhtml(char *xhtmlfile) for (i=0;i<4;i++) fprintf(fic,"
%s %d-%d\n",i+1,L("HOURS"),i*6,i*6+5); fprintf(fic,"\n\n\n\n"); + if (months) + { + /* last months */ + fprintf(fic,"
\n

%s

\n\n\n",L("LASTMONTHS")); + max=-1; + for (i=30;i>=0;i--) if (lastmonths[i].lines>max) max=lastmonths[i].lines; + for (i=30;i>=0;i--) + { + fprintf(fic,"\n"); + } + fprintf(fic,"\n\n"); + for (i=30;i>=0;i--) + fprintf(fic,"\n",i); + fprintf(fic,"\n
%d",lastmonths[i].lines); + for (j=0;j<4;j++) if (lastmonths[i].hours[j]!=0) fprintf(fic,"
",j+1,150*lastmonths[i].hours[j]/max); + fprintf(fic,"
%d
\n
\n\n"); + } + + if (weeks) + { + /* last weeks */ + fprintf(fic,"
\n

%s

\n\n\n",L("LASTWEEKS")); + max=-1; + for (i=30;i>=0;i--) if (lastweeks[i].lines>max) max=lastweeks[i].lines; + for (i=30;i>=0;i--) + { + fprintf(fic,"\n"); + } + fprintf(fic,"\n\n"); + for (i=30;i>=0;i--) + fprintf(fic,"\n",i); + fprintf(fic,"\n
%d",lastweeks[i].lines); + for (j=0;j<4;j++) if (lastweeks[i].hours[j]!=0) fprintf(fic,"
",j+1,150*lastweeks[i].hours[j]/max); + fprintf(fic,"
%d
\n
\n\n"); + } + /* last days */ fprintf(fic,"
\n

%s

\n\n\n",L("LASTDAYS")); max=-1; @@ -958,13 +1394,15 @@ void gen_xhtml(char *xhtmlfile) switch (ranking) { case 0: - fprintf(fic,"
\n\n",L("NICK"),L("NBLINES"),L("HOURS"),L("AVGLETTERS"),L("QUOTE")); + fprintf(fic,"
%s%s%s%s%s
\n\n",L("NICK"),L("NBLINES"),L("HOURS"),L("AVGLETTERS"),L("QUOTE")); break; default: /* "letters" and "words" ranking are not yet translated so we use the generic word "rank" ... */ - fprintf(fic,"
%s%s%s%s%s
\n\n",L("NICK"),"rank",L("HOURS"),L("AVGLETTERS"),L("QUOTE")); + fprintf(fic,"
%s%s%s%s%s
\n\n",L("NICK"),"rank",L("HOURS"),L("AVGLETTERS"),L("QUOTE")); break; } + if (photos) fprintf(fic,""); + fprintf(fic,""); for (i=1;i<=NBUSERS;i++) { user=-1; @@ -998,7 +1436,15 @@ void gen_xhtml(char *xhtmlfile) for (j=0;j<4;j++) if (users[user].hours[j]!=0) fprintf(fic,"
",j+1,100*users[user].hours[j]/users[user].lines); fprintf(fic,"\n"); + fprintf(fic,"\""); + if (photos && users[user].photo!=NULL) + { + if (photo_size) + fprintf(fic,"",users[user].photo,users[user].photo,photo_size,photo_size); + else + fprintf(fic,"",users[user].photo); + } + fprintf(fic,"\n"); users[user].lines=-1; users[user].words=-1; users[user].letters=-1; @@ -1094,10 +1540,16 @@ void gen_xhtml(char *xhtmlfile) fprintf(fic,"

\n\"Valid\n"); fprintf(fic,"\"Valid\n

\n"); } - fprintf(fic,"\n\n"); - if (strcmp("none",header)==0) + fprintf(fic,"\n\n"); + + /* logo*/ + if (logo) fprintf(fic,"
\n\n"); + + /* end */ + fprintf(fic,"\n\n"); + if (strcmp("none",footer)==0) { - fprintf(fic,"\n\n\n\n\n"); + fprintf(fic,"\n\n\n"); } else { @@ -1109,6 +1561,17 @@ void gen_xhtml(char *xhtmlfile) fclose(fic); } +void expand(char *path) +{ + char temp[MAXLINELENGTH]; + if (*path=='~') + { + snprintf(temp,MAXLINELENGTH-1,"%s%s",getenv("HOME"),path+1); + temp[MAXLINELENGTH-1]='\0'; + strcpy(path,temp); + } +} + void parse_config(char *configfile) { FILE *fic; @@ -1116,7 +1579,7 @@ void parse_config(char *configfile) char keyword[MAXLINELENGTH]; char value[MAXLINELENGTH]; int configlines=0; - int i; + int i,j; if (configfile!=NULL) { @@ -1128,11 +1591,12 @@ void parse_config(char *configfile) } else { - sprintf(line,"%s/.irssistats",getenv("HOME")); + snprintf(line,MAXLINELENGTH-1,"%s/.irssistats",getenv("HOME")); + line[MAXLINELENGTH-1]='\0'; if ((fic=fopen(line,"rt"))==NULL) - if ((fic=fopen("/etc/irssistats.conf","rt"))==NULL) + if ((fic=fopen(GLOBALCONF,"rt"))==NULL) { - fprintf(stderr,"can't find config file : \"%s\" nor \"/etc/irssistats.conf\"\n",line); + fprintf(stderr,"can't find config file : \"%s\" nor \"" GLOBALCONF "\"\n",line); fprintf(stderr,"please give the path to the config file in argument\n"); exit(1); } @@ -1198,6 +1662,13 @@ void parse_config(char *configfile) } else + if (strcmp("photo_size",keyword)==0) + { + photo_size=atoi(value); + if (debug==2) fprintf(stderr,"setting photo_size to \"%d\"\n",photo_size); + } + else + if (strcmp("w3c_link",keyword)==0) { if (debug==2) fprintf(stderr,"setting w3c_link to \"%s\"\n",value); @@ -1207,8 +1678,18 @@ void parse_config(char *configfile) } else + if (strcmp("logo",keyword)==0) + { + if (debug==2) fprintf(stderr,"setting logo to \"%s\"\n",value); + if (strcmp("no",value)==0) logo=0; + else if (strcmp("yes",value)==0) logo=1; + else { fprintf(stderr,"unknown value for \"logo\" option, must be \"yes\" or \"no\"\n"); exit(1); } + } + else + if (strcmp("header",keyword)==0) { + expand(value); if (debug==2) fprintf(stderr,"setting header to \"%s\"\n",value); strcpy(header,value); } @@ -1216,6 +1697,7 @@ void parse_config(char *configfile) if (strcmp("footer",keyword)==0) { + expand(value); if (debug==2) fprintf(stderr,"setting footer to \"%s\"\n",value); strcpy(footer,value); } @@ -1223,6 +1705,7 @@ void parse_config(char *configfile) if (strcmp("input",keyword)==0) { + expand(value); if (debug==2) fprintf(stderr,"parsing log file \"%s\"\n",value); parse_log(value); } @@ -1230,15 +1713,30 @@ void parse_config(char *configfile) if (strcmp("nickfile",keyword)==0) { + expand(value); if (debug==2) fprintf(stderr,"nick alias using file \"%s\"\n",value); +#ifdef __WIN32__ + fprintf(stderr,"no support for nickfile in WIN32 version\n"); +#else parse_nick(value); +#endif + } + else + + if (strcmp("photofile",keyword)==0) + { + expand(value); + if (debug==2) fprintf(stderr,"parsing photo file \"%s\"\n",value); + parse_photo(value); } else if (strcmp("output",keyword)==0) { + expand(value); if (debug==2) fprintf(stderr,"generating xhtml file \"%s\"\n",value); bestwords(words,0); + if (L("CHARSET")=="KOI8-R") bestruswords(ruswords,0); gen_xhtml(value); /* reset variables */ @@ -1246,12 +1744,32 @@ void parse_config(char *configfile) nburls=0; nbtopics=0; days=0; + currwday=-1; + currmon=-1; for (i=0;i<24*4;i++) hours[i]=0; lines=0; + for (i=0;i<31;i++) + { + lastdays[i].lines=0; + lastweeks[i].lines=0; + lastmonths[i].lines=0; + for (j=0;j<4;j++) + { + lastdays[i].hours[j]=0; + lastweeks[i].hours[j]=0; + lastmonths[i].hours[j]=0; + } + } freewords(&words); + freeruswords(&ruswords); for (i=0;i
%s%s%s%s%s
%d
\"",users[user].lines!=0?users[user].letters/users[user].lines:0,users[user].lines!=0?users[user].letters/users[user].lines:0); printhtml(fic,users[user].quote); - fprintf(fic,"\"
\"\"\"\"