4
0

livestats.c 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558
  1. /*
  2. * Copyright (C) 2000,2001 Florian Sander
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; either version 2
  7. * of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. static struct dcc_table LIVESTATS_LISTEN =
  19. {
  20. "LIVESTATS_LISTEN",
  21. DCT_VALIDIDX,
  22. eof_livestats,
  23. livestats_accept,
  24. 0,
  25. timeout_listen_livestats,
  26. display_livestats_accept,
  27. 0,
  28. NULL,
  29. 0
  30. };
  31. static struct dcc_table LIVESTATS =
  32. {
  33. "LIVESTATS",
  34. DCT_VALIDIDX,
  35. eof_livestats,
  36. livestats_activity,
  37. &livestats_timeout,
  38. timeout_livestats,
  39. display_livestats,
  40. expmem_livestats,
  41. kill_livestats,
  42. #ifdef OLDBOT
  43. out_livestats,
  44. #else
  45. out_livestats,
  46. outdone_livestats
  47. #endif
  48. };
  49. static int inactivechan(char *chan)
  50. {
  51. struct chanset_t *ch;
  52. ch = findchan_by_dname(chan);
  53. if (!ch)
  54. return 1;
  55. if (ch->status & CHAN_INACTIVE)
  56. return 1;
  57. return 0;
  58. }
  59. static int nostats(char *chan)
  60. {
  61. #if EGG_IS_MIN_VER(10503)
  62. if (ngetudef("nostats", chan))
  63. return 1;
  64. #endif
  65. return 0;
  66. }
  67. static void start_listen_livestats(int port)
  68. {
  69. int i, zz;
  70. char tmp[50];
  71. stop_listen_livestats();
  72. sprintf(tmp, "set my-ip \"%s\";", livestats_ip);
  73. do_tcl("livestats-hack-start",
  74. "set my-ip-livestats-backup ${my-ip};"
  75. "set my-hostname-livestats-backup ${my-hostname};"
  76. "set my-hostname \"\"");
  77. do_tcl("livestats-hack-setip", tmp);
  78. zz = open_listen(&port);
  79. do_tcl("livestats-hack-end",
  80. "set my-ip ${my-ip-livestats-backup};"
  81. "set my-hostname ${my-hostname-livestats-backup}");
  82. if (zz == (-1)) {
  83. putlog(LOG_MISC, "*", "ERROR! Cannot open listening socket for livestats!");
  84. return;
  85. }
  86. if ((i = new_dcc(&LIVESTATS_LISTEN, 0)) == -1) {
  87. putlog(LOG_MISC, "*", "ERROR! Cannot open listening socket for livestats! DCC table is full!");
  88. return;
  89. }
  90. dcc[i].sock = zz;
  91. dcc[i].addr = (IP) (-559026163);
  92. dcc[i].port = port;
  93. strcpy(dcc[i].nick, "livestats");
  94. strcpy(dcc[i].host, "*");
  95. dcc[i].timeval = now;
  96. putlog(LOG_MISC, "*", "Now listening for livestats connections on port %d", port);
  97. }
  98. static void stop_listen_livestats()
  99. {
  100. int i;
  101. for (i = 0; i < dcc_total; i++) {
  102. if (dcc[i].type == &LIVESTATS_LISTEN) {
  103. putlog(LOG_MISC, "*",
  104. "no longer listening for livestats connections on port %d",
  105. dcc[i].port);
  106. killsock(dcc[i].sock);
  107. lostdcc(i);
  108. } else if (dcc[i].type == &LIVESTATS) {
  109. putlog(LOG_MISC, "*", "killing livestats connection from %s", dcc[i].host);
  110. killsock(dcc[i].sock);
  111. lostdcc(i);
  112. }
  113. }
  114. }
  115. static void livestats_activity(int idx, char *buf, int len)
  116. {
  117. char *cmd, *path, *newpath, *imask;
  118. int lev;
  119. imask = nmalloc(strlen(dcc[idx].host) + 13);
  120. sprintf(imask, "livestats!*@%s", dcc[idx].host);
  121. if (match_ignore(imask)) {
  122. debug1("Ignoring livestats access from %s", dcc[idx].host);
  123. stats_info_access(idx)->code = 401;
  124. if (livestats_ignore_msg[0])
  125. dprintf(idx, "HTTP/1.0 401 Access Forbidden\nContent-Type: text/html\n\n%s", livestats_ignore_msg);
  126. killsock(dcc[idx].sock);
  127. lostdcc(idx);
  128. nfree(imask);
  129. return;
  130. }
  131. nfree(imask);
  132. if (!strncasecmp(buf, "GET ", 4)) {
  133. if (!stats_info_access(idx)->cmd) {
  134. stats_info_access(idx)->cmd = nmalloc(strlen(buf) + 1);
  135. strcpy(stats_info_access(idx)->cmd, buf);
  136. stats_info_access(idx)->code = 200;
  137. }
  138. }
  139. cmd = newsplit(&buf);
  140. if (!strcmp(cmd, "GET")) {
  141. if (livestats_flood()) {
  142. stats_info_access(idx)->code = 401;
  143. killsock(dcc[idx].sock);
  144. lostdcc(idx);
  145. return;
  146. }
  147. lev = logmodes(stats_loglevel);
  148. if (lev)
  149. putlog(lev, "*", "%s: GET %s", dcc[idx].host, buf);
  150. path = newsplit(&buf);
  151. if (!strncasecmp(path, "/robots.txt", 11)) {
  152. dprintf(idx, "HTTP/1.1 404 Not Found\nServer: stats.mod/%s\nConnection: close", MODULE_VERSION);
  153. dprintf(idx, "Content-Type: text/html; charset=iso-8859-1\n\n");
  154. dprintf(idx, "<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD><BODY><H1>Not Found</H1>");
  155. dprintf(idx, "The requested document was not found on this server.</BODY></HTML>");
  156. stats_info_access(idx)->code = 404;
  157. return;
  158. }
  159. if (path[strlen(path) - 1] != '/') {
  160. newpath = nmalloc(strlen(path) + 2);
  161. strcpy(newpath, path);
  162. newpath[strlen(path)] = '/';
  163. newpath[strlen(path) + 1] = 0;
  164. dprintf(idx, "HTTP/1.1 301 Moved Permanently\nServer: stats.mod/%s\n", MODULE_VERSION);
  165. dprintf(idx, "Location: %s\nConnection: close\nContent-Type: text/html\n\n", newpath);
  166. dprintf(idx, "<HTML><body>The concluding \"/\" is important!<br><center>");
  167. dprintf(idx, "<a href=\"%s\">%s</a></center><br>", newpath, newpath);
  168. stats_info_access(idx)->code = 301;
  169. nfree(newpath);
  170. return;
  171. }
  172. dprintf(idx, "HTTP/1.0 200 OK\nServer: stats.mod/%s\nContent-Type: text/html\n\n", MODULE_VERSION);
  173. send_livestats(idx, path);
  174. } else if (!strcasecmp(cmd, "User-Agent:")) {
  175. if (stats_info_access(idx)->browser)
  176. return;
  177. stats_info_access(idx)->browser = nmalloc(strlen(buf) + 1);
  178. strcpy(stats_info_access(idx)->browser, buf);
  179. } else if (!strcasecmp(cmd, "Referer:")) {
  180. if (stats_info_access(idx)->referer)
  181. return;
  182. stats_info_access(idx)->referer = nmalloc(strlen(buf) + 1);
  183. strcpy(stats_info_access(idx)->referer, buf);
  184. } else if (!buf[0]) {
  185. dcc[idx].status = 1;
  186. #ifndef OLDBOT
  187. /* If there's no data in our socket, we immediately get rid of it.
  188. */
  189. if (!sock_has_data(SOCK_DATA_OUTGOING, dcc[idx].sock)) {
  190. killsock(dcc[idx].sock);
  191. lostdcc(idx);
  192. }
  193. #endif
  194. }
  195. }
  196. #ifndef OLDBOT
  197. static void outdone_livestats(int idx)
  198. {
  199. if (dcc[idx].status) {
  200. killsock(dcc[idx].sock);
  201. lostdcc(idx);
  202. } else
  203. dcc[idx].status = 1;
  204. }
  205. #endif
  206. static void display_livestats(int idx, char *buf)
  207. {
  208. sprintf(buf, "livestats");
  209. }
  210. static void display_livestats_accept(int idx, char *buf)
  211. {
  212. sprintf(buf, "lstn port");
  213. }
  214. static void timeout_livestats(int idx)
  215. {
  216. killsock(dcc[idx].sock);
  217. lostdcc(idx);
  218. }
  219. static void timeout_listen_livestats(int idx)
  220. {
  221. debug0("timeout listen");
  222. killsock(dcc[idx].sock);
  223. lostdcc(idx);
  224. }
  225. static void kill_livestats(int idx, void *x)
  226. {
  227. register struct stats_clientinfo *p = (struct stats_clientinfo *) x;
  228. char ts[41], test[11];
  229. time_t tt;
  230. FILE *f;
  231. Context;
  232. tt = now;
  233. if (!p) {
  234. putlog(LOG_MISC, "*", "Can't kill clientinfo, no pointer. This should not happen!");
  235. return;
  236. }
  237. ctime(&tt);
  238. /* 05/Feb/2000:12:08:17 +0100 */
  239. strftime(test, 19, "%z", localtime(&tt));
  240. if (test[0] != 'z')
  241. strftime(ts, 40, "%d/%b/%Y:%H:%M:%S %z", localtime(&tt));
  242. else
  243. strftime(ts, 40, "%d/%b/%Y:%H:%M:%S", localtime(&tt));
  244. if (livestats_log[0]) {
  245. f = fopen(livestats_log, "a");
  246. if (f == NULL)
  247. putlog(LOG_MISC, "*", "ERROR writing livestats log.");
  248. else {
  249. if (test[0] != 'z')
  250. fprintf(f,
  251. "%s - - [%s] \"%s\" %d %d \"%s\" \"%s\"\n", dcc[idx].host, ts,
  252. p->cmd ? p->cmd : "", p->code, p->traffic,
  253. p->referer ? p->referer : "-", p->browser ? p->browser : "");
  254. else
  255. fprintf(f,
  256. "%s - - [%s %+05d] \"%s\" %d %d \"%s\" \"%s\"\n", dcc[idx].host,
  257. ts, offset * (-1) * 100, p->cmd ? p->cmd : "", p->code ,p->traffic,
  258. p->referer ? p->referer : "-", p->browser ? p->browser : "");
  259. fclose(f);
  260. }
  261. }
  262. if (p->browser)
  263. nfree(p->browser);
  264. if (p->referer)
  265. nfree(p->referer);
  266. if (p->cmd)
  267. nfree(p->cmd);
  268. nfree(p);
  269. }
  270. static int expmem_livestats(void *x)
  271. {
  272. register struct stats_clientinfo *p = (struct stats_clientinfo *) x;
  273. int tot = sizeof(struct stats_clientinfo);
  274. Context;
  275. if (!p) {
  276. putlog(LOG_MISC, "*", "Can't expmem clientinfo, no pointer. This should not happen!");
  277. return 0;
  278. }
  279. if (p->browser)
  280. tot += strlen(p->browser) + 1;
  281. if (p->referer)
  282. tot += strlen(p->referer) + 1;
  283. if (p->cmd)
  284. tot += strlen(p->cmd) + 1;
  285. return tot;
  286. }
  287. static void out_livestats(int idx, char *buf, void *x)
  288. {
  289. register struct stats_clientinfo *p = (struct stats_clientinfo *) x;
  290. if (!p) {
  291. putlog(LOG_MISC, "*", "No stats_clientinfo pointer. This should not happen!");
  292. return;
  293. }
  294. p->traffic += strlen(buf);
  295. tputs(dcc[idx].sock, buf, strlen(buf));
  296. }
  297. static void livestats_accept(int idx, char *buf, int len)
  298. {
  299. unsigned long ip;
  300. unsigned short port;
  301. int j = 0, sock, i;
  302. char s[UHOSTLEN];
  303. Context;
  304. if (dcc_total + 1 >= max_dcc) {
  305. j = answer(dcc[idx].sock, s, &ip, &port, 0);
  306. if (j != -1) {
  307. dprintf(-j, "Sorry, too many connections already.\r\n");
  308. killsock(j);
  309. }
  310. return;
  311. }
  312. sock = answer(dcc[idx].sock, s, &ip, &port, 0);
  313. if (sock < 0) {
  314. neterror(s);
  315. putlog(LOG_MISC, "*", "Stats.mod: Error accepting livestats connection: %s", s);
  316. return;
  317. }
  318. if ((i = new_dcc(&LIVESTATS, sizeof(struct stats_clientinfo))) == (-1)) {
  319. putlog(LOG_MISC, "*", "Error accepting livestats connection. DCC table is full.");
  320. killsock(sock);
  321. return;
  322. }
  323. dcc[i].sock = sock;
  324. dcc[i].addr = ip;
  325. dcc[i].port = port;
  326. strcpy(dcc[i].nick, "httpstats");
  327. #ifndef OLDBOT
  328. sprintf(s, "%s", iptostr(my_htonl(ip)));
  329. #else
  330. sprintf(s, "%lu.%lu.%lu.%lu", (ip >> 24) & 0xff, (ip >> 16) & 0xff,
  331. (ip >> 8) & 0xff, ip & 0xff); /* dw */
  332. #endif
  333. strcpy(dcc[i].host, s);
  334. dcc[i].timeval = now;
  335. dcc[i].status = 0;
  336. ((struct stats_clientinfo *) dcc[i].u.other)->traffic = 0;
  337. ((struct stats_clientinfo *) dcc[i].u.other)->code = 200;
  338. ((struct stats_clientinfo *) dcc[i].u.other)->browser = NULL;
  339. ((struct stats_clientinfo *) dcc[i].u.other)->referer = NULL;
  340. ((struct stats_clientinfo *) dcc[i].u.other)->cmd = NULL;
  341. }
  342. static int mlstat_time = 0, mlstat_thr = 0;
  343. static int livestats_flood()
  344. {
  345. if (!maxlivestats_thr || !maxlivestats_time)
  346. return 0;
  347. if ((now - mlstat_time) > maxlivestats_time) {
  348. mlstat_time = now;
  349. mlstat_thr = 0;
  350. }
  351. mlstat_thr++;
  352. if (mlstat_thr > maxlivestats_thr)
  353. return 1;
  354. return 0;
  355. }
  356. static void eof_livestats(int idx)
  357. {
  358. debug0("eof accept");
  359. killsock(dcc[idx].sock);
  360. lostdcc(idx);
  361. }
  362. static void send_livestats(int idx, char *buf)
  363. {
  364. char *channel, *command;
  365. char what[512], *pwhat, *type, *stoday, *user, prefix[4];
  366. struct chanset_t *chan;
  367. int today = 0;
  368. globstats *gs;
  369. locstats *ls, *ls2;
  370. time_t tt, ttbuf;
  371. struct userrec *u;
  372. int itype, nr, i, ii;
  373. wordstats *ws;
  374. quotestr *qs;
  375. unsigned long x;
  376. int wert;
  377. float r, g, b;
  378. float r2, g2, b2;
  379. float rstep, gstep, bstep;
  380. struct stats_userlist *suser;
  381. ttbuf = now;
  382. tt = now;
  383. if (!strcmp(buf, "/")) {
  384. setslglobs(NULL, 0, 0, 0);
  385. dprintf(idx, "<html><head><title>%s</title>\n%s\n</head>\n", ROOTTITLE, SLCSS);
  386. dprintf(idx, "%s\n", SLBODYTAG);
  387. long_dprintf(idx, SLHEADER);
  388. dprintf(idx, "<br><br><br><table border=1 width=100%%>\n");
  389. for (gs = sdata; gs; gs = gs->next) {
  390. if (!inactivechan(gs->chan) && !secretchan(gs->chan) && !nostats(gs->chan)) {
  391. if (gs->chan[0] == '!')
  392. strcpy(prefix, "!");
  393. else if (gs->chan[0] == '+')
  394. strcpy(prefix, "+");
  395. else if (gs->chan[0] == '&')
  396. strcpy(prefix, "&");
  397. else
  398. prefix[0] = 0;
  399. #ifndef OLDBOT
  400. chan = findchan_by_dname(gs->chan);
  401. #else
  402. chan = findchan(gs->chan);
  403. #endif
  404. i = 7;
  405. if (!show_userlist)
  406. i--;
  407. if (!show_usersonchan)
  408. i--;
  409. dprintf(idx, "<tr><td rowspan=%d align=center width=50%%>", i);
  410. if (chan && chan->channel.topic)
  411. dprintf(idx, "<a href=\"%s%s/\">%s</a><br><font size=-1>(%s)</font></td>",
  412. prefix, gs->chan + 1, gs->chan, filt2(chan->channel.topic));
  413. else
  414. dprintf(idx, "<a href=\"%s%s/\">%s</a></td>",
  415. prefix, gs->chan + 1, gs->chan);
  416. dprintf(idx, "<td rowspan=4 align=center>%s</td>", SLTOP);
  417. setslglobs(gs->chan, gs->peak[S_TOTAL], countstatmembers(gs), gs->started);
  418. dprintf(idx, "<td align=center><a href=\"%s%s/top/total/words/\">%s</a></td>",
  419. prefix, gs->chan + 1, SLTOTAL);
  420. dprintf(idx, "</tr>\n<tr>");
  421. dprintf(idx, "<td align=center><a href=\"%s%s/top/daily/words/\">%s</a></td>",
  422. prefix, gs->chan + 1, SLDAILY);
  423. dprintf(idx, "</tr>\n<tr>");
  424. dprintf(idx, "<td align=center><a href=\"%s%s/top/weekly/words/\">%s</a></td>",
  425. prefix, gs->chan + 1, SLWEEKLY);
  426. dprintf(idx, "</tr>\n<tr>");
  427. dprintf(idx, "<td align=center><a href=\"%s%s/top/monthly/words/\">%s</a></td>",
  428. prefix, gs->chan + 1, SLMONTHLY);
  429. dprintf(idx, "</tr>\n");
  430. if (show_userlist)
  431. dprintf(idx, "<tr><td align=center colspan=2><a href=\"%s%s/users/\">%s</a></td></tr>",
  432. prefix, gs->chan + 1, SLUSERS);
  433. if (show_usersonchan)
  434. dprintf(idx, "<tr><td align=center colspan=2><a href=\"%s%s/onchan/\">%s</a></td></tr>",
  435. prefix, gs->chan + 1, SLONCHAN);
  436. dprintf(idx, "<tr><td align=center colspan=2><a href=\"%s%s/misc/\">%s</a></td>",
  437. prefix, gs->chan + 1, SLMISCSTATS);
  438. dprintf(idx, "</tr><tr><td colspan=3 height=0><font size=-5>&nbsp;</font></td></tr>\n");
  439. }
  440. }
  441. dprintf(idx, "<tr><th colspan=3 align=center>");
  442. dprintf(idx, "<a href=\"http://www.visions-of-fantasy.de/stats.mod/\">");
  443. dprintf(idx, "Stats.mod v%s</a></th></tr></table>\n", MODULE_VERSION);
  444. long_dprintf(idx, SLFOOTER);
  445. dprintf(idx, "</body></html>\n");
  446. return;
  447. }
  448. if (buf[0] == '/') {
  449. if (!strncasecmp(buf, "/e/", 3)) {
  450. buf += 2;
  451. buf[0] = '!';
  452. } else if (!strncasecmp(buf, "/p/", 3)) {
  453. buf += 2;
  454. buf[0] = '+';
  455. } else if (!strncasecmp(buf, "/a/", 3)) {
  456. buf += 2;
  457. buf[0] = '&';
  458. } else if (buf[1] && strchr("+&!", buf[1]))
  459. buf++;
  460. else
  461. buf[0] = '#';
  462. }
  463. if (buf[strlen(buf) - 1] == '/')
  464. buf[strlen(buf) - 1] = 0;
  465. channel = splitpath(&buf);
  466. #ifndef OLDBOT
  467. chan = findchan_by_dname(channel);
  468. #else
  469. chan = findchan(channel);
  470. #endif
  471. if (!chan) {
  472. dprintf(idx, "no such channel %s", channel);
  473. if (idx >= 0)
  474. stats_info_access(idx)->code = 404;
  475. return;
  476. }
  477. gs = findglobstats(channel);
  478. if (gs)
  479. setslglobs(gs->chan, gs->peak[S_TOTAL], countstatmembers(gs), gs->started);
  480. else
  481. setslglobs(channel, 0, 0, 0);
  482. if (!strcmp(buf, "/") || !buf[0]) {
  483. dprintf(idx, "<html><head><title>%s</title>\n%s\n</head>%s", SLINDEXTITEL, SLCSS, SLBODYTAG);
  484. long_dprintf(idx, SLHEADER);
  485. dprintf(idx, "<br><br><br><center>\n");
  486. dprintf(idx, "<table border=1 width=50%%>\n");
  487. dprintf(idx, "<tr><th colspan=2><font size=+2>%s</font></th></tr>", channel);
  488. dprintf(idx, "<tr><td rowspan=4 align=center>%s</td>", SLTOP);
  489. dprintf(idx, "<td align=center><a href=\"top/total/words/\">%s</a></td>", SLTOTAL);
  490. dprintf(idx, "</tr>\n<tr>");
  491. dprintf(idx, "<td align=center><a href=\"top/daily/words/\">%s</a></td>", SLDAILY);
  492. dprintf(idx, "</tr>\n<tr>");
  493. dprintf(idx, "<td align=center><a href=\"top/weekly/words/\">%s</a></td>", SLWEEKLY);
  494. dprintf(idx, "</tr>\n<tr>");
  495. dprintf(idx, "<td align=center><a href=\"top/monthly/words/\">%s</a></td>", SLMONTHLY);
  496. dprintf(idx, "</tr>\n");
  497. if (show_userlist)
  498. dprintf(idx, "<tr><td align=center colspan=2><a href=\"users/\">%s</a></td></tr>", SLUSERS);
  499. if (show_usersonchan)
  500. dprintf(idx, "<tr><td align=center colspan=2><a href=\"onchan/\">%s</a></td></tr>", SLONCHAN);
  501. dprintf(idx, "<tr><td align=center colspan=2><a href=\"misc/\">%s</a></td></tr>", SLMISCSTATS);
  502. dprintf(idx, "<tr><td colspan=2 height=0><font size=-5>&nbsp;</font></td></tr>\n");
  503. dprintf(idx, "<tr><th colspan=2 align=center><font size=-2>");
  504. dprintf(idx, "<a href=\"http://www.visions-of-fantasy.de/stats.mod/\">");
  505. dprintf(idx, "Stats.mod v%s</a></font></th></tr></table>\n", MODULE_VERSION);
  506. dprintf(idx, "</center>\n");
  507. long_dprintf(idx, SLFOOTER);
  508. dprintf(idx, "</body></html>\n");
  509. return;
  510. }
  511. command = splitpath(&buf);
  512. if (!strcasecmp(command, "top")) {
  513. if (!strcmp(buf, "/") || !buf[0]) {
  514. dprintf(idx, "<html><body><table>");
  515. dprintf(idx, "<tr><td><a href=\"total/\">total</a></td></tr>");
  516. dprintf(idx, "<tr><td><a href=\"today/\">today</a></td></tr>");
  517. dprintf(idx, "</table></body></html>");
  518. return;
  519. }
  520. stoday = splitpath(&buf);
  521. if (!strcasecmp(stoday, "today") || !strcasecmp(stoday, "daily"))
  522. today = S_DAILY;
  523. else if (!strcasecmp(stoday, "weekly"))
  524. today = S_WEEKLY;
  525. else if (!strcasecmp(stoday, "monthly"))
  526. today = S_MONTHLY;
  527. else if (!strcasecmp(stoday, "total"))
  528. today = 0;
  529. else {
  530. dprintf(idx, "<html><body>Error, invalid value %s<table>", stoday);
  531. dprintf(idx, "<tr><td><a href=\"../total/\">total</a></td></tr>");
  532. dprintf(idx, "<tr><td><a href=\"../daily/\">daily</a></td></tr>");
  533. dprintf(idx, "<tr><td><a href=\"../weekly/\">weekly</a></td></tr>");
  534. dprintf(idx, "<tr><td><a href=\"../monthly/\">monthly</a></td></tr>");
  535. dprintf(idx, "</table></body></html>");
  536. Assert(idx >= 0);
  537. stats_info_access(idx)->code = 404;
  538. return;
  539. }
  540. if (!strcmp(buf, "/") || !buf[0]) {
  541. dprintf(idx, "<html><body><table>");
  542. sprintf(what, "%s", webstats);
  543. pwhat = what;
  544. while (strlen(pwhat) > 0) {
  545. type = newsplit(&pwhat);
  546. itype = typetoi(type);
  547. if (itype >= 0) {
  548. dprintf(idx, "<tr><td><a href=\"%s/\">%s</a></td></tr>", type, type);
  549. }
  550. }
  551. dprintf(idx, "</table></body></html>");
  552. return;
  553. }
  554. gs = findglobstats(channel);
  555. if (!gs) {
  556. debug1("Error! Can't find global stats for %s", channel);
  557. dprintf(idx, "<html><body>Error! Can't find global stats for %s</body></html>", channel);
  558. if (idx >= 0)
  559. stats_info_access(idx)->code = 404;
  560. return;
  561. }
  562. if (!strncasecmp(buf, "graph", 5)) {
  563. do_graphs(idx, today, gs, channel);
  564. return;
  565. }
  566. do_toptalkers(idx, today, gs, channel, buf);
  567. return;
  568. } else if (!strcasecmp(command, "onchan")) {
  569. display_users_on_chan(idx, channel, chan);
  570. } else if (!strcasecmp(command, "users")) {
  571. gs = findglobstats(channel);
  572. if (!gs) {
  573. debug1("Error! Can't find global stats for %s", channel);
  574. dprintf(idx, "<html><body>Error! Can't find global stats for %s</body></html>", channel);
  575. return;
  576. }
  577. setslglobs(gs->chan, gs->peak[S_TOTAL], countstatmembers(gs), gs->started);
  578. if (!strcmp(buf, "/") || !buf[0]) {
  579. if (!show_userlist)
  580. return;
  581. sort_stats_alphabetically(gs);
  582. dprintf(idx, "<html><head><title>%s</title>\n%s\n</head>%s",
  583. SLUSERSTITLE, SLCSS, SLBODYTAG);
  584. long_dprintf(idx, SLHEADER);
  585. dprintf(idx, "<center>\n");
  586. dprintf(idx, "<table border=%d>\n<tr><th>User</th><th>Info</th></tr>\n", table_border);
  587. i = 0;
  588. for (ls = gs->local; ls; ls = ls->next)
  589. i++;
  590. wert = table_color;
  591. b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16;
  592. wert = fade_table_to;
  593. b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16;
  594. rstep = (r2 - r) / i;
  595. gstep = (g2 - g) / i;
  596. bstep = (b2 - b) / i;
  597. for (ls = gs->local; ls; ls = ls->next) {
  598. u = get_user_by_handle(userlist, ls->user);
  599. what[0] = 0;
  600. get_handle_chaninfo(ls->user, channel, what);
  601. pwhat = what;
  602. if (!what[0])
  603. pwhat = get_user(&USERENTRY_INFO, u);
  604. if (!pwhat) {
  605. sprintf(what, "&nbsp;");
  606. pwhat = what;
  607. }
  608. dprintf(idx, "<tr bgcolor=#%02x%02x%02x><td><a href=\"%s/\">%s</a></td><td>%s</td></tr>\n",
  609. (int) r, (int) g, (int) b, ls->user, ls->user, filt2(pwhat));
  610. r += rstep;
  611. g += gstep;
  612. b += bstep;
  613. }
  614. /*
  615. * dprintf(idx, "<tr><td colspan=2 align=center><a href=\"http://www.visions-of-fantasy.de/stats.mod/\">");
  616. * dprintf(idx, "Stats.mod v%s</a></td></tr></table>\n", MODULE_VERSION);
  617. */
  618. dprintf(idx, "</table>\n");
  619. dprintf(idx, "<br><br><hr>\n");
  620. dprintf(idx, "<table width=100%% border=0>\n");
  621. dprintf(idx, "<tr><td align=center><table width=100%% border=0><tr>\n");
  622. dprintf(idx, "<td width=25%% align=center><font size=-1><%sa "
  623. "href=\"../onchan/\">%s</a></font></td>\n",
  624. ISLINK(show_usersonchan), ISTEXT(show_usersonchan, SLONCHAN));
  625. dprintf(idx, "<td width=25%% align=center><font size=-1><a href=\"../top/total/words/\">top%d</a></font></td>\n", webnr);
  626. dprintf(idx, "<td width=25%% align=center><font size=-1><a href=\"../misc/\">%s</a></font></td>\n", SLMISCSTATS);
  627. dprintf(idx, "<td width=25%% align=center><font size=-1><a href=\"../../\">%s</a></font></td>\n", SLOTHERCHANS);
  628. dprintf(idx, "</tr></table></td></tr>\n");
  629. dprintf(idx, "</table>\n");
  630. dprintf(idx, "<center>Created by <a href=\"http://www.visions-of-fantasy.de/stats.mod/\">Stats.mod v%s</a></center></body></html>", MODULE_VERSION);
  631. dprintf(idx, "</center>\n");
  632. long_dprintf(idx, SLFOOTER);
  633. dprintf(idx, "</body></html>");
  634. return;
  635. }
  636. user = buf;
  637. ls = findlocstats(channel, user);
  638. if (!ls) {
  639. debug2("Error! Can't find local stats for %s in %s", user, channel);
  640. dprintf(idx, "<html><body>I don't have any stats for %s in %s, sorry</body></html>", user, channel);
  641. if (idx >= 0)
  642. stats_info_access(idx)->code = 404;
  643. return;
  644. }
  645. i = countwords(webstats) + 2;
  646. suser = findsuser_by_name(user);
  647. dprintf(idx, "<html><head><META http-equiv=\"Pragma\" content=\"no-cache\"><META http-equiv=\"Expires\" content=\"now\">\n");
  648. slgloblocstats = ls;
  649. dprintf(idx, "<title>%s</title>\n%s\n</head>%s\n", SLUSERTITLE, SLCSS, SLBODYTAG);
  650. long_dprintf(idx, SLHEADER);
  651. dprintf(idx, "<center>\n");
  652. dprintf(idx, "%s\n", SLUSERHEAD);
  653. if (suser) {
  654. dprintf(idx, "<center>");
  655. if (suser->email)
  656. dprintf(idx, "<a href=\"mailto:%s\" target=\"_new\">%s</a><br>", suser->email, SLEMAIL);
  657. if (suser->homepage)
  658. dprintf(idx, "<a href=\"%s\" target=\"_new\">%s</a><br>", suser->homepage, SLHOMEPAGE);
  659. dprintf(idx, "</center><br>");
  660. }
  661. dprintf(idx, "<table border=%d><tr><td></td><td>%s</td>", table_border, SLPLACE);
  662. sprintf(what, "%s", webstats);
  663. pwhat = what;
  664. while (strlen(pwhat) > 0) {
  665. dprintf(idx, "<td>%s</td>", getslangtype(newsplit(&pwhat)));
  666. }
  667. dprintf(idx, "</tr>\n");
  668. wert = table_color;
  669. b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16;
  670. wert = fade_table_to;
  671. b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16;
  672. rstep = (r2 - r) / 4;
  673. gstep = (g2 - g) / 4;
  674. bstep = (b2 - b) / 4;
  675. for (today = 0; today < 4; today++) {
  676. dprintf(idx, "<tr><td align=center>%s</td>", RANGESTR_LONG);
  677. nr = 0;
  678. if (ls->values[today][T_WORDS] > 0) {
  679. sortstats(gs, T_WORDS, today);
  680. for (ls2 = gs->slocal[today][T_WORDS]; ls2; ls2 = ls2->snext[today][T_WORDS]) {
  681. nr++;
  682. if (!strcasecmp(ls2->user, user))
  683. break;
  684. }
  685. }
  686. dprintf(idx, "<td bgcolor=#%02x%02x%02x align=\"right\">\n", (int) r, (int) g, (int) b);
  687. if (nr == 0)
  688. dprintf(idx, "-</td>");
  689. else
  690. dprintf(idx, "%d</td>", nr);
  691. sprintf(what, "%s", webstats);
  692. pwhat = what;
  693. while (strlen(pwhat) > 0) {
  694. itype = typetoi(newsplit(&pwhat));
  695. dprintf(idx, "<td bgcolor=#%02x%02x%02x align=\"right\">\n", (int) r, (int) g, (int) b);
  696. if (itype == T_MINUTES)
  697. dprintf(idx, "%s</td>", stats_duration(ls->values[today][itype] * 60));
  698. else if (itype >= 0)
  699. dprintf(idx, "%d</td>", ls->values[today][itype]);
  700. else if (itype == T_WPL) {
  701. if (ls->values[today][T_LINES])
  702. dprintf(idx, "%.2f</td>", (float) ls->values[today][T_WORDS] / (float) ls->values[today][T_LINES]);
  703. else
  704. dprintf(idx, "0</td>");
  705. } else if (itype == T_IDLE) {
  706. if (ls->values[today][T_LINES])
  707. dprintf(idx, "%.2f</td>", (float) ls->values[today][T_MINUTES] / (float) ls->values[today][T_LINES]);
  708. else
  709. dprintf(idx, "0</td>");
  710. } else
  711. dprintf(idx, "ERR!</td>");
  712. }
  713. dprintf(idx, "</tr>\n");
  714. r += rstep;
  715. g += gstep;
  716. b += bstep;
  717. }
  718. if (ls->quotes && quote_freq) {
  719. nr = 0;
  720. for (qs = ls->quotes; qs; qs = qs->next)
  721. nr++;
  722. x = random() % nr;
  723. ii = 0;
  724. qs = ls->quotes;
  725. while (qs) {
  726. if (ii == x) {
  727. dprintf(idx, "<tr><td colspan=%d align=center>", i);
  728. dprintf(idx, SLRANDQUOTE, filt2(qs->quote));
  729. dprintf(idx, "</td></tr>\n");
  730. break;
  731. }
  732. qs = qs->next;
  733. ii++;
  734. }
  735. }
  736. dprintf(idx, "</table></center>\n");
  737. if (ls->words) {
  738. if (ls->words) {
  739. nr = 0;
  740. for (ws = ls->words; ws; ws = ws->next)
  741. nr++;
  742. slglobint = nr;
  743. dprintf(idx, "<center><br><br>%s<br>\n", SLUWORDSTATS);
  744. sortwordstats(ls, NULL);
  745. dprintf(idx, "<table>\n");
  746. nr = 0;
  747. ws = ls->words;
  748. while (ws && (nr < 10)) {
  749. nr++;
  750. dprintf(idx, "<tr><td>%d.</td><td>%s</td><td>(%d)</td></tr>\n", nr, filt2(ws->word), ws->nr);
  751. ws = ws->next;
  752. }
  753. dprintf(idx, "</table><br><br></center>\n");
  754. }
  755. }
  756. dprintf(idx, "<br><br><hr>\n");
  757. dprintf(idx, "<table width=100%% border=0>\n");
  758. dprintf(idx, "<tr><td align=center><table width=100%% border=0><tr>\n");
  759. dprintf(idx, "<td width=20%% align=center><font size=-1><%sa href=\"../\">%s</a></font></td>\n",
  760. ISLINK(show_usersonchan), ISTEXT(show_usersonchan, SLOTHERUSERS));
  761. dprintf(idx, "<td width=20%% align=center><font size=-1><%sa href=\"../../onchan\">%s</a></font></td>\n",
  762. ISLINK(show_usersonchan), ISTEXT(show_usersonchan, SLONCHAN));
  763. dprintf(idx, "<td width=20%% align=center><font size=-1><a href=\"../../top/total/words/\">%s</a></font></td>\n", SLTOP);
  764. dprintf(idx, "<td width=20%% align=center><font size=-1><a href=\"../../misc/\">%s</a></font></td>\n", SLMISCSTATS);
  765. dprintf(idx, "<td width=20%% align=center><font size=-1><a href=\"../../../\">%s</a></font></td>\n", SLOTHERCHANS);
  766. dprintf(idx, "</tr></table></td></tr>\n");
  767. dprintf(idx, "</table>\n");
  768. dprintf(idx, "<center>Created by <a href=\"http://www.visions-of-fantasy.de/stats.mod/\">Stats.mod v%s</a></center></body></html>", MODULE_VERSION);
  769. long_dprintf(idx, SLFOOTER);
  770. dprintf(idx, "</body></html>");
  771. return;
  772. } else if (!strcasecmp(command, "misc")) {
  773. do_miscstats(idx, channel);
  774. return;
  775. } else {
  776. dprintf(idx, "<html><body>Error! unknown command %s</body></html>", command);
  777. if (idx >= 0)
  778. stats_info_access(idx)->code = 404;
  779. return;
  780. }
  781. }
  782. static void do_graphs(int idx, int today, globstats *gs, char *channel)
  783. {
  784. int itype, nr;
  785. int total, rest, width, max;
  786. float onep, percent, wpercent;
  787. char bground[140];
  788. locstats *ls;
  789. char what[512], *pwhat, *type;
  790. Context;
  791. setslglobs(gs->chan, gs->peak[S_TOTAL], countstatmembers(gs), gs->started);
  792. if (graphgif[0] == 0)
  793. bground[0] = 0;
  794. else
  795. sprintf(bground, "background=\"%s\"", graphgif);
  796. dprintf(idx, "<!-- Created by Stats.mod v%s-->\n", MODULE_VERSION);
  797. dprintf(idx, "<html><head><META http-equiv=\"Pragma\" content=\"no-cache\"><META http-equiv=\"Expires\" content=\"now\">\n");
  798. if (today == 0)
  799. dprintf(idx, "<title>%s</title>\n", SLGRTTITLE);
  800. else if (today == 1)
  801. dprintf(idx, "<title>%s</title>\n", SLGRDTITLE);
  802. else if (today == 2)
  803. dprintf(idx, "<title>%s</title>\n", SLGRWTITLE);
  804. else if (today == 3)
  805. dprintf(idx, "<title>%s</title>\n", SLGRMTITLE);
  806. dprintf(idx, "%s\n</head>%s\n", SLCSS, SLBODYTAG);
  807. long_dprintf(idx, SLHEADER);
  808. if (today == 0)
  809. dprintf(idx, "%s", SLGRTHEAD);
  810. else if (today == 1)
  811. dprintf(idx, "%s", SLGRDHEAD);
  812. else if (today == 2)
  813. dprintf(idx, "%s", SLGRWHEAD);
  814. else if (today == 3)
  815. dprintf(idx, "%s", SLGRMHEAD);
  816. sprintf(what, "%s", graphstats);
  817. pwhat = what;
  818. while (strlen(pwhat) > 0) {
  819. type = newsplit(&pwhat);
  820. itype = typetoi(type);
  821. if (itype < 0) {
  822. putlog(LOG_MISC, "*", "Stats.mod: Error serving livestats. Unsupported type %s. Skipping.", type);
  823. continue;
  824. }
  825. sortstats(gs, itype, today);
  826. max = 0;
  827. for (ls = gs->slocal[today][itype]; ls; ls = ls->snext[today][itype]) {
  828. if (listsuser(ls, channel)) {
  829. max = ls->values[today][itype];
  830. break;
  831. }
  832. }
  833. if (max == 0)
  834. continue;
  835. total = gettotal(gs, itype, today);
  836. rest = total;
  837. dprintf(idx, "<br><br><br><table width=100%% border=1><tr><th width=100%% align=center>");
  838. dprintf(idx, SLGRORDEREDBY, getslangtype(type));
  839. dprintf(idx, "</td></tr></table>\n");
  840. slglobint = total;
  841. dprintf(idx, SLGRTOTAL, getslangtype(type));
  842. dprintf(idx, "<br>\n");
  843. dprintf(idx, "<table width=100%%>\n");
  844. if (!total || !max)
  845. continue;
  846. onep = (float) total / 100.0;
  847. nr = 0;
  848. for (ls = gs->slocal[today][itype]; ls; ls = ls->snext[today][itype]) {
  849. if (!listsuser(ls, channel))
  850. continue;
  851. if (!ls->values[today][itype])
  852. break;
  853. nr++;
  854. if (nr > graphnr)
  855. break;
  856. dprintf(idx, "<tr>\n");
  857. percent = (float) ls->values[today][itype] / onep;
  858. wpercent = (float) ls->values[today][itype] / ((float) max / 100.0);
  859. width = (int) wpercent * 0.8;
  860. dprintf(idx, " <td align=right width=10%%><a href=\"../../../users/%s/\">%s</a></td>\n", ls->user, ls->user);
  861. dprintf(idx, " <td align=left width=90%%>\n");
  862. dprintf(idx, " <table width=100%%><tr>\n");
  863. dprintf(idx, " <td width=%d%% bgcolor=\"%s\" %s>&nbsp;</td>\n", width, graphcolor, bground);
  864. dprintf(idx, " <td align=left width=%d%%>%.2f%% <font size=-2>[%d]</font></td>\n", 100 - width, percent, ls->values[today][itype]);
  865. dprintf(idx, " </tr></table>\n");
  866. dprintf(idx, " </td>\n");
  867. dprintf(idx, "</tr>\n");
  868. rest -= ls->values[today][itype];
  869. }
  870. dprintf(idx, "<tr>\n");
  871. percent = (float) rest / ((float) total / 100.0);
  872. wpercent = (float) rest / ((float) max / 100.0);
  873. width = (int) wpercent * 0.8;
  874. dprintf(idx, " <td align=right width=10%%>%s</td>\n", SLGROTHERS);
  875. dprintf(idx, " <td align=left width=90%%>\n");
  876. dprintf(idx, " <table width=100%%><tr>\n");
  877. dprintf(idx, " <td width=%d%% bgcolor=\"%s\" %s>&nbsp;</td>\n", width, graphcolor, bground);
  878. dprintf(idx, " <td align=left width=%d%%>%.2f%% <font size=-2>[%d]</font></td>\n", 100 - width, percent, rest);
  879. dprintf(idx, " </tr></table>\n");
  880. dprintf(idx, " </td>\n");
  881. dprintf(idx, "</tr></table>\n");
  882. }
  883. dprintf(idx, "</table>\n");
  884. dprintf(idx, "<br><hr><br>\n");
  885. dprintf(idx, "<table width=100%% border=0>\n");
  886. dprintf(idx, "<tr><td width=25%% align=center><a href=\"../words/\">%s</a></td></tr>\n", SLGRTABLE);
  887. dprintf(idx, "<tr><td align=center><table width=100%% border=0><tr>\n");
  888. dprintf(idx, "<td width=25%% align=center><a href=\"../../total/graphs/\">%s</a></td>\n", SLTOTAL);
  889. dprintf(idx, "<td width=25%% align=center><a href=\"../../daily/graphs/\">%s</a></td>\n", SLDAILY);
  890. dprintf(idx, "<td width=25%% align=center><a href=\"../../weekly/graphs/\">%s</a></td>\n", SLWEEKLY);
  891. dprintf(idx, "<td width=25%% align=center><a href=\"../../monthly/graphs/\">%s</a></td>\n", SLMONTHLY);
  892. dprintf(idx, "</tr></table></td></tr>\n");
  893. dprintf(idx, "<tr><td align=center><table width=100%% border=0><tr>\n");
  894. dprintf(idx, "<td width=25%% align=center><a href=\"../../../misc/\">%s</a></td>\n", SLMISCSTATS);
  895. dprintf(idx, "<td width=25%% align=center><%sa href=\"../../../users/\">%s</a></td>\n",
  896. ISLINK(show_userlist), ISTEXT(show_userlist, SLUSERS));
  897. dprintf(idx, "<td width=25%% align=center><%sa href=\"../../../onchan/\">%s</a></td>\n",
  898. ISLINK(show_usersonchan), ISTEXT(show_usersonchan, SLONCHAN));
  899. dprintf(idx, "<td width=25%% align=center><a href=\"../../../../\">%s</a></td>\n", SLOTHERCHANS);
  900. dprintf(idx, "</tr></table></td></tr>\n");
  901. dprintf(idx, "</table>\n");
  902. dprintf(idx, "<br><center>Created by "
  903. "<a href=\"http://www.visions-of-fantasy.de/stats.mod/\">Stats.mod "
  904. "v%s</a></center>\n", MODULE_VERSION);
  905. long_dprintf(idx, SLFOOTER);
  906. dprintf(idx, "</body></html>");
  907. return;
  908. }
  909. static void do_toptalkers(int idx, int today, globstats *gs, char *channel, char *buf)
  910. {
  911. char what2[512], *pwhat2, *type, *type2;
  912. locstats *ls;
  913. int itype, itype2, pitype, nr, i;
  914. int wert;
  915. float r, g, b;
  916. float r2, g2, b2;
  917. float rstep, gstep, bstep;
  918. quotestr *q;
  919. unsigned long x;
  920. Context;
  921. setslglobs(channel, gs->peak[today], countstatmembers(gs), gs->started);
  922. type = buf;
  923. itype = typetoi(type);
  924. if (itype == T_ERROR) {
  925. dprintf(idx, "<html><body>Error! No such type %s</body></html>", type);
  926. if (idx >= 0)
  927. stats_info_access(idx)->code = 404;
  928. return;
  929. }
  930. if (itype < 0)
  931. pitype = (itype * -1) + (TOTAL_TYPES - 1);
  932. else
  933. pitype = itype;
  934. dprintf(idx, "<html><head><META http-equiv=\"Pragma\" content=\"no-cache\"><META http-equiv=\"Expires\" content=\"now\">\n");
  935. if (today == 0)
  936. dprintf(idx, "<title>%s</title>\n", SLTTOPTITLE);
  937. else if (today == 1)
  938. dprintf(idx, "<title>%s</title>\n", SLDTOPTITLE);
  939. else if (today == 2)
  940. dprintf(idx, "<title>%s</title>\n", SLWTOPTITLE);
  941. else if (today == 3)
  942. dprintf(idx, "<title>%s</title>\n", SLMTOPTITLE);
  943. dprintf(idx, "<META Name=\"Stats.mod\" Content=\"%s\">\n", MODULE_VERSION);
  944. dprintf(idx, "<META Name=\"channel\" Content=\"%s\">\n", gs->chan);
  945. dprintf(idx, "<META Name=\"network\" Content=\"%s\">\n", network);
  946. dprintf(idx, "<META Name=\"written\" Content=\"%lu\">\n", now);
  947. dprintf(idx, "%s\n</head>\n", SLCSS);
  948. dprintf(idx, "%s", SLBODYTAG);
  949. long_dprintf(idx, SLHEADER);
  950. if (today == 0)
  951. dprintf(idx, "%s\n", SLTTOPHEAD);
  952. else if (today == 1)
  953. dprintf(idx, "%s\n", SLDTOPHEAD);
  954. else if (today == 2)
  955. dprintf(idx, "%s\n", SLWTOPHEAD);
  956. else if (today == 3)
  957. dprintf(idx, "%s\n", SLMTOPHEAD);
  958. dprintf(idx, SLORDEREDBY, getslangtype(type));
  959. dprintf(idx, "<BR>\n");
  960. dprintf(idx, SLPEAK);
  961. dprintf(idx, "<BR>\n");
  962. dprintf(idx, "<P><center><table border=%d cellpadding=1><tr align=right>", table_border);
  963. dprintf(idx, "<th>%s</th>", SLTNR);
  964. dprintf(idx, "<th align=center>Nick</th>");
  965. sprintf(what2, "%s", webstats);
  966. pwhat2 = what2;
  967. while (strlen(pwhat2) > 0) {
  968. type2 = newsplit(&pwhat2);
  969. dprintf(idx, "<th><a href=\"../%s/\">%s</a></th>\n", type2, getslangtype(type2));
  970. }
  971. sortstats(gs, itype, today);
  972. nr = 0;
  973. wert = table_color;
  974. b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16;
  975. wert = fade_table_to;
  976. b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16;
  977. rstep = (r2 - r) / webnr;
  978. gstep = (g2 - g) / webnr;
  979. bstep = (b2 - b) / webnr;
  980. for (ls = gs->slocal[today][pitype]; ls; ls = ls->snext[today][pitype]) {
  981. if (!listsuser(ls, channel))
  982. continue;
  983. if ((itype >= 0) && !ls->values[today][itype])
  984. break;
  985. nr++;
  986. if (nr > webnr)
  987. break;
  988. dprintf(idx, "<tr align=\"right\" bgcolor=#%02x%02x%02x><td>%d</td><td><a href=\"../../../users/%s/\">%s</a></td>",
  989. (int) r, (int) g, (int) b, nr, ls->user, ls->user);
  990. r += rstep;
  991. g += gstep;
  992. b += bstep;
  993. sprintf(what2, "%s", webstats);
  994. pwhat2 = what2;
  995. while (strlen(pwhat2) > 0) {
  996. type2 = newsplit(&pwhat2);
  997. itype2 = typetoi(type2);
  998. dprintf(idx, "<td>");
  999. // mark the sorted value bold
  1000. if (itype == itype2)
  1001. dprintf(idx, "<b>");
  1002. // now output the values
  1003. // T_MINUTES gets a special handling, because it's kinda hard to read
  1004. // something like "2348 Minutes" *g*
  1005. if (itype2 == T_MINUTES)
  1006. dprintf(idx, "%s", stats_duration(ls->values[today][itype2] * 60));
  1007. // no positive type needs any special handling, so lt's just output it
  1008. else if (itype2 >= 0)
  1009. dprintf(idx, "%d", ls->values[today][itype2]);
  1010. // words per line need to be calculated
  1011. else if (itype2 == T_WPL) {
  1012. if (ls->values[today][T_LINES])
  1013. dprintf(idx, "%.2f", ((float) ls->values[today][T_WORDS]) / ((float) ls->values[today][T_LINES]));
  1014. else
  1015. dprintf(idx, "0");
  1016. // idle-factor also needs to be calculated
  1017. } else if (itype2 == T_IDLE) {
  1018. if (ls->values[today][T_LINES])
  1019. dprintf(idx, "%.2f", ((float) ls->values[today][T_MINUTES]) / ((float) ls->values[today][T_LINES]));
  1020. else
  1021. dprintf(idx, "0");
  1022. } else if (itype2 == T_QUOTE) {
  1023. if (!ls->quotes)
  1024. dprintf(idx, "&nbsp;");
  1025. else {
  1026. nr = 0;
  1027. for (q = ls->quotes; q; q = q->next)
  1028. nr++;
  1029. x = random() % nr;
  1030. i = 0;
  1031. q = ls->quotes;
  1032. while (q) {
  1033. if (i == x) {
  1034. dprintf(idx, "%s", filt2(q->quote));
  1035. break;
  1036. }
  1037. q = q->next;
  1038. i++;
  1039. }
  1040. }
  1041. } else // output an error, if we missed something
  1042. dprintf(idx, "ERROR! itype2: %d", itype2);
  1043. if (itype == itype2)
  1044. dprintf(idx, "</b>");
  1045. dprintf(idx, "</td>");
  1046. }
  1047. dprintf(idx, "</tr>\n");
  1048. }
  1049. dprintf(idx, "<tr>");
  1050. dprintf(idx, "<td colspan=%d align=center><b>", countwords(webstats) + 2);
  1051. dprintf(idx, SLTOTALUSERS);
  1052. dprintf(idx, "</B></td></tr>\n");
  1053. dprintf(idx, "<tr><td colspan=%d align=center>", countwords(webstats) + 2);
  1054. dprintf(idx, "<table width=100%% border=0>\n");
  1055. dprintf(idx, "<tr><td width=100%% align=center colspan=4><a href=\"../graphs/\">%s</a></td></tr>\n", SLGRAPHS);
  1056. dprintf(idx, "<tr><td width=25%% align=center><a href=\"../../total/%s/\">%s</a></td>\n", type, SLTOTAL);
  1057. dprintf(idx, "<td width=25%% align=center><a href=\"../../daily/%s/\">%s</a></td>\n", type, SLDAILY);
  1058. dprintf(idx, "<td width=25%% align=center><a href=\"../../weekly/%s/\">%s</a></td>\n", type, SLWEEKLY);
  1059. dprintf(idx, "<td width=25%% align=center><a href=\"../../monthly/%s/\">%s</a></td>\n", type, SLMONTHLY);
  1060. dprintf(idx, "</tr></table></td></tr>\n");
  1061. dprintf(idx, "<tr><td colspan=%d align=center><table width=100%% border=0><tr>\n", countwords(webstats) + 2);
  1062. dprintf(idx, "<td width=25%% align=center><a href=\"../../../misc/\">%s</a></td>\n", SLMISCSTATS);
  1063. dprintf(idx, "<td width=25%% align=center><%sa href=\"../../../users/\">%s</a></td>\n",
  1064. ISLINK(show_userlist), ISTEXT(show_userlist, SLUSERS));
  1065. dprintf(idx, "<td width=25%% align=center><%sa href=\"../../../onchan/\">%s</a></td>\n",
  1066. ISLINK(show_usersonchan), ISTEXT(show_usersonchan, SLONCHAN));
  1067. dprintf(idx, "<td width=25%% align=center><a href=\"../../../../\">%s</a></td>\n", SLOTHERCHANS);
  1068. dprintf(idx, "</tr>\n</table></td></tr>\n");
  1069. dprintf(idx, "</table><br>");
  1070. if (!today)
  1071. dprintf(idx, SLGSTARTED);
  1072. dprintf(idx, "<br><a href=\"http://www.visions-of-fantasy.de/stats.mod/\">Stats.mod v%s</a>.", MODULE_VERSION);
  1073. dprintf(idx, "</CENTER>\n");
  1074. long_dprintf(idx, SLFOOTER);
  1075. dprintf(idx, "</body></html>");
  1076. return;
  1077. }
  1078. static void do_miscstats(int idx, char *channel)
  1079. {
  1080. globstats *gs, *tlds, *isps;
  1081. wordstats *ws;
  1082. int nr, tr, i, wert, wieoft, pitype;
  1083. locstats *ls;
  1084. char *host, *s;
  1085. topicstr *t;
  1086. char ts[20];
  1087. float f, max, onep;
  1088. hoststr *h, *isp, *tld;
  1089. struct slang_lang *l;
  1090. struct slang_bntypes *ty;
  1091. struct slang_bnplaces *p;
  1092. struct slang_texts *txt;
  1093. unsigned long x;
  1094. float r, g, b;
  1095. float r2, g2, b2;
  1096. float rstep, gstep, bstep;
  1097. struct stats_url *url;
  1098. struct stats_kick *kick;
  1099. struct stats_quote *log;
  1100. Context;
  1101. gs = findglobstats(channel);
  1102. if (!gs) {
  1103. dprintf(idx, "<html><body>ERROR! Can't find stats for %s!</body></html>\n", channel);
  1104. return;
  1105. }
  1106. setslglobs(gs->chan, gs->peak[S_TOTAL], countstatmembers(gs), gs->started);
  1107. dprintf(idx, "<html><head><META http-equiv=\"Pragma\" content=\"no-cache\">"
  1108. "<META http-equiv=\"Expires\" content=\"now\"><title>%s</title>\n",
  1109. SLMISCTITLE);
  1110. long_dprintf(idx, SLCSS);
  1111. dprintf(idx, "</head>\n");
  1112. dprintf(idx, "%s\n", SLBODYTAG);
  1113. long_dprintf(idx, SLHEADER);
  1114. dprintf(idx, "%s<br>\n", SLMISCHEAD);
  1115. do_globwordstats(gs);
  1116. max = 0.0;
  1117. wert = nr = 0; /* I'm recycling these vars, so ignore the strange names */
  1118. for (i = 0; i < 24; i++) {
  1119. if (i < 12) {
  1120. if (gs->users[S_USERCOUNTS][i] > 0)
  1121. wert = 1;
  1122. } else {
  1123. if (gs->users[S_USERCOUNTS][i] > 0)
  1124. nr = 1;
  1125. }
  1126. if (gs->users[S_USERCOUNTS][i] > 0)
  1127. if ((((float) gs->users[S_USERSUM][i]) / ((float) gs->users[S_USERCOUNTS][i])) > max)
  1128. max = ((float) gs->users[S_USERSUM][i]) / ((float) gs->users[S_USERCOUNTS][i]);
  1129. }
  1130. if (display_average_users && (max > 0.0)) {
  1131. dprintf(idx, "%s<br><font size=\"-5\">\n", SLMAUSERS);
  1132. if (wert && nr)
  1133. dprintf(idx, "<table border=0 width=\"75%%\"><tr><td width=\"50%%\" align=\"center\" valign=\"bottom\">\n");
  1134. else
  1135. dprintf(idx, "<table border=0 width=\"37%%\"><tr><td width=\"100%%\" align=\"center\" valign=\"bottom\">\n");
  1136. dprintf(idx, "<table border=%d width=\"100%%\">", table_border);
  1137. onep = max / 100.0;
  1138. for (i = 0; i < 24; i++) {
  1139. if ((i == 12) && (wert && nr))
  1140. dprintf(idx, "</table></td><td width=\"50%%\" align=\"center\" valign=\"bottom\"><table border=%d width=\"100%%\">", table_border);
  1141. if (gs->users[S_USERCOUNTS][i] > 0) {
  1142. f = ((float) gs->users[S_USERSUM][i]) / ((float) gs->users[S_USERCOUNTS][i]);
  1143. dprintf(idx, "<tr><td width=\"1%%\"><font size=\"-5\">%d.00-%d.59</font></td><td width=\"99%%\"><table width=\"100%%\"><tr>", i, i);
  1144. if (((int) (f / onep)) > 0)
  1145. dprintf(idx, "<td width=\"%d%%\" bgcolor=\"%s\"><font size=\"-5\">&nbsp;</font></td><td><font size=\"-5\">%.2f</font></td></tr></table></td>", (int) (f / onep), graphcolor, f);
  1146. else if ((f / onep) > 0.0)
  1147. dprintf(idx, "<td width=\"100%%\"><font size=\"-5\">%.2f</font></td></tr></table></td>", f);
  1148. else
  1149. dprintf(idx, "<td width=\"100%%\"><font size=\"-5\">%.2f</font></td></tr></table></td>", f);
  1150. dprintf(idx, "</tr>\n");
  1151. }
  1152. }
  1153. dprintf(idx, "</table>");
  1154. dprintf(idx, "</td></tr></table>");
  1155. dprintf(idx, "</font>\n");
  1156. }
  1157. if (gs->topics) {
  1158. dprintf(idx, "<br><br>%s<br>\n<table border=%d>", SLMTOPICS, table_border);
  1159. i = 0;
  1160. for (t = gs->topics; t; t = t->next)
  1161. i++;
  1162. wert = table_color;
  1163. b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16;
  1164. wert = fade_table_to;
  1165. b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16;
  1166. rstep = (r2 - r) / i;
  1167. gstep = (g2 - g) / i;
  1168. bstep = (b2 - b) / i;
  1169. for (t = gs->topics; t; t = t->next) {
  1170. strftime(ts, 20, "%H:%M", localtime(&t->when));
  1171. setslnick(t->by);
  1172. dprintf(idx, "<tr bgcolor=#%02x%02x%02x><td>\"%s\"</td><td>",
  1173. (int) r, (int) g, (int) b, filt2(t->topic));
  1174. dprintf(idx, SLMTOPICBY, ts);
  1175. dprintf(idx, "</td></tr>\n");
  1176. r += rstep;
  1177. g += gstep;
  1178. b += bstep;
  1179. }
  1180. dprintf(idx, "</table><br><br>\n");
  1181. }
  1182. if (gs->urls && log_urls) {
  1183. nr = 0;
  1184. for (url = gs->urls; url; url = url->next) {
  1185. nr++;
  1186. url->shown = 0;
  1187. }
  1188. if (nr > log_urls)
  1189. wieoft = log_urls;
  1190. else
  1191. wieoft = nr;
  1192. slglobint = wieoft;
  1193. dprintf(idx, "<br><br><table border=%d><caption>%s</caption>", table_border, SLMURLS);
  1194. wert = table_color;
  1195. b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16;
  1196. wert = fade_table_to;
  1197. b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16;
  1198. rstep = (r2 - r) / wieoft;
  1199. gstep = (g2 - g) / wieoft;
  1200. bstep = (b2 - b) / wieoft;
  1201. while (wieoft > 0) {
  1202. x = random() % nr;
  1203. i = 0;
  1204. url = gs->urls;
  1205. while (url) {
  1206. if (url->shown) {
  1207. url = url->next;
  1208. continue;
  1209. }
  1210. if (i == x) {
  1211. dprintf(idx, "<tr bgcolor=#%02x%02x%02x><td>\"<a href=\"%s\">%s</a>\"</td><td>",
  1212. (int) r, (int) g, (int) b, url->url, url->url);
  1213. strftime(ts, 20, "%H:%M", localtime(&url->when));
  1214. setslnick(url->by);
  1215. dprintf(idx, SLMURLBY, ts);
  1216. dprintf(idx, "</td></tr>\n");
  1217. url->shown = 1;
  1218. nr--;
  1219. r += rstep;
  1220. g += gstep;
  1221. b += bstep;
  1222. break;
  1223. }
  1224. url = url->next;
  1225. i++;
  1226. }
  1227. wieoft--;
  1228. }
  1229. dprintf(idx, "</table>\n");
  1230. }
  1231. if (gs->hosts) {
  1232. tlds = nmalloc(sizeof(globstats));
  1233. tlds->hosts = NULL;
  1234. isps = nmalloc(sizeof(globstats));
  1235. isps->hosts = NULL;
  1236. for (h = gs->hosts; h; h = h->next) {
  1237. // skip IPv6 hosts
  1238. if (strchr(h->host, ':'))
  1239. continue;
  1240. host = strrchr(h->host, '.') + 1;
  1241. if (!atoi(host) && (host[0] != '0')) {
  1242. addhost(host, tlds);
  1243. host = h->host;
  1244. while ((s = strchr(host, '.')) && strchr(s + 1, '.'))
  1245. host = s + 1;
  1246. addhost(host, isps);
  1247. } else {
  1248. addhost("[IP]", tlds);
  1249. addhost("[IP]", isps);
  1250. }
  1251. }
  1252. sorthosts(isps);
  1253. sorthosts(tlds);
  1254. dprintf(idx, "<br><br><table border=%d><tr><th colspan=2>%s</th></tr><tr><th>%s</th><th>%s</th></tr>\n",
  1255. table_border, SLMMOSTUSED, SLMISPS, SLMTLDS);
  1256. i = 0;
  1257. isp = isps->hosts;
  1258. tld = tlds->hosts;
  1259. wert = table_color;
  1260. b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16;
  1261. wert = fade_table_to;
  1262. b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16;
  1263. rstep = (r2 - r) / 5;
  1264. gstep = (g2 - g) / 5;
  1265. bstep = (b2 - b) / 5;
  1266. while ((i <= 5) && (isp || tld)) {
  1267. i++;
  1268. dprintf(idx, "<tr bgcolor=#%02x%02x%02x>\n", (int) r, (int) g, (int) b);
  1269. r += rstep;
  1270. g += gstep;
  1271. b += bstep;
  1272. if (isp)
  1273. dprintf(idx, "<td>%s (%d)</td>", isp->host, isp->nr);
  1274. else
  1275. dprintf(idx, "<td>-</td>");
  1276. if (tld)
  1277. dprintf(idx, "<td>%s (%d)</td>", tld->host, tld->nr);
  1278. else
  1279. dprintf(idx, "<td>-</td>");
  1280. dprintf(idx, "</tr>\n");
  1281. if (isp)
  1282. isp = isp->next;
  1283. if (tld)
  1284. tld = tld->next;
  1285. }
  1286. dprintf(idx, "</table>\n");
  1287. free_hosts(isps->hosts);
  1288. free_hosts(tlds->hosts);
  1289. nfree(isps);
  1290. nfree(tlds);
  1291. }
  1292. if (gs->kicks && (display_kicks > 0)) {
  1293. nr = 0;
  1294. for (kick = gs->kicks; kick; kick = kick->next) {
  1295. nr++;
  1296. kick->shown = 0;
  1297. }
  1298. if (nr > display_kicks)
  1299. wieoft = display_kicks;
  1300. else
  1301. wieoft = nr;
  1302. slglobint = wieoft;
  1303. dprintf(idx, "<br><br><table border=%d><caption>%s</caption>", table_border, SLMKICKS);
  1304. wert = table_color;
  1305. b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16;
  1306. wert = fade_table_to;
  1307. b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16;
  1308. rstep = (r2 - r) / wieoft;
  1309. gstep = (g2 - g) / wieoft;
  1310. bstep = (b2 - b) / wieoft;
  1311. while (wieoft > 0) {
  1312. x = random() % nr;
  1313. i = 0;
  1314. kick = gs->kicks;
  1315. while (kick) {
  1316. if (kick->shown) {
  1317. kick = kick->next;
  1318. continue;
  1319. }
  1320. if (i == x) {
  1321. dprintf(idx, "<tr bgcolor=#%02x%02x%02x><td><cite><font size=-2>", (int) r, (int) g, (int) b);
  1322. for (log = kick->log; log; log = log->next) {
  1323. if (log->next)
  1324. dprintf(idx, "%s<br>", filt2(log->quote));
  1325. else
  1326. dprintf(idx, "</font>%s</b><br>", filt2(log->quote));
  1327. }
  1328. dprintf(idx, "</cite></td></tr>\n");
  1329. kick->shown = 1;
  1330. nr--;
  1331. r += rstep;
  1332. g += gstep;
  1333. b += bstep;
  1334. break;
  1335. }
  1336. kick = kick->next;
  1337. i++;
  1338. }
  1339. wieoft--;
  1340. }
  1341. dprintf(idx, "</table>\n");
  1342. }
  1343. if (gs->words) {
  1344. nr = 0;
  1345. for (ws = gs->words; ws; ws = ws->next)
  1346. nr++;
  1347. dprintf(idx, "<br><br>"); dprintf(idx, SLMCWORDSTATS, nr); dprintf(idx, "<br>\n");
  1348. dprintf(idx, "%s<br><table border=%d>\n", SLMMOSTUSEDWORDS, table_border);
  1349. wert = table_color;
  1350. b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16;
  1351. wert = fade_table_to;
  1352. b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16;
  1353. rstep = (r2 - r) / 10;
  1354. gstep = (g2 - g) / 10;
  1355. bstep = (b2 - b) / 10;
  1356. ws = gs->words;
  1357. nr = 0;
  1358. while (ws && (nr < 10)) {
  1359. nr++;
  1360. dprintf(idx, "<tr bgcolor=#%02x%02x%02x><td>%d.</td><td>%s</td><td>(%d)</td></tr>\n",
  1361. (int) r, (int) g, (int) b, nr, filt2(ws->word), ws->nr);
  1362. r += rstep;
  1363. g += gstep;
  1364. b += bstep;
  1365. ws = ws->next;
  1366. }
  1367. dprintf(idx, "</table>\n");
  1368. }
  1369. dprintf(idx, "<br><br><table border=%d>\n", table_border);
  1370. for (l = slangs; l; l = l->next) {
  1371. if ((!l->lang && !slgloblang) || (l->lang && slgloblang && !strcasecmp(l->lang, slgloblang))) {
  1372. i = 0;
  1373. for (ty = l->bignumbers; ty; ty = ty->next)
  1374. i++;
  1375. wert = table_color;
  1376. b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16;
  1377. wert = fade_table_to;
  1378. b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16;
  1379. rstep = (r2 - r) / i;
  1380. gstep = (g2 - g) / i;
  1381. bstep = (b2 - b) / i;
  1382. for (ty = l->bignumbers; ty; ty = ty->next) {
  1383. i = typetoi(ty->type);
  1384. sortstats(gs, i, S_DAILY);
  1385. tr = 0;
  1386. for (p = ty->places; p; p = p->next) {
  1387. nr = 1;
  1388. if (i < 0)
  1389. pitype = (i * -1) + (TOTAL_TYPES - 1);
  1390. else
  1391. pitype = i;
  1392. ls = gs->slocal[S_DAILY][pitype];
  1393. while (ls && (nr < p->place)) {
  1394. nr++;
  1395. ls = ls->snext[S_DAILY][pitype];
  1396. }
  1397. // just skip this entry if any vital information is missing.
  1398. if (!ls)
  1399. continue;
  1400. else if ((i >= 0) && !ls->values[S_DAILY][i])
  1401. continue;
  1402. else if ((i == T_WPL) && (!ls->values[S_DAILY][T_WORDS] || !ls->values[S_DAILY][T_LINES]))
  1403. continue;
  1404. else if ((i == T_IDLE) && (!ls->values[S_DAILY][T_MINUTES] || !ls->values[S_DAILY][T_LINES]))
  1405. continue;
  1406. else if ((i == T_VOCABLES) && !ls->vocables)
  1407. continue;
  1408. if (!tr) {
  1409. dprintf(idx, "<tr bgcolor=#%02x%02x%02x><td>\n", (int) r, (int) g, (int) b);
  1410. r += rstep;
  1411. g += gstep;
  1412. b += bstep;
  1413. tr = 1;
  1414. }
  1415. slgloblocstats = ls;
  1416. slglobtype = ty->type;
  1417. x = random() % p->entries;
  1418. txt = p->texts;
  1419. while (txt) {
  1420. if (!x)
  1421. dprintf(idx, "%s\n", dynamicslang(txt->text));
  1422. x--;
  1423. txt = txt->next;
  1424. }
  1425. }
  1426. if (tr)
  1427. dprintf(idx, "</td></tr>\n");
  1428. }
  1429. }
  1430. }
  1431. dprintf(idx, "</table>\n");
  1432. dprintf(idx, "<br><br><hr>\n");
  1433. dprintf(idx, "<table width=100%% border=0>\n");
  1434. dprintf(idx, "<tr><td align=center><table width=100%% border=0><tr>\n");
  1435. dprintf(idx, "<td width=25%% align=center><font size=-1><a href=\"../top/total/words/\">top%d</a></font></td>\n", webnr);
  1436. dprintf(idx, "<td width=25%% align=center><font size=-1><%sa href=\"../users/\">%s</a></font></td>\n",
  1437. ISLINK(show_userlist), ISTEXT(show_userlist, SLUSERS));
  1438. dprintf(idx, "<td width=25%% align=center><font size=-1><%sa href=\"../onchan/\">%s</a></font></td>\n",
  1439. ISLINK(show_usersonchan), ISTEXT(show_usersonchan, SLONCHAN));
  1440. dprintf(idx, "<td width=25%% align=center><font size=-1><a href=\"../../\">%s</a></font></td>\n", SLOTHERCHANS);
  1441. dprintf(idx, "</tr></table></td></tr>\n");
  1442. dprintf(idx, "</table>\n");
  1443. dprintf(idx, "<center>Created by <a href=\"http://www.visions-of-fantasy.de/stats.mod/\">Stats.mod v%s</a></center></body></html>", MODULE_VERSION);
  1444. long_dprintf(idx, SLFOOTER);
  1445. dprintf(idx, "</body></html>");
  1446. }
  1447. static void display_users_on_chan(int idx, char *channel, struct chanset_t *chan)
  1448. {
  1449. memberlist *m;
  1450. struct stats_memberlist *mm;
  1451. int wert;
  1452. float r, g, b;
  1453. float r2, g2, b2;
  1454. float rstep, gstep, bstep;
  1455. int i;
  1456. char s1[121];
  1457. Context;
  1458. dprintf(idx, "<html><head><title>%s</title>\n%s\n</head>\n", SLUSERSONCHANTITLE, SLCSS);
  1459. dprintf(idx, "%s\n", SLBODYTAG);
  1460. long_dprintf(idx, SLHEADER);
  1461. if (show_usersonchan && chan && (chan->channel.members > 0)) {
  1462. dprintf(idx, "<br><br><center><table border=%d>\n<tr><th colspan=3>%s</th></tr>\n", table_border, SLNOWONCHAN);
  1463. dprintf(idx, "<tr><th align=\"center\">nick</th><th align=\"center\">user</th><th align=\"center\">%s</th></tr>\n", SLIDLETIME);
  1464. i = 0;
  1465. for (m = chan->channel.member; m && m->nick[0]; m = m->next)
  1466. i++;
  1467. wert = table_color;
  1468. b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16;
  1469. wert = fade_table_to;
  1470. b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16;
  1471. rstep = (r2 - r) / i;
  1472. gstep = (g2 - g) / i;
  1473. bstep = (b2 - b) / i;
  1474. for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
  1475. dprintf(idx, "<tr bgcolor=#%02x%02x%02x>", (int) r, (int) g, (int) b);
  1476. dprintf(idx, "<td align=\"left\">%s%s</td>",
  1477. chan_hasop(m) ? "@" : (chan_hasvoice(m) ? "+" : "&nbsp;"),
  1478. m->nick);
  1479. r += rstep;
  1480. g += gstep;
  1481. b += bstep;
  1482. if (!m->user && ((strlen(m->nick) + strlen(m->userhost) + 1) < 120)) {
  1483. sprintf(s1, "%s!%s", m->nick, m->userhost);
  1484. m->user = get_user_by_host(s1);
  1485. }
  1486. if (!use_userfile) {
  1487. mm = nick2suser(m->nick, channel);
  1488. if (mm && mm->user)
  1489. dprintf(idx, "<td align=\"center\"><a href=\"../users/%s/\">%s</a></td>", mm->user->user, mm->user->user);
  1490. else
  1491. dprintf(idx, "<td align=\"center\">-</td>");
  1492. } else {
  1493. if (m->user)
  1494. dprintf(idx, "<td align=\"center\"><a href=\"../users/%s/\">%s</a></td>", m->user->handle, m->user->handle);
  1495. else
  1496. dprintf(idx, "<td align=\"center\">-</td>");
  1497. }
  1498. if (chan_issplit(m))
  1499. dprintf(idx, "<td align=\"right\">%s</td>", SLNETSPLITTED);
  1500. else if (!rfc_casecmp(m->nick, botname))
  1501. dprintf(idx, "<td align=\"right\">%s</td>", SLITSME);
  1502. else
  1503. dprintf(idx, "<td align=\"right\">&nbsp;%s</td>", stats_duration(now - m->last));
  1504. dprintf(idx, "</tr>\n");
  1505. }
  1506. dprintf(idx, "</table></center>\n<br><br>");
  1507. }
  1508. dprintf(idx, "<table width=100%% border=0>\n");
  1509. dprintf(idx, "<tr><td align=center><table width=100%% border=0><tr>\n");
  1510. dprintf(idx, "<td width=25%% align=center><font size=-1><a href=\"../top/total/words/\">top%d</a></font></td>\n", webnr);
  1511. dprintf(idx, "<td width=25%% align=center><font size=-1><%sa href=\"../users/\">%s</a></font></td>\n",
  1512. ISLINK(show_userlist), ISTEXT(show_userlist, SLUSERS));
  1513. dprintf(idx, "<td width=25%% align=center><font size=-1><a href=\"../misc/\">%s</a></font></td>\n", SLMISCSTATS);
  1514. dprintf(idx, "<td width=25%% align=center><font size=-1><a href=\"../../\">%s</a></font></td>\n", SLOTHERCHANS);
  1515. dprintf(idx, "</tr></table></td></tr>\n");
  1516. dprintf(idx, "</table>\n");
  1517. dprintf(idx, "<center>Created by <a href=\"http://www.visions-of-fantasy.de/stats.mod/\">Stats.mod v%s</a></center></body></html>", MODULE_VERSION);
  1518. long_dprintf(idx, SLFOOTER);
  1519. dprintf(idx, "</body></html>");
  1520. }