/* * Copyright (C) 2000,2001 Florian Sander * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * 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. */ static struct dcc_table LIVESTATS_LISTEN = { "LIVESTATS_LISTEN", DCT_VALIDIDX, eof_livestats, livestats_accept, 0, timeout_listen_livestats, display_livestats_accept, 0, NULL, 0 }; static struct dcc_table LIVESTATS = { "LIVESTATS", DCT_VALIDIDX, eof_livestats, livestats_activity, &livestats_timeout, timeout_livestats, display_livestats, expmem_livestats, kill_livestats, #ifdef OLDBOT out_livestats, #else out_livestats, outdone_livestats #endif }; static int inactivechan(char *chan) { struct chanset_t *ch; ch = findchan_by_dname(chan); if (!ch) return 1; if (ch->status & CHAN_INACTIVE) return 1; return 0; } static int nostats(char *chan) { #if EGG_IS_MIN_VER(10503) if (ngetudef("nostats", chan)) return 1; #endif return 0; } static void start_listen_livestats(int port) { int i, zz; char tmp[50]; stop_listen_livestats(); sprintf(tmp, "set my-ip \"%s\";", livestats_ip); do_tcl("livestats-hack-start", "set my-ip-livestats-backup ${my-ip};" "set my-hostname-livestats-backup ${my-hostname};" "set my-hostname \"\""); do_tcl("livestats-hack-setip", tmp); zz = open_listen(&port); do_tcl("livestats-hack-end", "set my-ip ${my-ip-livestats-backup};" "set my-hostname ${my-hostname-livestats-backup}"); if (zz == (-1)) { putlog(LOG_MISC, "*", "ERROR! Cannot open listening socket for livestats!"); return; } if ((i = new_dcc(&LIVESTATS_LISTEN, 0)) == -1) { putlog(LOG_MISC, "*", "ERROR! Cannot open listening socket for livestats! DCC table is full!"); return; } dcc[i].sock = zz; dcc[i].addr = (IP) (-559026163); dcc[i].port = port; strcpy(dcc[i].nick, "livestats"); strcpy(dcc[i].host, "*"); dcc[i].timeval = now; putlog(LOG_MISC, "*", "Now listening for livestats connections on port %d", port); } static void stop_listen_livestats() { int i; for (i = 0; i < dcc_total; i++) { if (dcc[i].type == &LIVESTATS_LISTEN) { putlog(LOG_MISC, "*", "no longer listening for livestats connections on port %d", dcc[i].port); killsock(dcc[i].sock); lostdcc(i); } else if (dcc[i].type == &LIVESTATS) { putlog(LOG_MISC, "*", "killing livestats connection from %s", dcc[i].host); killsock(dcc[i].sock); lostdcc(i); } } } static void livestats_activity(int idx, char *buf, int len) { char *cmd, *path, *newpath, *imask; int lev; imask = nmalloc(strlen(dcc[idx].host) + 13); sprintf(imask, "livestats!*@%s", dcc[idx].host); if (match_ignore(imask)) { debug1("Ignoring livestats access from %s", dcc[idx].host); stats_info_access(idx)->code = 401; if (livestats_ignore_msg[0]) dprintf(idx, "HTTP/1.0 401 Access Forbidden\nContent-Type: text/html\n\n%s", livestats_ignore_msg); killsock(dcc[idx].sock); lostdcc(idx); nfree(imask); return; } nfree(imask); if (!strncasecmp(buf, "GET ", 4)) { if (!stats_info_access(idx)->cmd) { stats_info_access(idx)->cmd = nmalloc(strlen(buf) + 1); strcpy(stats_info_access(idx)->cmd, buf); stats_info_access(idx)->code = 200; } } cmd = newsplit(&buf); if (!strcmp(cmd, "GET")) { if (livestats_flood()) { stats_info_access(idx)->code = 401; killsock(dcc[idx].sock); lostdcc(idx); return; } lev = logmodes(stats_loglevel); if (lev) putlog(lev, "*", "%s: GET %s", dcc[idx].host, buf); path = newsplit(&buf); if (!strncasecmp(path, "/robots.txt", 11)) { dprintf(idx, "HTTP/1.1 404 Not Found\nServer: stats.mod/%s\nConnection: close", MODULE_VERSION); dprintf(idx, "Content-Type: text/html; charset=iso-8859-1\n\n"); dprintf(idx, "404 Not Found

Not Found

"); dprintf(idx, "The requested document was not found on this server."); stats_info_access(idx)->code = 404; return; } if (path[strlen(path) - 1] != '/') { newpath = nmalloc(strlen(path) + 2); strcpy(newpath, path); newpath[strlen(path)] = '/'; newpath[strlen(path) + 1] = 0; dprintf(idx, "HTTP/1.1 301 Moved Permanently\nServer: stats.mod/%s\n", MODULE_VERSION); dprintf(idx, "Location: %s\nConnection: close\nContent-Type: text/html\n\n", newpath); dprintf(idx, "The concluding \"/\" is important!
"); dprintf(idx, "%s

", newpath, newpath); stats_info_access(idx)->code = 301; nfree(newpath); return; } dprintf(idx, "HTTP/1.0 200 OK\nServer: stats.mod/%s\nContent-Type: text/html\n\n", MODULE_VERSION); send_livestats(idx, path); } else if (!strcasecmp(cmd, "User-Agent:")) { if (stats_info_access(idx)->browser) return; stats_info_access(idx)->browser = nmalloc(strlen(buf) + 1); strcpy(stats_info_access(idx)->browser, buf); } else if (!strcasecmp(cmd, "Referer:")) { if (stats_info_access(idx)->referer) return; stats_info_access(idx)->referer = nmalloc(strlen(buf) + 1); strcpy(stats_info_access(idx)->referer, buf); } else if (!buf[0]) { dcc[idx].status = 1; #ifndef OLDBOT /* If there's no data in our socket, we immediately get rid of it. */ if (!sock_has_data(SOCK_DATA_OUTGOING, dcc[idx].sock)) { killsock(dcc[idx].sock); lostdcc(idx); } #endif } } #ifndef OLDBOT static void outdone_livestats(int idx) { if (dcc[idx].status) { killsock(dcc[idx].sock); lostdcc(idx); } else dcc[idx].status = 1; } #endif static void display_livestats(int idx, char *buf) { sprintf(buf, "livestats"); } static void display_livestats_accept(int idx, char *buf) { sprintf(buf, "lstn port"); } static void timeout_livestats(int idx) { killsock(dcc[idx].sock); lostdcc(idx); } static void timeout_listen_livestats(int idx) { debug0("timeout listen"); killsock(dcc[idx].sock); lostdcc(idx); } static void kill_livestats(int idx, void *x) { register struct stats_clientinfo *p = (struct stats_clientinfo *) x; char ts[41], test[11]; time_t tt; FILE *f; Context; tt = now; if (!p) { putlog(LOG_MISC, "*", "Can't kill clientinfo, no pointer. This should not happen!"); return; } ctime(&tt); /* 05/Feb/2000:12:08:17 +0100 */ strftime(test, 19, "%z", localtime(&tt)); if (test[0] != 'z') strftime(ts, 40, "%d/%b/%Y:%H:%M:%S %z", localtime(&tt)); else strftime(ts, 40, "%d/%b/%Y:%H:%M:%S", localtime(&tt)); if (livestats_log[0]) { f = fopen(livestats_log, "a"); if (f == NULL) putlog(LOG_MISC, "*", "ERROR writing livestats log."); else { if (test[0] != 'z') fprintf(f, "%s - - [%s] \"%s\" %d %d \"%s\" \"%s\"\n", dcc[idx].host, ts, p->cmd ? p->cmd : "", p->code, p->traffic, p->referer ? p->referer : "-", p->browser ? p->browser : ""); else fprintf(f, "%s - - [%s %+05d] \"%s\" %d %d \"%s\" \"%s\"\n", dcc[idx].host, ts, offset * (-1) * 100, p->cmd ? p->cmd : "", p->code ,p->traffic, p->referer ? p->referer : "-", p->browser ? p->browser : ""); fclose(f); } } if (p->browser) nfree(p->browser); if (p->referer) nfree(p->referer); if (p->cmd) nfree(p->cmd); nfree(p); } static int expmem_livestats(void *x) { register struct stats_clientinfo *p = (struct stats_clientinfo *) x; int tot = sizeof(struct stats_clientinfo); Context; if (!p) { putlog(LOG_MISC, "*", "Can't expmem clientinfo, no pointer. This should not happen!"); return 0; } if (p->browser) tot += strlen(p->browser) + 1; if (p->referer) tot += strlen(p->referer) + 1; if (p->cmd) tot += strlen(p->cmd) + 1; return tot; } static void out_livestats(int idx, char *buf, void *x) { register struct stats_clientinfo *p = (struct stats_clientinfo *) x; if (!p) { putlog(LOG_MISC, "*", "No stats_clientinfo pointer. This should not happen!"); return; } p->traffic += strlen(buf); tputs(dcc[idx].sock, buf, strlen(buf)); } static void livestats_accept(int idx, char *buf, int len) { unsigned long ip; unsigned short port; int j = 0, sock, i; char s[UHOSTLEN]; Context; if (dcc_total + 1 >= max_dcc) { j = answer(dcc[idx].sock, s, &ip, &port, 0); if (j != -1) { dprintf(-j, "Sorry, too many connections already.\r\n"); killsock(j); } return; } sock = answer(dcc[idx].sock, s, &ip, &port, 0); if (sock < 0) { neterror(s); putlog(LOG_MISC, "*", "Stats.mod: Error accepting livestats connection: %s", s); return; } if ((i = new_dcc(&LIVESTATS, sizeof(struct stats_clientinfo))) == (-1)) { putlog(LOG_MISC, "*", "Error accepting livestats connection. DCC table is full."); killsock(sock); return; } dcc[i].sock = sock; dcc[i].addr = ip; dcc[i].port = port; strcpy(dcc[i].nick, "httpstats"); #ifndef OLDBOT sprintf(s, "%s", iptostr(my_htonl(ip))); #else sprintf(s, "%lu.%lu.%lu.%lu", (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); /* dw */ #endif strcpy(dcc[i].host, s); dcc[i].timeval = now; dcc[i].status = 0; ((struct stats_clientinfo *) dcc[i].u.other)->traffic = 0; ((struct stats_clientinfo *) dcc[i].u.other)->code = 200; ((struct stats_clientinfo *) dcc[i].u.other)->browser = NULL; ((struct stats_clientinfo *) dcc[i].u.other)->referer = NULL; ((struct stats_clientinfo *) dcc[i].u.other)->cmd = NULL; } static int mlstat_time = 0, mlstat_thr = 0; static int livestats_flood() { if (!maxlivestats_thr || !maxlivestats_time) return 0; if ((now - mlstat_time) > maxlivestats_time) { mlstat_time = now; mlstat_thr = 0; } mlstat_thr++; if (mlstat_thr > maxlivestats_thr) return 1; return 0; } static void eof_livestats(int idx) { debug0("eof accept"); killsock(dcc[idx].sock); lostdcc(idx); } static void send_livestats(int idx, char *buf) { char *channel, *command; char what[512], *pwhat, *type, *stoday, *user, prefix[4]; struct chanset_t *chan; int today = 0; globstats *gs; locstats *ls, *ls2; time_t tt, ttbuf; struct userrec *u; int itype, nr, i, ii; wordstats *ws; quotestr *qs; unsigned long x; int wert; float r, g, b; float r2, g2, b2; float rstep, gstep, bstep; struct stats_userlist *suser; ttbuf = now; tt = now; if (!strcmp(buf, "/")) { setslglobs(NULL, 0, 0, 0); dprintf(idx, "%s\n%s\n\n", ROOTTITLE, SLCSS); dprintf(idx, "%s\n", SLBODYTAG); long_dprintf(idx, SLHEADER); dprintf(idx, "


\n"); for (gs = sdata; gs; gs = gs->next) { if (!inactivechan(gs->chan) && !secretchan(gs->chan) && !nostats(gs->chan)) { if (gs->chan[0] == '!') strcpy(prefix, "!"); else if (gs->chan[0] == '+') strcpy(prefix, "+"); else if (gs->chan[0] == '&') strcpy(prefix, "&"); else prefix[0] = 0; #ifndef OLDBOT chan = findchan_by_dname(gs->chan); #else chan = findchan(gs->chan); #endif i = 7; if (!show_userlist) i--; if (!show_usersonchan) i--; dprintf(idx, "", prefix, gs->chan + 1, gs->chan, filt2(chan->channel.topic)); else dprintf(idx, "%s", prefix, gs->chan + 1, gs->chan); dprintf(idx, "", SLTOP); setslglobs(gs->chan, gs->peak[S_TOTAL], countstatmembers(gs), gs->started); dprintf(idx, "", prefix, gs->chan + 1, SLTOTAL); dprintf(idx, "\n"); dprintf(idx, "", prefix, gs->chan + 1, SLDAILY); dprintf(idx, "\n"); dprintf(idx, "", prefix, gs->chan + 1, SLWEEKLY); dprintf(idx, "\n"); dprintf(idx, "", prefix, gs->chan + 1, SLMONTHLY); dprintf(idx, "\n"); if (show_userlist) dprintf(idx, "", prefix, gs->chan + 1, SLUSERS); if (show_usersonchan) dprintf(idx, "", prefix, gs->chan + 1, SLONCHAN); dprintf(idx, "", prefix, gs->chan + 1, SLMISCSTATS); dprintf(idx, "\n"); } } dprintf(idx, "
", i); if (chan && chan->channel.topic) dprintf(idx, "%s
(%s)
%s%s
%s
%s
%s
%s
%s
%s
 
"); dprintf(idx, ""); dprintf(idx, "Stats.mod v%s
\n", MODULE_VERSION); long_dprintf(idx, SLFOOTER); dprintf(idx, "\n"); return; } if (buf[0] == '/') { if (!strncasecmp(buf, "/e/", 3)) { buf += 2; buf[0] = '!'; } else if (!strncasecmp(buf, "/p/", 3)) { buf += 2; buf[0] = '+'; } else if (!strncasecmp(buf, "/a/", 3)) { buf += 2; buf[0] = '&'; } else if (buf[1] && strchr("+&!", buf[1])) buf++; else buf[0] = '#'; } if (buf[strlen(buf) - 1] == '/') buf[strlen(buf) - 1] = 0; channel = splitpath(&buf); #ifndef OLDBOT chan = findchan_by_dname(channel); #else chan = findchan(channel); #endif if (!chan) { dprintf(idx, "no such channel %s", channel); if (idx >= 0) stats_info_access(idx)->code = 404; return; } gs = findglobstats(channel); if (gs) setslglobs(gs->chan, gs->peak[S_TOTAL], countstatmembers(gs), gs->started); else setslglobs(channel, 0, 0, 0); if (!strcmp(buf, "/") || !buf[0]) { dprintf(idx, "%s\n%s\n%s", SLINDEXTITEL, SLCSS, SLBODYTAG); long_dprintf(idx, SLHEADER); dprintf(idx, "


\n"); dprintf(idx, "\n"); dprintf(idx, "", channel); dprintf(idx, "", SLTOP); dprintf(idx, "", SLTOTAL); dprintf(idx, "\n"); dprintf(idx, "", SLDAILY); dprintf(idx, "\n"); dprintf(idx, "", SLWEEKLY); dprintf(idx, "\n"); dprintf(idx, "", SLMONTHLY); dprintf(idx, "\n"); if (show_userlist) dprintf(idx, "", SLUSERS); if (show_usersonchan) dprintf(idx, "", SLONCHAN); dprintf(idx, "", SLMISCSTATS); dprintf(idx, "\n"); dprintf(idx, "
%s
%s%s
%s
%s
%s
%s
%s
%s
 
"); dprintf(idx, ""); dprintf(idx, "Stats.mod v%s
\n", MODULE_VERSION); dprintf(idx, "
\n"); long_dprintf(idx, SLFOOTER); dprintf(idx, "\n"); return; } command = splitpath(&buf); if (!strcasecmp(command, "top")) { if (!strcmp(buf, "/") || !buf[0]) { dprintf(idx, ""); dprintf(idx, ""); dprintf(idx, ""); dprintf(idx, "
total
today
"); return; } stoday = splitpath(&buf); if (!strcasecmp(stoday, "today") || !strcasecmp(stoday, "daily")) today = S_DAILY; else if (!strcasecmp(stoday, "weekly")) today = S_WEEKLY; else if (!strcasecmp(stoday, "monthly")) today = S_MONTHLY; else if (!strcasecmp(stoday, "total")) today = 0; else { dprintf(idx, "Error, invalid value %s", stoday); dprintf(idx, ""); dprintf(idx, ""); dprintf(idx, ""); dprintf(idx, ""); dprintf(idx, "
total
daily
weekly
monthly
"); Assert(idx >= 0); stats_info_access(idx)->code = 404; return; } if (!strcmp(buf, "/") || !buf[0]) { dprintf(idx, ""); sprintf(what, "%s", webstats); pwhat = what; while (strlen(pwhat) > 0) { type = newsplit(&pwhat); itype = typetoi(type); if (itype >= 0) { dprintf(idx, "", type, type); } } dprintf(idx, "
%s
"); return; } gs = findglobstats(channel); if (!gs) { debug1("Error! Can't find global stats for %s", channel); dprintf(idx, "Error! Can't find global stats for %s", channel); if (idx >= 0) stats_info_access(idx)->code = 404; return; } if (!strncasecmp(buf, "graph", 5)) { do_graphs(idx, today, gs, channel); return; } do_toptalkers(idx, today, gs, channel, buf); return; } else if (!strcasecmp(command, "onchan")) { display_users_on_chan(idx, channel, chan); } else if (!strcasecmp(command, "users")) { gs = findglobstats(channel); if (!gs) { debug1("Error! Can't find global stats for %s", channel); dprintf(idx, "Error! Can't find global stats for %s", channel); return; } setslglobs(gs->chan, gs->peak[S_TOTAL], countstatmembers(gs), gs->started); if (!strcmp(buf, "/") || !buf[0]) { if (!show_userlist) return; sort_stats_alphabetically(gs); dprintf(idx, "%s\n%s\n%s", SLUSERSTITLE, SLCSS, SLBODYTAG); long_dprintf(idx, SLHEADER); dprintf(idx, "
\n"); dprintf(idx, "\n\n", table_border); i = 0; for (ls = gs->local; ls; ls = ls->next) i++; wert = table_color; b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16; wert = fade_table_to; b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16; rstep = (r2 - r) / i; gstep = (g2 - g) / i; bstep = (b2 - b) / i; for (ls = gs->local; ls; ls = ls->next) { u = get_user_by_handle(userlist, ls->user); what[0] = 0; get_handle_chaninfo(ls->user, channel, what); pwhat = what; if (!what[0]) pwhat = get_user(&USERENTRY_INFO, u); if (!pwhat) { sprintf(what, " "); pwhat = what; } dprintf(idx, "\n", (int) r, (int) g, (int) b, ls->user, ls->user, filt2(pwhat)); r += rstep; g += gstep; b += bstep; } /* * dprintf(idx, "
UserInfo
%s%s
"); * dprintf(idx, "Stats.mod v%s
\n", MODULE_VERSION); */ dprintf(idx, "\n"); dprintf(idx, "


\n"); dprintf(idx, "\n"); dprintf(idx, "\n"); dprintf(idx, "
\n"); dprintf(idx, "\n", ISLINK(show_usersonchan), ISTEXT(show_usersonchan, SLONCHAN)); dprintf(idx, "\n", webnr); dprintf(idx, "\n", SLMISCSTATS); dprintf(idx, "\n", SLOTHERCHANS); dprintf(idx, "
<%sa " "href=\"../onchan/\">%stop%d%s%s
\n"); dprintf(idx, "
Created by Stats.mod v%s
", MODULE_VERSION); dprintf(idx, "
\n"); long_dprintf(idx, SLFOOTER); dprintf(idx, ""); return; } user = buf; ls = findlocstats(channel, user); if (!ls) { debug2("Error! Can't find local stats for %s in %s", user, channel); dprintf(idx, "I don't have any stats for %s in %s, sorry", user, channel); if (idx >= 0) stats_info_access(idx)->code = 404; return; } i = countwords(webstats) + 2; suser = findsuser_by_name(user); dprintf(idx, "\n"); slgloblocstats = ls; dprintf(idx, "%s\n%s\n%s\n", SLUSERTITLE, SLCSS, SLBODYTAG); long_dprintf(idx, SLHEADER); dprintf(idx, "
\n"); dprintf(idx, "%s\n", SLUSERHEAD); if (suser) { dprintf(idx, "
"); if (suser->email) dprintf(idx, "%s
", suser->email, SLEMAIL); if (suser->homepage) dprintf(idx, "%s
", suser->homepage, SLHOMEPAGE); dprintf(idx, "

"); } dprintf(idx, "", table_border, SLPLACE); sprintf(what, "%s", webstats); pwhat = what; while (strlen(pwhat) > 0) { dprintf(idx, "", getslangtype(newsplit(&pwhat))); } dprintf(idx, "\n"); wert = table_color; b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16; wert = fade_table_to; b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16; rstep = (r2 - r) / 4; gstep = (g2 - g) / 4; bstep = (b2 - b) / 4; for (today = 0; today < 4; today++) { dprintf(idx, "", RANGESTR_LONG); nr = 0; if (ls->values[today][T_WORDS] > 0) { sortstats(gs, T_WORDS, today); for (ls2 = gs->slocal[today][T_WORDS]; ls2; ls2 = ls2->snext[today][T_WORDS]) { nr++; if (!strcasecmp(ls2->user, user)) break; } } dprintf(idx, ""); else dprintf(idx, "%d", nr); sprintf(what, "%s", webstats); pwhat = what; while (strlen(pwhat) > 0) { itype = typetoi(newsplit(&pwhat)); dprintf(idx, "", stats_duration(ls->values[today][itype] * 60)); else if (itype >= 0) dprintf(idx, "%d", ls->values[today][itype]); else if (itype == T_WPL) { if (ls->values[today][T_LINES]) dprintf(idx, "%.2f", (float) ls->values[today][T_WORDS] / (float) ls->values[today][T_LINES]); else dprintf(idx, "0"); } else if (itype == T_IDLE) { if (ls->values[today][T_LINES]) dprintf(idx, "%.2f", (float) ls->values[today][T_MINUTES] / (float) ls->values[today][T_LINES]); else dprintf(idx, "0"); } else dprintf(idx, "ERR!"); } dprintf(idx, "\n"); r += rstep; g += gstep; b += bstep; } if (ls->quotes && quote_freq) { nr = 0; for (qs = ls->quotes; qs; qs = qs->next) nr++; x = random() % nr; ii = 0; qs = ls->quotes; while (qs) { if (ii == x) { dprintf(idx, "\n"); break; } qs = qs->next; ii++; } } dprintf(idx, "
%s%s
%s\n", (int) r, (int) g, (int) b); if (nr == 0) dprintf(idx, "-\n", (int) r, (int) g, (int) b); if (itype == T_MINUTES) dprintf(idx, "%s
", i); dprintf(idx, SLRANDQUOTE, filt2(qs->quote)); dprintf(idx, "
\n"); if (ls->words) { if (ls->words) { nr = 0; for (ws = ls->words; ws; ws = ws->next) nr++; slglobint = nr; dprintf(idx, "


%s
\n", SLUWORDSTATS); sortwordstats(ls, NULL); dprintf(idx, "\n"); nr = 0; ws = ls->words; while (ws && (nr < 10)) { nr++; dprintf(idx, "\n", nr, filt2(ws->word), ws->nr); ws = ws->next; } dprintf(idx, "
%d.%s(%d)


\n"); } } dprintf(idx, "


\n"); dprintf(idx, "\n"); dprintf(idx, "\n"); dprintf(idx, "
\n"); dprintf(idx, "\n", ISLINK(show_usersonchan), ISTEXT(show_usersonchan, SLOTHERUSERS)); dprintf(idx, "\n", ISLINK(show_usersonchan), ISTEXT(show_usersonchan, SLONCHAN)); dprintf(idx, "\n", SLTOP); dprintf(idx, "\n", SLMISCSTATS); dprintf(idx, "\n", SLOTHERCHANS); dprintf(idx, "
<%sa href=\"../\">%s<%sa href=\"../../onchan\">%s%s%s%s
\n"); dprintf(idx, "
Created by Stats.mod v%s
", MODULE_VERSION); long_dprintf(idx, SLFOOTER); dprintf(idx, ""); return; } else if (!strcasecmp(command, "misc")) { do_miscstats(idx, channel); return; } else { dprintf(idx, "Error! unknown command %s", command); if (idx >= 0) stats_info_access(idx)->code = 404; return; } } static void do_graphs(int idx, int today, globstats *gs, char *channel) { int itype, nr; int total, rest, width, max; float onep, percent, wpercent; char bground[140]; locstats *ls; char what[512], *pwhat, *type; Context; setslglobs(gs->chan, gs->peak[S_TOTAL], countstatmembers(gs), gs->started); if (graphgif[0] == 0) bground[0] = 0; else sprintf(bground, "background=\"%s\"", graphgif); dprintf(idx, "\n", MODULE_VERSION); dprintf(idx, "\n"); if (today == 0) dprintf(idx, "%s\n", SLGRTTITLE); else if (today == 1) dprintf(idx, "%s\n", SLGRDTITLE); else if (today == 2) dprintf(idx, "%s\n", SLGRWTITLE); else if (today == 3) dprintf(idx, "%s\n", SLGRMTITLE); dprintf(idx, "%s\n%s\n", SLCSS, SLBODYTAG); long_dprintf(idx, SLHEADER); if (today == 0) dprintf(idx, "%s", SLGRTHEAD); else if (today == 1) dprintf(idx, "%s", SLGRDHEAD); else if (today == 2) dprintf(idx, "%s", SLGRWHEAD); else if (today == 3) dprintf(idx, "%s", SLGRMHEAD); sprintf(what, "%s", graphstats); pwhat = what; while (strlen(pwhat) > 0) { type = newsplit(&pwhat); itype = typetoi(type); if (itype < 0) { putlog(LOG_MISC, "*", "Stats.mod: Error serving livestats. Unsupported type %s. Skipping.", type); continue; } sortstats(gs, itype, today); max = 0; for (ls = gs->slocal[today][itype]; ls; ls = ls->snext[today][itype]) { if (listsuser(ls, channel)) { max = ls->values[today][itype]; break; } } if (max == 0) continue; total = gettotal(gs, itype, today); rest = total; dprintf(idx, "


"); dprintf(idx, SLGRORDEREDBY, getslangtype(type)); dprintf(idx, "
\n"); slglobint = total; dprintf(idx, SLGRTOTAL, getslangtype(type)); dprintf(idx, "
\n"); dprintf(idx, "\n"); if (!total || !max) continue; onep = (float) total / 100.0; nr = 0; for (ls = gs->slocal[today][itype]; ls; ls = ls->snext[today][itype]) { if (!listsuser(ls, channel)) continue; if (!ls->values[today][itype]) break; nr++; if (nr > graphnr) break; dprintf(idx, "\n"); percent = (float) ls->values[today][itype] / onep; wpercent = (float) ls->values[today][itype] / ((float) max / 100.0); width = (int) wpercent * 0.8; dprintf(idx, " \n", ls->user, ls->user); dprintf(idx, " \n"); dprintf(idx, "\n"); rest -= ls->values[today][itype]; } dprintf(idx, "\n"); percent = (float) rest / ((float) total / 100.0); wpercent = (float) rest / ((float) max / 100.0); width = (int) wpercent * 0.8; dprintf(idx, " \n", SLGROTHERS); dprintf(idx, " \n"); dprintf(idx, "
%s\n"); dprintf(idx, " \n"); dprintf(idx, " \n", width, graphcolor, bground); dprintf(idx, " \n", 100 - width, percent, ls->values[today][itype]); dprintf(idx, "
 %.2f%% [%d]
\n"); dprintf(idx, "
%s\n"); dprintf(idx, " \n"); dprintf(idx, " \n", width, graphcolor, bground); dprintf(idx, " \n", 100 - width, percent, rest); dprintf(idx, "
 %.2f%% [%d]
\n"); dprintf(idx, "
\n"); } dprintf(idx, "\n"); dprintf(idx, "


\n"); dprintf(idx, "\n"); dprintf(idx, "\n", SLGRTABLE); dprintf(idx, "\n"); dprintf(idx, "\n"); dprintf(idx, "
%s
\n"); dprintf(idx, "\n", SLTOTAL); dprintf(idx, "\n", SLDAILY); dprintf(idx, "\n", SLWEEKLY); dprintf(idx, "\n", SLMONTHLY); dprintf(idx, "
%s%s%s%s
\n"); dprintf(idx, "\n", SLMISCSTATS); dprintf(idx, "\n", ISLINK(show_userlist), ISTEXT(show_userlist, SLUSERS)); dprintf(idx, "\n", ISLINK(show_usersonchan), ISTEXT(show_usersonchan, SLONCHAN)); dprintf(idx, "\n", SLOTHERCHANS); dprintf(idx, "
%s<%sa href=\"../../../users/\">%s<%sa href=\"../../../onchan/\">%s%s
\n"); dprintf(idx, "
Created by " "Stats.mod " "v%s
\n", MODULE_VERSION); long_dprintf(idx, SLFOOTER); dprintf(idx, ""); return; } static void do_toptalkers(int idx, int today, globstats *gs, char *channel, char *buf) { char what2[512], *pwhat2, *type, *type2; locstats *ls; int itype, itype2, pitype, nr, i; int wert; float r, g, b; float r2, g2, b2; float rstep, gstep, bstep; quotestr *q; unsigned long x; Context; setslglobs(channel, gs->peak[today], countstatmembers(gs), gs->started); type = buf; itype = typetoi(type); if (itype == T_ERROR) { dprintf(idx, "Error! No such type %s", type); if (idx >= 0) stats_info_access(idx)->code = 404; return; } if (itype < 0) pitype = (itype * -1) + (TOTAL_TYPES - 1); else pitype = itype; dprintf(idx, "\n"); if (today == 0) dprintf(idx, "%s\n", SLTTOPTITLE); else if (today == 1) dprintf(idx, "%s\n", SLDTOPTITLE); else if (today == 2) dprintf(idx, "%s\n", SLWTOPTITLE); else if (today == 3) dprintf(idx, "%s\n", SLMTOPTITLE); dprintf(idx, "\n", MODULE_VERSION); dprintf(idx, "\n", gs->chan); dprintf(idx, "\n", network); dprintf(idx, "\n", now); dprintf(idx, "%s\n\n", SLCSS); dprintf(idx, "%s", SLBODYTAG); long_dprintf(idx, SLHEADER); if (today == 0) dprintf(idx, "%s\n", SLTTOPHEAD); else if (today == 1) dprintf(idx, "%s\n", SLDTOPHEAD); else if (today == 2) dprintf(idx, "%s\n", SLWTOPHEAD); else if (today == 3) dprintf(idx, "%s\n", SLMTOPHEAD); dprintf(idx, SLORDEREDBY, getslangtype(type)); dprintf(idx, "
\n"); dprintf(idx, SLPEAK); dprintf(idx, "
\n"); dprintf(idx, "

", table_border); dprintf(idx, "", SLTNR); dprintf(idx, ""); sprintf(what2, "%s", webstats); pwhat2 = what2; while (strlen(pwhat2) > 0) { type2 = newsplit(&pwhat2); dprintf(idx, "\n", type2, getslangtype(type2)); } sortstats(gs, itype, today); nr = 0; wert = table_color; b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16; wert = fade_table_to; b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16; rstep = (r2 - r) / webnr; gstep = (g2 - g) / webnr; bstep = (b2 - b) / webnr; for (ls = gs->slocal[today][pitype]; ls; ls = ls->snext[today][pitype]) { if (!listsuser(ls, channel)) continue; if ((itype >= 0) && !ls->values[today][itype]) break; nr++; if (nr > webnr) break; dprintf(idx, "", (int) r, (int) g, (int) b, nr, ls->user, ls->user); r += rstep; g += gstep; b += bstep; sprintf(what2, "%s", webstats); pwhat2 = what2; while (strlen(pwhat2) > 0) { type2 = newsplit(&pwhat2); itype2 = typetoi(type2); dprintf(idx, ""); } dprintf(idx, "\n"); } dprintf(idx, ""); dprintf(idx, "\n"); dprintf(idx, "\n"); dprintf(idx, "\n"); dprintf(idx, "
%sNick%s
%d%s"); // mark the sorted value bold if (itype == itype2) dprintf(idx, ""); // now output the values // T_MINUTES gets a special handling, because it's kinda hard to read // something like "2348 Minutes" *g* if (itype2 == T_MINUTES) dprintf(idx, "%s", stats_duration(ls->values[today][itype2] * 60)); // no positive type needs any special handling, so lt's just output it else if (itype2 >= 0) dprintf(idx, "%d", ls->values[today][itype2]); // words per line need to be calculated else if (itype2 == T_WPL) { if (ls->values[today][T_LINES]) dprintf(idx, "%.2f", ((float) ls->values[today][T_WORDS]) / ((float) ls->values[today][T_LINES])); else dprintf(idx, "0"); // idle-factor also needs to be calculated } else if (itype2 == T_IDLE) { if (ls->values[today][T_LINES]) dprintf(idx, "%.2f", ((float) ls->values[today][T_MINUTES]) / ((float) ls->values[today][T_LINES])); else dprintf(idx, "0"); } else if (itype2 == T_QUOTE) { if (!ls->quotes) dprintf(idx, " "); else { nr = 0; for (q = ls->quotes; q; q = q->next) nr++; x = random() % nr; i = 0; q = ls->quotes; while (q) { if (i == x) { dprintf(idx, "%s", filt2(q->quote)); break; } q = q->next; i++; } } } else // output an error, if we missed something dprintf(idx, "ERROR! itype2: %d", itype2); if (itype == itype2) dprintf(idx, ""); dprintf(idx, "
", countwords(webstats) + 2); dprintf(idx, SLTOTALUSERS); dprintf(idx, "
", countwords(webstats) + 2); dprintf(idx, "\n"); dprintf(idx, "\n", SLGRAPHS); dprintf(idx, "\n", type, SLTOTAL); dprintf(idx, "\n", type, SLDAILY); dprintf(idx, "\n", type, SLWEEKLY); dprintf(idx, "\n", type, SLMONTHLY); dprintf(idx, "
%s
%s%s%s%s
\n", countwords(webstats) + 2); dprintf(idx, "\n", SLMISCSTATS); dprintf(idx, "\n", ISLINK(show_userlist), ISTEXT(show_userlist, SLUSERS)); dprintf(idx, "\n", ISLINK(show_usersonchan), ISTEXT(show_usersonchan, SLONCHAN)); dprintf(idx, "\n", SLOTHERCHANS); dprintf(idx, "\n
%s<%sa href=\"../../../users/\">%s<%sa href=\"../../../onchan/\">%s%s

"); if (!today) dprintf(idx, SLGSTARTED); dprintf(idx, "
Stats.mod v%s.", MODULE_VERSION); dprintf(idx, "
\n"); long_dprintf(idx, SLFOOTER); dprintf(idx, ""); return; } static void do_miscstats(int idx, char *channel) { globstats *gs, *tlds, *isps; wordstats *ws; int nr, tr, i, wert, wieoft, pitype; locstats *ls; char *host, *s; topicstr *t; char ts[20]; float f, max, onep; hoststr *h, *isp, *tld; struct slang_lang *l; struct slang_bntypes *ty; struct slang_bnplaces *p; struct slang_texts *txt; unsigned long x; float r, g, b; float r2, g2, b2; float rstep, gstep, bstep; struct stats_url *url; struct stats_kick *kick; struct stats_quote *log; Context; gs = findglobstats(channel); if (!gs) { dprintf(idx, "ERROR! Can't find stats for %s!\n", channel); return; } setslglobs(gs->chan, gs->peak[S_TOTAL], countstatmembers(gs), gs->started); dprintf(idx, "" "%s\n", SLMISCTITLE); long_dprintf(idx, SLCSS); dprintf(idx, "\n"); dprintf(idx, "%s\n", SLBODYTAG); long_dprintf(idx, SLHEADER); dprintf(idx, "%s
\n", SLMISCHEAD); do_globwordstats(gs); max = 0.0; wert = nr = 0; /* I'm recycling these vars, so ignore the strange names */ for (i = 0; i < 24; i++) { if (i < 12) { if (gs->users[S_USERCOUNTS][i] > 0) wert = 1; } else { if (gs->users[S_USERCOUNTS][i] > 0) nr = 1; } if (gs->users[S_USERCOUNTS][i] > 0) if ((((float) gs->users[S_USERSUM][i]) / ((float) gs->users[S_USERCOUNTS][i])) > max) max = ((float) gs->users[S_USERSUM][i]) / ((float) gs->users[S_USERCOUNTS][i]); } if (display_average_users && (max > 0.0)) { dprintf(idx, "%s
\n", SLMAUSERS); if (wert && nr) dprintf(idx, "", f); dprintf(idx, "\n"); } } dprintf(idx, "
\n"); else dprintf(idx, "", f); else dprintf(idx, "
\n"); dprintf(idx, "", table_border); onep = max / 100.0; for (i = 0; i < 24; i++) { if ((i == 12) && (wert && nr)) dprintf(idx, "
", table_border); if (gs->users[S_USERCOUNTS][i] > 0) { f = ((float) gs->users[S_USERSUM][i]) / ((float) gs->users[S_USERCOUNTS][i]); dprintf(idx, "", (int) (f / onep), graphcolor, f); else if ((f / onep) > 0.0) dprintf(idx, "
%d.00-%d.59", i, i); if (((int) (f / onep)) > 0) dprintf(idx, "
 %.2f
%.2f
%.2f
"); dprintf(idx, ""); dprintf(idx, "
\n"); } if (gs->topics) { dprintf(idx, "

%s
\n", SLMTOPICS, table_border); i = 0; for (t = gs->topics; t; t = t->next) i++; wert = table_color; b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16; wert = fade_table_to; b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16; rstep = (r2 - r) / i; gstep = (g2 - g) / i; bstep = (b2 - b) / i; for (t = gs->topics; t; t = t->next) { strftime(ts, 20, "%H:%M", localtime(&t->when)); setslnick(t->by); dprintf(idx, "\n"); r += rstep; g += gstep; b += bstep; } dprintf(idx, "
\"%s\"", (int) r, (int) g, (int) b, filt2(t->topic)); dprintf(idx, SLMTOPICBY, ts); dprintf(idx, "


\n"); } if (gs->urls && log_urls) { nr = 0; for (url = gs->urls; url; url = url->next) { nr++; url->shown = 0; } if (nr > log_urls) wieoft = log_urls; else wieoft = nr; slglobint = wieoft; dprintf(idx, "

", table_border, SLMURLS); wert = table_color; b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16; wert = fade_table_to; b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16; rstep = (r2 - r) / wieoft; gstep = (g2 - g) / wieoft; bstep = (b2 - b) / wieoft; while (wieoft > 0) { x = random() % nr; i = 0; url = gs->urls; while (url) { if (url->shown) { url = url->next; continue; } if (i == x) { dprintf(idx, "\n"); url->shown = 1; nr--; r += rstep; g += gstep; b += bstep; break; } url = url->next; i++; } wieoft--; } dprintf(idx, "
%s
\"%s\"", (int) r, (int) g, (int) b, url->url, url->url); strftime(ts, 20, "%H:%M", localtime(&url->when)); setslnick(url->by); dprintf(idx, SLMURLBY, ts); dprintf(idx, "
\n"); } if (gs->hosts) { tlds = nmalloc(sizeof(globstats)); tlds->hosts = NULL; isps = nmalloc(sizeof(globstats)); isps->hosts = NULL; for (h = gs->hosts; h; h = h->next) { // skip IPv6 hosts if (strchr(h->host, ':')) continue; host = strrchr(h->host, '.') + 1; if (!atoi(host) && (host[0] != '0')) { addhost(host, tlds); host = h->host; while ((s = strchr(host, '.')) && strchr(s + 1, '.')) host = s + 1; addhost(host, isps); } else { addhost("[IP]", tlds); addhost("[IP]", isps); } } sorthosts(isps); sorthosts(tlds); dprintf(idx, "

\n", table_border, SLMMOSTUSED, SLMISPS, SLMTLDS); i = 0; isp = isps->hosts; tld = tlds->hosts; wert = table_color; b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16; wert = fade_table_to; b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16; rstep = (r2 - r) / 5; gstep = (g2 - g) / 5; bstep = (b2 - b) / 5; while ((i <= 5) && (isp || tld)) { i++; dprintf(idx, "\n", (int) r, (int) g, (int) b); r += rstep; g += gstep; b += bstep; if (isp) dprintf(idx, "", isp->host, isp->nr); else dprintf(idx, ""); if (tld) dprintf(idx, "", tld->host, tld->nr); else dprintf(idx, ""); dprintf(idx, "\n"); if (isp) isp = isp->next; if (tld) tld = tld->next; } dprintf(idx, "
%s
%s%s
%s (%d)-%s (%d)-
\n"); free_hosts(isps->hosts); free_hosts(tlds->hosts); nfree(isps); nfree(tlds); } if (gs->kicks && (display_kicks > 0)) { nr = 0; for (kick = gs->kicks; kick; kick = kick->next) { nr++; kick->shown = 0; } if (nr > display_kicks) wieoft = display_kicks; else wieoft = nr; slglobint = wieoft; dprintf(idx, "

", table_border, SLMKICKS); wert = table_color; b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16; wert = fade_table_to; b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16; rstep = (r2 - r) / wieoft; gstep = (g2 - g) / wieoft; bstep = (b2 - b) / wieoft; while (wieoft > 0) { x = random() % nr; i = 0; kick = gs->kicks; while (kick) { if (kick->shown) { kick = kick->next; continue; } if (i == x) { dprintf(idx, "\n"); kick->shown = 1; nr--; r += rstep; g += gstep; b += bstep; break; } kick = kick->next; i++; } wieoft--; } dprintf(idx, "
%s
", (int) r, (int) g, (int) b); for (log = kick->log; log; log = log->next) { if (log->next) dprintf(idx, "%s
", filt2(log->quote)); else dprintf(idx, "
%s
", filt2(log->quote)); } dprintf(idx, "
\n"); } if (gs->words) { nr = 0; for (ws = gs->words; ws; ws = ws->next) nr++; dprintf(idx, "

"); dprintf(idx, SLMCWORDSTATS, nr); dprintf(idx, "
\n"); dprintf(idx, "%s
\n", SLMMOSTUSEDWORDS, table_border); wert = table_color; b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16; wert = fade_table_to; b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16; rstep = (r2 - r) / 10; gstep = (g2 - g) / 10; bstep = (b2 - b) / 10; ws = gs->words; nr = 0; while (ws && (nr < 10)) { nr++; dprintf(idx, "\n", (int) r, (int) g, (int) b, nr, filt2(ws->word), ws->nr); r += rstep; g += gstep; b += bstep; ws = ws->next; } dprintf(idx, "
%d.%s(%d)
\n"); } dprintf(idx, "

\n", table_border); for (l = slangs; l; l = l->next) { if ((!l->lang && !slgloblang) || (l->lang && slgloblang && !strcasecmp(l->lang, slgloblang))) { i = 0; for (ty = l->bignumbers; ty; ty = ty->next) i++; wert = table_color; b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16; wert = fade_table_to; b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16; rstep = (r2 - r) / i; gstep = (g2 - g) / i; bstep = (b2 - b) / i; for (ty = l->bignumbers; ty; ty = ty->next) { i = typetoi(ty->type); sortstats(gs, i, S_DAILY); tr = 0; for (p = ty->places; p; p = p->next) { nr = 1; if (i < 0) pitype = (i * -1) + (TOTAL_TYPES - 1); else pitype = i; ls = gs->slocal[S_DAILY][pitype]; while (ls && (nr < p->place)) { nr++; ls = ls->snext[S_DAILY][pitype]; } // just skip this entry if any vital information is missing. if (!ls) continue; else if ((i >= 0) && !ls->values[S_DAILY][i]) continue; else if ((i == T_WPL) && (!ls->values[S_DAILY][T_WORDS] || !ls->values[S_DAILY][T_LINES])) continue; else if ((i == T_IDLE) && (!ls->values[S_DAILY][T_MINUTES] || !ls->values[S_DAILY][T_LINES])) continue; else if ((i == T_VOCABLES) && !ls->vocables) continue; if (!tr) { dprintf(idx, "\n"); } } } dprintf(idx, "
\n", (int) r, (int) g, (int) b); r += rstep; g += gstep; b += bstep; tr = 1; } slgloblocstats = ls; slglobtype = ty->type; x = random() % p->entries; txt = p->texts; while (txt) { if (!x) dprintf(idx, "%s\n", dynamicslang(txt->text)); x--; txt = txt->next; } } if (tr) dprintf(idx, "
\n"); dprintf(idx, "


\n"); dprintf(idx, "\n"); dprintf(idx, "\n"); dprintf(idx, "
\n"); dprintf(idx, "\n", webnr); dprintf(idx, "\n", ISLINK(show_userlist), ISTEXT(show_userlist, SLUSERS)); dprintf(idx, "\n", ISLINK(show_usersonchan), ISTEXT(show_usersonchan, SLONCHAN)); dprintf(idx, "\n", SLOTHERCHANS); dprintf(idx, "
top%d<%sa href=\"../users/\">%s<%sa href=\"../onchan/\">%s%s
\n"); dprintf(idx, "
Created by Stats.mod v%s
", MODULE_VERSION); long_dprintf(idx, SLFOOTER); dprintf(idx, ""); } static void display_users_on_chan(int idx, char *channel, struct chanset_t *chan) { memberlist *m; struct stats_memberlist *mm; int wert; float r, g, b; float r2, g2, b2; float rstep, gstep, bstep; int i; char s1[121]; Context; dprintf(idx, "%s\n%s\n\n", SLUSERSONCHANTITLE, SLCSS); dprintf(idx, "%s\n", SLBODYTAG); long_dprintf(idx, SLHEADER); if (show_usersonchan && chan && (chan->channel.members > 0)) { dprintf(idx, "

\n\n", table_border, SLNOWONCHAN); dprintf(idx, "\n", SLIDLETIME); i = 0; for (m = chan->channel.member; m && m->nick[0]; m = m->next) i++; wert = table_color; b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16; wert = fade_table_to; b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16; rstep = (r2 - r) / i; gstep = (g2 - g) / i; bstep = (b2 - b) / i; for (m = chan->channel.member; m && m->nick[0]; m = m->next) { dprintf(idx, "", (int) r, (int) g, (int) b); dprintf(idx, "", chan_hasop(m) ? "@" : (chan_hasvoice(m) ? "+" : " "), m->nick); r += rstep; g += gstep; b += bstep; if (!m->user && ((strlen(m->nick) + strlen(m->userhost) + 1) < 120)) { sprintf(s1, "%s!%s", m->nick, m->userhost); m->user = get_user_by_host(s1); } if (!use_userfile) { mm = nick2suser(m->nick, channel); if (mm && mm->user) dprintf(idx, "", mm->user->user, mm->user->user); else dprintf(idx, ""); } else { if (m->user) dprintf(idx, "", m->user->handle, m->user->handle); else dprintf(idx, ""); } if (chan_issplit(m)) dprintf(idx, "", SLNETSPLITTED); else if (!rfc_casecmp(m->nick, botname)) dprintf(idx, "", SLITSME); else dprintf(idx, "", stats_duration(now - m->last)); dprintf(idx, "\n"); } dprintf(idx, "
%s
nickuser%s
%s%s%s-%s-%s%s %s
\n

"); } dprintf(idx, "\n"); dprintf(idx, "\n"); dprintf(idx, "
\n"); dprintf(idx, "\n", webnr); dprintf(idx, "\n", ISLINK(show_userlist), ISTEXT(show_userlist, SLUSERS)); dprintf(idx, "\n", SLMISCSTATS); dprintf(idx, "\n", SLOTHERCHANS); dprintf(idx, "
top%d<%sa href=\"../users/\">%s%s%s
\n"); dprintf(idx, "
Created by Stats.mod v%s
", MODULE_VERSION); long_dprintf(idx, SLFOOTER); dprintf(idx, ""); }