livestats.c 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594
  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. #if EGG_IS_MIN_VER(10800)
  300. int i, j = 0;
  301. sockname_t name;
  302. unsigned short port;
  303. Context;
  304. if (dcc_total + 1 >= max_dcc) {
  305. j = answer(dcc[idx].sock, &name, &port, 0);
  306. if (j != -1) {
  307. dprintf(-j, "Sorry, too many connections already.\r\n");
  308. killsock(j);
  309. }
  310. return;
  311. }
  312. if ((i = new_dcc(&LIVESTATS, sizeof(struct stats_clientinfo))) == (-1)) {
  313. putlog(LOG_MISC, "*", "Error accepting livestats connection. DCC table is full.");
  314. return;
  315. }
  316. dcc[i].sock = answer(dcc[idx].sock, &dcc[i].sockname,
  317. (short unsigned *) &dcc[i].port, 0);
  318. if (dcc[i].sock < 0) {
  319. putlog(LOG_MISC, "*", "Stats.mod: Error accepting livestats connection: %s", strerror(errno));
  320. lostdcc(i);
  321. return;
  322. }
  323. strcpy(dcc[i].nick, "httpstats");
  324. strcpy(dcc[i].host, iptostr(&dcc[idx].sockname.addr.sa));
  325. dcc[i].timeval = now;
  326. dcc[i].status = 0;
  327. ((struct stats_clientinfo *) dcc[i].u.other)->traffic = 0;
  328. ((struct stats_clientinfo *) dcc[i].u.other)->code = 200;
  329. ((struct stats_clientinfo *) dcc[i].u.other)->browser = NULL;
  330. ((struct stats_clientinfo *) dcc[i].u.other)->referer = NULL;
  331. ((struct stats_clientinfo *) dcc[i].u.other)->cmd = NULL;
  332. #else
  333. unsigned long ip;
  334. unsigned short port;
  335. int j = 0, sock, i;
  336. char s[UHOSTLEN];
  337. Context;
  338. if (dcc_total + 1 >= max_dcc) {
  339. j = answer(dcc[idx].sock, s, &ip, &port, 0);
  340. if (j != -1) {
  341. dprintf(-j, "Sorry, too many connections already.\r\n");
  342. killsock(j);
  343. }
  344. return;
  345. }
  346. sock = answer(dcc[idx].sock, s, &ip, &port, 0);
  347. if (sock < 0) {
  348. neterror(s);
  349. putlog(LOG_MISC, "*", "Stats.mod: Error accepting livestats connection: %s", s);
  350. return;
  351. }
  352. if ((i = new_dcc(&LIVESTATS, sizeof(struct stats_clientinfo))) == (-1)) {
  353. putlog(LOG_MISC, "*", "Error accepting livestats connection. DCC table is full.");
  354. killsock(sock);
  355. return;
  356. }
  357. dcc[i].sock = sock;
  358. dcc[i].addr = ip;
  359. dcc[i].port = port;
  360. strcpy(dcc[i].nick, "httpstats");
  361. #ifndef OLDBOT
  362. sprintf(s, "%s", iptostr(my_htonl(ip)));
  363. #else
  364. sprintf(s, "%lu.%lu.%lu.%lu", (ip >> 24) & 0xff, (ip >> 16) & 0xff,
  365. (ip >> 8) & 0xff, ip & 0xff); /* dw */
  366. #endif
  367. strcpy(dcc[i].host, s);
  368. dcc[i].timeval = now;
  369. dcc[i].status = 0;
  370. ((struct stats_clientinfo *) dcc[i].u.other)->traffic = 0;
  371. ((struct stats_clientinfo *) dcc[i].u.other)->code = 200;
  372. ((struct stats_clientinfo *) dcc[i].u.other)->browser = NULL;
  373. ((struct stats_clientinfo *) dcc[i].u.other)->referer = NULL;
  374. ((struct stats_clientinfo *) dcc[i].u.other)->cmd = NULL;
  375. #endif
  376. }
  377. static int mlstat_time = 0, mlstat_thr = 0;
  378. static int livestats_flood()
  379. {
  380. if (!maxlivestats_thr || !maxlivestats_time)
  381. return 0;
  382. if ((now - mlstat_time) > maxlivestats_time) {
  383. mlstat_time = now;
  384. mlstat_thr = 0;
  385. }
  386. mlstat_thr++;
  387. if (mlstat_thr > maxlivestats_thr)
  388. return 1;
  389. return 0;
  390. }
  391. static void eof_livestats(int idx)
  392. {
  393. debug0("eof accept");
  394. killsock(dcc[idx].sock);
  395. lostdcc(idx);
  396. }
  397. static void send_livestats(int idx, char *buf)
  398. {
  399. char *channel, *command;
  400. char what[512], *pwhat, *type, *stoday, *user, prefix[4];
  401. struct chanset_t *chan;
  402. int today = 0;
  403. globstats *gs;
  404. locstats *ls, *ls2;
  405. time_t tt, ttbuf;
  406. struct userrec *u;
  407. int itype, nr, i, ii;
  408. wordstats *ws;
  409. quotestr *qs;
  410. unsigned long x;
  411. int wert;
  412. float r, g, b;
  413. float r2, g2, b2;
  414. float rstep, gstep, bstep;
  415. struct stats_userlist *suser;
  416. ttbuf = now;
  417. tt = now;
  418. if (!strcmp(buf, "/")) {
  419. setslglobs(NULL, 0, 0, 0);
  420. dprintf(idx, "<html><head><title>%s</title>\n%s\n</head>\n", ROOTTITLE, SLCSS);
  421. dprintf(idx, "%s\n", SLBODYTAG);
  422. long_dprintf(idx, SLHEADER);
  423. dprintf(idx, "<br><br><br><table border=1 width=100%%>\n");
  424. for (gs = sdata; gs; gs = gs->next) {
  425. if (!inactivechan(gs->chan) && !secretchan(gs->chan) && !nostats(gs->chan)) {
  426. if (gs->chan[0] == '!')
  427. strcpy(prefix, "!");
  428. else if (gs->chan[0] == '+')
  429. strcpy(prefix, "+");
  430. else if (gs->chan[0] == '&')
  431. strcpy(prefix, "&");
  432. else
  433. prefix[0] = 0;
  434. #ifndef OLDBOT
  435. chan = findchan_by_dname(gs->chan);
  436. #else
  437. chan = findchan(gs->chan);
  438. #endif
  439. i = 7;
  440. if (!show_userlist)
  441. i--;
  442. if (!show_usersonchan)
  443. i--;
  444. dprintf(idx, "<tr><td rowspan=%d align=center width=50%%>", i);
  445. if (chan && chan->channel.topic)
  446. dprintf(idx, "<a href=\"%s%s/\">%s</a><br><font size=-1>(%s)</font></td>",
  447. prefix, gs->chan + 1, gs->chan, filt2(chan->channel.topic));
  448. else
  449. dprintf(idx, "<a href=\"%s%s/\">%s</a></td>",
  450. prefix, gs->chan + 1, gs->chan);
  451. dprintf(idx, "<td rowspan=4 align=center>%s</td>", SLTOP);
  452. setslglobs(gs->chan, gs->peak[S_TOTAL], countstatmembers(gs), gs->started);
  453. dprintf(idx, "<td align=center><a href=\"%s%s/top/total/words/\">%s</a></td>",
  454. prefix, gs->chan + 1, SLTOTAL);
  455. dprintf(idx, "</tr>\n<tr>");
  456. dprintf(idx, "<td align=center><a href=\"%s%s/top/daily/words/\">%s</a></td>",
  457. prefix, gs->chan + 1, SLDAILY);
  458. dprintf(idx, "</tr>\n<tr>");
  459. dprintf(idx, "<td align=center><a href=\"%s%s/top/weekly/words/\">%s</a></td>",
  460. prefix, gs->chan + 1, SLWEEKLY);
  461. dprintf(idx, "</tr>\n<tr>");
  462. dprintf(idx, "<td align=center><a href=\"%s%s/top/monthly/words/\">%s</a></td>",
  463. prefix, gs->chan + 1, SLMONTHLY);
  464. dprintf(idx, "</tr>\n");
  465. if (show_userlist)
  466. dprintf(idx, "<tr><td align=center colspan=2><a href=\"%s%s/users/\">%s</a></td></tr>",
  467. prefix, gs->chan + 1, SLUSERS);
  468. if (show_usersonchan)
  469. dprintf(idx, "<tr><td align=center colspan=2><a href=\"%s%s/onchan/\">%s</a></td></tr>",
  470. prefix, gs->chan + 1, SLONCHAN);
  471. dprintf(idx, "<tr><td align=center colspan=2><a href=\"%s%s/misc/\">%s</a></td>",
  472. prefix, gs->chan + 1, SLMISCSTATS);
  473. dprintf(idx, "</tr><tr><td colspan=3 height=0><font size=-5>&nbsp;</font></td></tr>\n");
  474. }
  475. }
  476. dprintf(idx, "<tr><th colspan=3 align=center>");
  477. dprintf(idx, "<a href=\"http://www.kreativrauschen.de/stats.mod/\">");
  478. dprintf(idx, "Stats.mod v%s</a></th></tr></table>\n", MODULE_VERSION);
  479. long_dprintf(idx, SLFOOTER);
  480. dprintf(idx, "</body></html>\n");
  481. return;
  482. }
  483. if (buf[0] == '/') {
  484. if (!strncasecmp(buf, "/e/", 3)) {
  485. buf += 2;
  486. buf[0] = '!';
  487. } else if (!strncasecmp(buf, "/p/", 3)) {
  488. buf += 2;
  489. buf[0] = '+';
  490. } else if (!strncasecmp(buf, "/a/", 3)) {
  491. buf += 2;
  492. buf[0] = '&';
  493. } else if (buf[1] && strchr("+&!", buf[1]))
  494. buf++;
  495. else
  496. buf[0] = '#';
  497. }
  498. if (buf[strlen(buf) - 1] == '/')
  499. buf[strlen(buf) - 1] = 0;
  500. channel = splitpath(&buf);
  501. #ifndef OLDBOT
  502. chan = findchan_by_dname(channel);
  503. #else
  504. chan = findchan(channel);
  505. #endif
  506. if (!chan) {
  507. dprintf(idx, "no such channel %s", channel);
  508. if (idx >= 0)
  509. stats_info_access(idx)->code = 404;
  510. return;
  511. }
  512. gs = findglobstats(channel);
  513. if (gs)
  514. setslglobs(gs->chan, gs->peak[S_TOTAL], countstatmembers(gs), gs->started);
  515. else
  516. setslglobs(channel, 0, 0, 0);
  517. if (!strcmp(buf, "/") || !buf[0]) {
  518. dprintf(idx, "<html><head><title>%s</title>\n%s\n</head>%s", SLINDEXTITEL, SLCSS, SLBODYTAG);
  519. long_dprintf(idx, SLHEADER);
  520. dprintf(idx, "<br><br><br><center>\n");
  521. dprintf(idx, "<table border=1 width=50%%>\n");
  522. dprintf(idx, "<tr><th colspan=2><font size=+2>%s</font></th></tr>", channel);
  523. dprintf(idx, "<tr><td rowspan=4 align=center>%s</td>", SLTOP);
  524. dprintf(idx, "<td align=center><a href=\"top/total/words/\">%s</a></td>", SLTOTAL);
  525. dprintf(idx, "</tr>\n<tr>");
  526. dprintf(idx, "<td align=center><a href=\"top/daily/words/\">%s</a></td>", SLDAILY);
  527. dprintf(idx, "</tr>\n<tr>");
  528. dprintf(idx, "<td align=center><a href=\"top/weekly/words/\">%s</a></td>", SLWEEKLY);
  529. dprintf(idx, "</tr>\n<tr>");
  530. dprintf(idx, "<td align=center><a href=\"top/monthly/words/\">%s</a></td>", SLMONTHLY);
  531. dprintf(idx, "</tr>\n");
  532. if (show_userlist)
  533. dprintf(idx, "<tr><td align=center colspan=2><a href=\"users/\">%s</a></td></tr>", SLUSERS);
  534. if (show_usersonchan)
  535. dprintf(idx, "<tr><td align=center colspan=2><a href=\"onchan/\">%s</a></td></tr>", SLONCHAN);
  536. dprintf(idx, "<tr><td align=center colspan=2><a href=\"misc/\">%s</a></td></tr>", SLMISCSTATS);
  537. dprintf(idx, "<tr><td colspan=2 height=0><font size=-5>&nbsp;</font></td></tr>\n");
  538. dprintf(idx, "<tr><th colspan=2 align=center><font size=-2>");
  539. dprintf(idx, "<a href=\"http://www.kreativrauschen.de/stats.mod/\">");
  540. dprintf(idx, "Stats.mod v%s</a></font></th></tr></table>\n", MODULE_VERSION);
  541. dprintf(idx, "</center>\n");
  542. long_dprintf(idx, SLFOOTER);
  543. dprintf(idx, "</body></html>\n");
  544. return;
  545. }
  546. command = splitpath(&buf);
  547. if (!strcasecmp(command, "top")) {
  548. if (!strcmp(buf, "/") || !buf[0]) {
  549. dprintf(idx, "<html><body><table>");
  550. dprintf(idx, "<tr><td><a href=\"total/\">total</a></td></tr>");
  551. dprintf(idx, "<tr><td><a href=\"today/\">today</a></td></tr>");
  552. dprintf(idx, "</table></body></html>");
  553. return;
  554. }
  555. stoday = splitpath(&buf);
  556. if (!strcasecmp(stoday, "today") || !strcasecmp(stoday, "daily"))
  557. today = S_DAILY;
  558. else if (!strcasecmp(stoday, "weekly"))
  559. today = S_WEEKLY;
  560. else if (!strcasecmp(stoday, "monthly"))
  561. today = S_MONTHLY;
  562. else if (!strcasecmp(stoday, "total"))
  563. today = 0;
  564. else {
  565. dprintf(idx, "<html><body>Error, invalid value %s<table>", stoday);
  566. dprintf(idx, "<tr><td><a href=\"../total/\">total</a></td></tr>");
  567. dprintf(idx, "<tr><td><a href=\"../daily/\">daily</a></td></tr>");
  568. dprintf(idx, "<tr><td><a href=\"../weekly/\">weekly</a></td></tr>");
  569. dprintf(idx, "<tr><td><a href=\"../monthly/\">monthly</a></td></tr>");
  570. dprintf(idx, "</table></body></html>");
  571. Assert(idx >= 0);
  572. stats_info_access(idx)->code = 404;
  573. return;
  574. }
  575. if (!strcmp(buf, "/") || !buf[0]) {
  576. dprintf(idx, "<html><body><table>");
  577. sprintf(what, "%s", webstats);
  578. pwhat = what;
  579. while (strlen(pwhat) > 0) {
  580. type = newsplit(&pwhat);
  581. itype = typetoi(type);
  582. if (itype >= 0) {
  583. dprintf(idx, "<tr><td><a href=\"%s/\">%s</a></td></tr>", type, type);
  584. }
  585. }
  586. dprintf(idx, "</table></body></html>");
  587. return;
  588. }
  589. gs = findglobstats(channel);
  590. if (!gs) {
  591. debug1("Error! Can't find global stats for %s", channel);
  592. dprintf(idx, "<html><body>Error! Can't find global stats for %s</body></html>", channel);
  593. if (idx >= 0)
  594. stats_info_access(idx)->code = 404;
  595. return;
  596. }
  597. if (!strncasecmp(buf, "graph", 5)) {
  598. do_graphs(idx, today, gs, channel);
  599. return;
  600. }
  601. do_toptalkers(idx, today, gs, channel, buf);
  602. return;
  603. } else if (!strcasecmp(command, "onchan")) {
  604. display_users_on_chan(idx, channel, chan);
  605. } else if (!strcasecmp(command, "users")) {
  606. gs = findglobstats(channel);
  607. if (!gs) {
  608. debug1("Error! Can't find global stats for %s", channel);
  609. dprintf(idx, "<html><body>Error! Can't find global stats for %s</body></html>", channel);
  610. return;
  611. }
  612. setslglobs(gs->chan, gs->peak[S_TOTAL], countstatmembers(gs), gs->started);
  613. if (!strcmp(buf, "/") || !buf[0]) {
  614. if (!show_userlist)
  615. return;
  616. sort_stats_alphabetically(gs);
  617. dprintf(idx, "<html><head><title>%s</title>\n%s\n</head>%s",
  618. SLUSERSTITLE, SLCSS, SLBODYTAG);
  619. long_dprintf(idx, SLHEADER);
  620. dprintf(idx, "<center>\n");
  621. dprintf(idx, "<table border=%d>\n<tr><th>User</th><th>Info</th></tr>\n", table_border);
  622. i = 0;
  623. for (ls = gs->local; ls; ls = ls->next)
  624. i++;
  625. wert = table_color;
  626. b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16;
  627. wert = fade_table_to;
  628. b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16;
  629. rstep = (r2 - r) / i;
  630. gstep = (g2 - g) / i;
  631. bstep = (b2 - b) / i;
  632. for (ls = gs->local; ls; ls = ls->next) {
  633. u = get_user_by_handle(userlist, ls->user);
  634. what[0] = 0;
  635. get_handle_chaninfo(ls->user, channel, what);
  636. pwhat = what;
  637. if (!what[0])
  638. pwhat = get_user(&USERENTRY_INFO, u);
  639. if (!pwhat) {
  640. sprintf(what, "&nbsp;");
  641. pwhat = what;
  642. }
  643. dprintf(idx, "<tr bgcolor=#%02x%02x%02x><td><a href=\"%s/\">%s</a></td><td>%s</td></tr>\n",
  644. (int) r, (int) g, (int) b, ls->user, ls->user, filt2(pwhat));
  645. r += rstep;
  646. g += gstep;
  647. b += bstep;
  648. }
  649. /*
  650. * dprintf(idx, "<tr><td colspan=2 align=center><a href=\"http://www.kreativrauschen.de/stats.mod/\">");
  651. * dprintf(idx, "Stats.mod v%s</a></td></tr></table>\n", MODULE_VERSION);
  652. */
  653. dprintf(idx, "</table>\n");
  654. dprintf(idx, "<br><br><hr>\n");
  655. dprintf(idx, "<table width=100%% border=0>\n");
  656. dprintf(idx, "<tr><td align=center><table width=100%% border=0><tr>\n");
  657. dprintf(idx, "<td width=25%% align=center><font size=-1><%sa "
  658. "href=\"../onchan/\">%s</a></font></td>\n",
  659. ISLINK(show_usersonchan), ISTEXT(show_usersonchan, SLONCHAN));
  660. dprintf(idx, "<td width=25%% align=center><font size=-1><a href=\"../top/total/words/\">top%d</a></font></td>\n", webnr);
  661. dprintf(idx, "<td width=25%% align=center><font size=-1><a href=\"../misc/\">%s</a></font></td>\n", SLMISCSTATS);
  662. dprintf(idx, "<td width=25%% align=center><font size=-1><a href=\"../../\">%s</a></font></td>\n", SLOTHERCHANS);
  663. dprintf(idx, "</tr></table></td></tr>\n");
  664. dprintf(idx, "</table>\n");
  665. dprintf(idx, "<center>Created by <a href=\"http://www.kreativrauschen.de/stats.mod/\">Stats.mod v%s</a></center></body></html>", MODULE_VERSION);
  666. dprintf(idx, "</center>\n");
  667. long_dprintf(idx, SLFOOTER);
  668. dprintf(idx, "</body></html>");
  669. return;
  670. }
  671. user = buf;
  672. ls = findlocstats(channel, user);
  673. if (!ls) {
  674. debug2("Error! Can't find local stats for %s in %s", user, channel);
  675. dprintf(idx, "<html><body>I don't have any stats for %s in %s, sorry</body></html>", user, channel);
  676. if (idx >= 0)
  677. stats_info_access(idx)->code = 404;
  678. return;
  679. }
  680. i = countwords(webstats) + 2;
  681. suser = findsuser_by_name(user);
  682. dprintf(idx, "<html><head><META http-equiv=\"Pragma\" content=\"no-cache\"><META http-equiv=\"Expires\" content=\"now\">\n");
  683. slgloblocstats = ls;
  684. dprintf(idx, "<title>%s</title>\n%s\n</head>%s\n", SLUSERTITLE, SLCSS, SLBODYTAG);
  685. long_dprintf(idx, SLHEADER);
  686. dprintf(idx, "<center>\n");
  687. dprintf(idx, "%s\n", SLUSERHEAD);
  688. if (suser) {
  689. dprintf(idx, "<center>");
  690. if (suser->email)
  691. dprintf(idx, "<a href=\"mailto:%s\" target=\"_new\">%s</a><br>", suser->email, SLEMAIL);
  692. if (suser->homepage)
  693. dprintf(idx, "<a href=\"%s\" target=\"_new\">%s</a><br>", suser->homepage, SLHOMEPAGE);
  694. dprintf(idx, "</center><br>");
  695. }
  696. dprintf(idx, "<table border=%d><tr><td></td><td>%s</td>", table_border, SLPLACE);
  697. sprintf(what, "%s", webstats);
  698. pwhat = what;
  699. while (strlen(pwhat) > 0) {
  700. dprintf(idx, "<td>%s</td>", getslangtype(newsplit(&pwhat)));
  701. }
  702. dprintf(idx, "</tr>\n");
  703. wert = table_color;
  704. b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16;
  705. wert = fade_table_to;
  706. b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16;
  707. rstep = (r2 - r) / 4;
  708. gstep = (g2 - g) / 4;
  709. bstep = (b2 - b) / 4;
  710. for (today = 0; today < 4; today++) {
  711. dprintf(idx, "<tr><td align=center>%s</td>", RANGESTR_LONG);
  712. nr = 0;
  713. if (ls->values[today][T_WORDS] > 0) {
  714. sortstats(gs, T_WORDS, today);
  715. for (ls2 = gs->slocal[today][T_WORDS]; ls2; ls2 = ls2->snext[today][T_WORDS]) {
  716. nr++;
  717. if (!strcasecmp(ls2->user, user))
  718. break;
  719. }
  720. }
  721. dprintf(idx, "<td bgcolor=#%02x%02x%02x align=\"right\">\n", (int) r, (int) g, (int) b);
  722. if (nr == 0)
  723. dprintf(idx, "-</td>");
  724. else
  725. dprintf(idx, "%d</td>", nr);
  726. sprintf(what, "%s", webstats);
  727. pwhat = what;
  728. while (strlen(pwhat) > 0) {
  729. itype = typetoi(newsplit(&pwhat));
  730. dprintf(idx, "<td bgcolor=#%02x%02x%02x align=\"right\">\n", (int) r, (int) g, (int) b);
  731. if (itype == T_MINUTES)
  732. dprintf(idx, "%s</td>", stats_duration(ls->values[today][itype] * 60));
  733. else if (itype >= 0)
  734. dprintf(idx, "%d</td>", ls->values[today][itype]);
  735. else if (itype == T_WPL) {
  736. if (ls->values[today][T_LINES])
  737. dprintf(idx, "%.2f</td>", (float) ls->values[today][T_WORDS] / (float) ls->values[today][T_LINES]);
  738. else
  739. dprintf(idx, "0</td>");
  740. } else if (itype == T_IDLE) {
  741. if (ls->values[today][T_LINES])
  742. dprintf(idx, "%.2f</td>", (float) ls->values[today][T_MINUTES] / (float) ls->values[today][T_LINES]);
  743. else
  744. dprintf(idx, "0</td>");
  745. } else
  746. dprintf(idx, "ERR!</td>");
  747. }
  748. dprintf(idx, "</tr>\n");
  749. r += rstep;
  750. g += gstep;
  751. b += bstep;
  752. }
  753. if (ls->quotes && quote_freq) {
  754. nr = 0;
  755. for (qs = ls->quotes; qs; qs = qs->next)
  756. nr++;
  757. x = random() % nr;
  758. ii = 0;
  759. qs = ls->quotes;
  760. while (qs) {
  761. if (ii == x) {
  762. dprintf(idx, "<tr><td colspan=%d align=center>", i);
  763. dprintf(idx, SLRANDQUOTE, filt2(qs->quote));
  764. dprintf(idx, "</td></tr>\n");
  765. break;
  766. }
  767. qs = qs->next;
  768. ii++;
  769. }
  770. }
  771. dprintf(idx, "</table></center>\n");
  772. if (ls->words) {
  773. if (ls->words) {
  774. nr = 0;
  775. for (ws = ls->words; ws; ws = ws->next)
  776. nr++;
  777. slglobint = nr;
  778. dprintf(idx, "<center><br><br>%s<br>\n", SLUWORDSTATS);
  779. sortwordstats(ls, NULL);
  780. dprintf(idx, "<table>\n");
  781. nr = 0;
  782. ws = ls->words;
  783. while (ws && (nr < 10)) {
  784. nr++;
  785. dprintf(idx, "<tr><td>%d.</td><td>%s</td><td>(%d)</td></tr>\n", nr, filt2(ws->word), ws->nr);
  786. ws = ws->next;
  787. }
  788. dprintf(idx, "</table><br><br></center>\n");
  789. }
  790. }
  791. dprintf(idx, "<br><br><hr>\n");
  792. dprintf(idx, "<table width=100%% border=0>\n");
  793. dprintf(idx, "<tr><td align=center><table width=100%% border=0><tr>\n");
  794. dprintf(idx, "<td width=20%% align=center><font size=-1><%sa href=\"../\">%s</a></font></td>\n",
  795. ISLINK(show_usersonchan), ISTEXT(show_usersonchan, SLOTHERUSERS));
  796. dprintf(idx, "<td width=20%% align=center><font size=-1><%sa href=\"../../onchan\">%s</a></font></td>\n",
  797. ISLINK(show_usersonchan), ISTEXT(show_usersonchan, SLONCHAN));
  798. dprintf(idx, "<td width=20%% align=center><font size=-1><a href=\"../../top/total/words/\">%s</a></font></td>\n", SLTOP);
  799. dprintf(idx, "<td width=20%% align=center><font size=-1><a href=\"../../misc/\">%s</a></font></td>\n", SLMISCSTATS);
  800. dprintf(idx, "<td width=20%% align=center><font size=-1><a href=\"../../../\">%s</a></font></td>\n", SLOTHERCHANS);
  801. dprintf(idx, "</tr></table></td></tr>\n");
  802. dprintf(idx, "</table>\n");
  803. dprintf(idx, "<center>Created by <a href=\"http://www.kreativrauschen.de/stats.mod/\">Stats.mod v%s</a></center></body></html>", MODULE_VERSION);
  804. long_dprintf(idx, SLFOOTER);
  805. dprintf(idx, "</body></html>");
  806. return;
  807. } else if (!strcasecmp(command, "misc")) {
  808. do_miscstats(idx, channel);
  809. return;
  810. } else {
  811. dprintf(idx, "<html><body>Error! unknown command %s</body></html>", command);
  812. if (idx >= 0)
  813. stats_info_access(idx)->code = 404;
  814. return;
  815. }
  816. }
  817. static void do_graphs(int idx, int today, globstats *gs, char *channel)
  818. {
  819. int itype, nr;
  820. int total, rest, width, max;
  821. float onep, percent, wpercent;
  822. char bground[140];
  823. locstats *ls;
  824. char what[512], *pwhat, *type;
  825. Context;
  826. setslglobs(gs->chan, gs->peak[S_TOTAL], countstatmembers(gs), gs->started);
  827. if (graphgif[0] == 0)
  828. bground[0] = 0;
  829. else
  830. sprintf(bground, "background=\"%s\"", graphgif);
  831. dprintf(idx, "<!-- Created by Stats.mod v%s-->\n", MODULE_VERSION);
  832. dprintf(idx, "<html><head><META http-equiv=\"Pragma\" content=\"no-cache\"><META http-equiv=\"Expires\" content=\"now\">\n");
  833. if (today == 0)
  834. dprintf(idx, "<title>%s</title>\n", SLGRTTITLE);
  835. else if (today == 1)
  836. dprintf(idx, "<title>%s</title>\n", SLGRDTITLE);
  837. else if (today == 2)
  838. dprintf(idx, "<title>%s</title>\n", SLGRWTITLE);
  839. else if (today == 3)
  840. dprintf(idx, "<title>%s</title>\n", SLGRMTITLE);
  841. dprintf(idx, "%s\n</head>%s\n", SLCSS, SLBODYTAG);
  842. long_dprintf(idx, SLHEADER);
  843. if (today == 0)
  844. dprintf(idx, "%s", SLGRTHEAD);
  845. else if (today == 1)
  846. dprintf(idx, "%s", SLGRDHEAD);
  847. else if (today == 2)
  848. dprintf(idx, "%s", SLGRWHEAD);
  849. else if (today == 3)
  850. dprintf(idx, "%s", SLGRMHEAD);
  851. sprintf(what, "%s", graphstats);
  852. pwhat = what;
  853. while (strlen(pwhat) > 0) {
  854. type = newsplit(&pwhat);
  855. itype = typetoi(type);
  856. if (itype < 0) {
  857. putlog(LOG_MISC, "*", "Stats.mod: Error serving livestats. Unsupported type %s. Skipping.", type);
  858. continue;
  859. }
  860. sortstats(gs, itype, today);
  861. max = 0;
  862. for (ls = gs->slocal[today][itype]; ls; ls = ls->snext[today][itype]) {
  863. if (listsuser(ls, channel)) {
  864. max = ls->values[today][itype];
  865. break;
  866. }
  867. }
  868. if (max == 0)
  869. continue;
  870. total = gettotal(gs, itype, today);
  871. rest = total;
  872. dprintf(idx, "<br><br><br><table width=100%% border=1><tr><th width=100%% align=center>");
  873. dprintf(idx, SLGRORDEREDBY, getslangtype(type));
  874. dprintf(idx, "</td></tr></table>\n");
  875. slglobint = total;
  876. dprintf(idx, SLGRTOTAL, getslangtype(type));
  877. dprintf(idx, "<br>\n");
  878. dprintf(idx, "<table width=100%%>\n");
  879. if (!total || !max)
  880. continue;
  881. onep = (float) total / 100.0;
  882. nr = 0;
  883. for (ls = gs->slocal[today][itype]; ls; ls = ls->snext[today][itype]) {
  884. if (!listsuser(ls, channel))
  885. continue;
  886. if (!ls->values[today][itype])
  887. break;
  888. nr++;
  889. if (nr > graphnr)
  890. break;
  891. dprintf(idx, "<tr>\n");
  892. percent = (float) ls->values[today][itype] / onep;
  893. wpercent = (float) ls->values[today][itype] / ((float) max / 100.0);
  894. width = (int) wpercent * 0.8;
  895. dprintf(idx, " <td align=right width=10%%><a href=\"../../../users/%s/\">%s</a></td>\n", ls->user, ls->user);
  896. dprintf(idx, " <td align=left width=90%%>\n");
  897. dprintf(idx, " <table width=100%%><tr>\n");
  898. dprintf(idx, " <td width=%d%% bgcolor=\"%s\" %s>&nbsp;</td>\n", width, graphcolor, bground);
  899. dprintf(idx, " <td align=left width=%d%%>%.2f%% <font size=-2>[%d]</font></td>\n", 100 - width, percent, ls->values[today][itype]);
  900. dprintf(idx, " </tr></table>\n");
  901. dprintf(idx, " </td>\n");
  902. dprintf(idx, "</tr>\n");
  903. rest -= ls->values[today][itype];
  904. }
  905. dprintf(idx, "<tr>\n");
  906. percent = (float) rest / ((float) total / 100.0);
  907. wpercent = (float) rest / ((float) max / 100.0);
  908. width = (int) wpercent * 0.8;
  909. dprintf(idx, " <td align=right width=10%%>%s</td>\n", SLGROTHERS);
  910. dprintf(idx, " <td align=left width=90%%>\n");
  911. dprintf(idx, " <table width=100%%><tr>\n");
  912. dprintf(idx, " <td width=%d%% bgcolor=\"%s\" %s>&nbsp;</td>\n", width, graphcolor, bground);
  913. dprintf(idx, " <td align=left width=%d%%>%.2f%% <font size=-2>[%d]</font></td>\n", 100 - width, percent, rest);
  914. dprintf(idx, " </tr></table>\n");
  915. dprintf(idx, " </td>\n");
  916. dprintf(idx, "</tr></table>\n");
  917. }
  918. dprintf(idx, "</table>\n");
  919. dprintf(idx, "<br><hr><br>\n");
  920. dprintf(idx, "<table width=100%% border=0>\n");
  921. dprintf(idx, "<tr><td width=25%% align=center><a href=\"../words/\">%s</a></td></tr>\n", SLGRTABLE);
  922. dprintf(idx, "<tr><td align=center><table width=100%% border=0><tr>\n");
  923. dprintf(idx, "<td width=25%% align=center><a href=\"../../total/graphs/\">%s</a></td>\n", SLTOTAL);
  924. dprintf(idx, "<td width=25%% align=center><a href=\"../../daily/graphs/\">%s</a></td>\n", SLDAILY);
  925. dprintf(idx, "<td width=25%% align=center><a href=\"../../weekly/graphs/\">%s</a></td>\n", SLWEEKLY);
  926. dprintf(idx, "<td width=25%% align=center><a href=\"../../monthly/graphs/\">%s</a></td>\n", SLMONTHLY);
  927. dprintf(idx, "</tr></table></td></tr>\n");
  928. dprintf(idx, "<tr><td align=center><table width=100%% border=0><tr>\n");
  929. dprintf(idx, "<td width=25%% align=center><a href=\"../../../misc/\">%s</a></td>\n", SLMISCSTATS);
  930. dprintf(idx, "<td width=25%% align=center><%sa href=\"../../../users/\">%s</a></td>\n",
  931. ISLINK(show_userlist), ISTEXT(show_userlist, SLUSERS));
  932. dprintf(idx, "<td width=25%% align=center><%sa href=\"../../../onchan/\">%s</a></td>\n",
  933. ISLINK(show_usersonchan), ISTEXT(show_usersonchan, SLONCHAN));
  934. dprintf(idx, "<td width=25%% align=center><a href=\"../../../../\">%s</a></td>\n", SLOTHERCHANS);
  935. dprintf(idx, "</tr></table></td></tr>\n");
  936. dprintf(idx, "</table>\n");
  937. dprintf(idx, "<br><center>Created by "
  938. "<a href=\"http://www.kreativrauschen.de/stats.mod/\">Stats.mod "
  939. "v%s</a></center>\n", MODULE_VERSION);
  940. long_dprintf(idx, SLFOOTER);
  941. dprintf(idx, "</body></html>");
  942. return;
  943. }
  944. static void do_toptalkers(int idx, int today, globstats *gs, char *channel, char *buf)
  945. {
  946. char what2[512], *pwhat2, *type, *type2;
  947. locstats *ls;
  948. int itype, itype2, pitype, nr, i;
  949. int wert;
  950. float r, g, b;
  951. float r2, g2, b2;
  952. float rstep, gstep, bstep;
  953. quotestr *q;
  954. unsigned long x;
  955. Context;
  956. setslglobs(channel, gs->peak[today], countstatmembers(gs), gs->started);
  957. type = buf;
  958. itype = typetoi(type);
  959. if (itype == T_ERROR) {
  960. dprintf(idx, "<html><body>Error! No such type %s</body></html>", type);
  961. if (idx >= 0)
  962. stats_info_access(idx)->code = 404;
  963. return;
  964. }
  965. if (itype < 0)
  966. pitype = (itype * -1) + (TOTAL_TYPES - 1);
  967. else
  968. pitype = itype;
  969. dprintf(idx, "<html><head><META http-equiv=\"Pragma\" content=\"no-cache\"><META http-equiv=\"Expires\" content=\"now\">\n");
  970. if (today == 0)
  971. dprintf(idx, "<title>%s</title>\n", SLTTOPTITLE);
  972. else if (today == 1)
  973. dprintf(idx, "<title>%s</title>\n", SLDTOPTITLE);
  974. else if (today == 2)
  975. dprintf(idx, "<title>%s</title>\n", SLWTOPTITLE);
  976. else if (today == 3)
  977. dprintf(idx, "<title>%s</title>\n", SLMTOPTITLE);
  978. dprintf(idx, "<META Name=\"Stats.mod\" Content=\"%s\">\n", MODULE_VERSION);
  979. dprintf(idx, "<META Name=\"channel\" Content=\"%s\">\n", gs->chan);
  980. dprintf(idx, "<META Name=\"network\" Content=\"%s\">\n", network);
  981. dprintf(idx, "<META Name=\"written\" Content=\"%lu\">\n", now);
  982. dprintf(idx, "%s\n</head>\n", SLCSS);
  983. dprintf(idx, "%s", SLBODYTAG);
  984. long_dprintf(idx, SLHEADER);
  985. if (today == 0)
  986. dprintf(idx, "%s\n", SLTTOPHEAD);
  987. else if (today == 1)
  988. dprintf(idx, "%s\n", SLDTOPHEAD);
  989. else if (today == 2)
  990. dprintf(idx, "%s\n", SLWTOPHEAD);
  991. else if (today == 3)
  992. dprintf(idx, "%s\n", SLMTOPHEAD);
  993. dprintf(idx, SLORDEREDBY, getslangtype(type));
  994. dprintf(idx, "<BR>\n");
  995. dprintf(idx, SLPEAK);
  996. dprintf(idx, "<BR>\n");
  997. dprintf(idx, "<P><center><table border=%d cellpadding=1><tr align=right>", table_border);
  998. dprintf(idx, "<th>%s</th>", SLTNR);
  999. dprintf(idx, "<th align=center>Nick</th>");
  1000. sprintf(what2, "%s", webstats);
  1001. pwhat2 = what2;
  1002. while (strlen(pwhat2) > 0) {
  1003. type2 = newsplit(&pwhat2);
  1004. dprintf(idx, "<th><a href=\"../%s/\">%s</a></th>\n", type2, getslangtype(type2));
  1005. }
  1006. sortstats(gs, itype, today);
  1007. nr = 0;
  1008. wert = table_color;
  1009. b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16;
  1010. wert = fade_table_to;
  1011. b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16;
  1012. rstep = (r2 - r) / webnr;
  1013. gstep = (g2 - g) / webnr;
  1014. bstep = (b2 - b) / webnr;
  1015. for (ls = gs->slocal[today][pitype]; ls; ls = ls->snext[today][pitype]) {
  1016. if (!listsuser(ls, channel))
  1017. continue;
  1018. if ((itype >= 0) && !ls->values[today][itype])
  1019. break;
  1020. nr++;
  1021. if (nr > webnr)
  1022. break;
  1023. dprintf(idx, "<tr align=\"right\" bgcolor=#%02x%02x%02x><td>%d</td><td><a href=\"../../../users/%s/\">%s</a></td>",
  1024. (int) r, (int) g, (int) b, nr, ls->user, ls->user);
  1025. r += rstep;
  1026. g += gstep;
  1027. b += bstep;
  1028. sprintf(what2, "%s", webstats);
  1029. pwhat2 = what2;
  1030. while (strlen(pwhat2) > 0) {
  1031. type2 = newsplit(&pwhat2);
  1032. itype2 = typetoi(type2);
  1033. dprintf(idx, "<td>");
  1034. // mark the sorted value bold
  1035. if (itype == itype2)
  1036. dprintf(idx, "<b>");
  1037. // now output the values
  1038. // T_MINUTES gets a special handling, because it's kinda hard to read
  1039. // something like "2348 Minutes" *g*
  1040. if (itype2 == T_MINUTES)
  1041. dprintf(idx, "%s", stats_duration(ls->values[today][itype2] * 60));
  1042. // no positive type needs any special handling, so lt's just output it
  1043. else if (itype2 >= 0)
  1044. dprintf(idx, "%d", ls->values[today][itype2]);
  1045. // words per line need to be calculated
  1046. else if (itype2 == T_WPL) {
  1047. if (ls->values[today][T_LINES])
  1048. dprintf(idx, "%.2f", ((float) ls->values[today][T_WORDS]) / ((float) ls->values[today][T_LINES]));
  1049. else
  1050. dprintf(idx, "0");
  1051. // idle-factor also needs to be calculated
  1052. } else if (itype2 == T_IDLE) {
  1053. if (ls->values[today][T_LINES])
  1054. dprintf(idx, "%.2f", ((float) ls->values[today][T_MINUTES]) / ((float) ls->values[today][T_LINES]));
  1055. else
  1056. dprintf(idx, "0");
  1057. } else if (itype2 == T_QUOTE) {
  1058. if (!ls->quotes)
  1059. dprintf(idx, "&nbsp;");
  1060. else {
  1061. nr = 0;
  1062. for (q = ls->quotes; q; q = q->next)
  1063. nr++;
  1064. x = random() % nr;
  1065. i = 0;
  1066. q = ls->quotes;
  1067. while (q) {
  1068. if (i == x) {
  1069. dprintf(idx, "%s", filt2(q->quote));
  1070. break;
  1071. }
  1072. q = q->next;
  1073. i++;
  1074. }
  1075. }
  1076. } else // output an error, if we missed something
  1077. dprintf(idx, "ERROR! itype2: %d", itype2);
  1078. if (itype == itype2)
  1079. dprintf(idx, "</b>");
  1080. dprintf(idx, "</td>");
  1081. }
  1082. dprintf(idx, "</tr>\n");
  1083. }
  1084. dprintf(idx, "<tr>");
  1085. dprintf(idx, "<td colspan=%d align=center><b>", countwords(webstats) + 2);
  1086. dprintf(idx, SLTOTALUSERS);
  1087. dprintf(idx, "</B></td></tr>\n");
  1088. dprintf(idx, "<tr><td colspan=%d align=center>", countwords(webstats) + 2);
  1089. dprintf(idx, "<table width=100%% border=0>\n");
  1090. dprintf(idx, "<tr><td width=100%% align=center colspan=4><a href=\"../graphs/\">%s</a></td></tr>\n", SLGRAPHS);
  1091. dprintf(idx, "<tr><td width=25%% align=center><a href=\"../../total/%s/\">%s</a></td>\n", type, SLTOTAL);
  1092. dprintf(idx, "<td width=25%% align=center><a href=\"../../daily/%s/\">%s</a></td>\n", type, SLDAILY);
  1093. dprintf(idx, "<td width=25%% align=center><a href=\"../../weekly/%s/\">%s</a></td>\n", type, SLWEEKLY);
  1094. dprintf(idx, "<td width=25%% align=center><a href=\"../../monthly/%s/\">%s</a></td>\n", type, SLMONTHLY);
  1095. dprintf(idx, "</tr></table></td></tr>\n");
  1096. dprintf(idx, "<tr><td colspan=%d align=center><table width=100%% border=0><tr>\n", countwords(webstats) + 2);
  1097. dprintf(idx, "<td width=25%% align=center><a href=\"../../../misc/\">%s</a></td>\n", SLMISCSTATS);
  1098. dprintf(idx, "<td width=25%% align=center><%sa href=\"../../../users/\">%s</a></td>\n",
  1099. ISLINK(show_userlist), ISTEXT(show_userlist, SLUSERS));
  1100. dprintf(idx, "<td width=25%% align=center><%sa href=\"../../../onchan/\">%s</a></td>\n",
  1101. ISLINK(show_usersonchan), ISTEXT(show_usersonchan, SLONCHAN));
  1102. dprintf(idx, "<td width=25%% align=center><a href=\"../../../../\">%s</a></td>\n", SLOTHERCHANS);
  1103. dprintf(idx, "</tr>\n</table></td></tr>\n");
  1104. dprintf(idx, "</table><br>");
  1105. if (!today)
  1106. dprintf(idx, SLGSTARTED);
  1107. dprintf(idx, "<br><a href=\"http://www.kreativrauschen.de/stats.mod/\">Stats.mod v%s</a>.", MODULE_VERSION);
  1108. dprintf(idx, "</CENTER>\n");
  1109. long_dprintf(idx, SLFOOTER);
  1110. dprintf(idx, "</body></html>");
  1111. return;
  1112. }
  1113. static void do_miscstats(int idx, char *channel)
  1114. {
  1115. globstats *gs, *tlds, *isps;
  1116. wordstats *ws;
  1117. int nr, tr, i, wert, wieoft, pitype;
  1118. locstats *ls;
  1119. char *host, *s;
  1120. topicstr *t;
  1121. char ts[20];
  1122. float f, max, onep;
  1123. hoststr *h, *isp, *tld;
  1124. struct slang_lang *l;
  1125. struct slang_bntypes *ty;
  1126. struct slang_bnplaces *p;
  1127. struct slang_texts *txt;
  1128. unsigned long x;
  1129. float r, g, b;
  1130. float r2, g2, b2;
  1131. float rstep, gstep, bstep;
  1132. struct stats_url *url;
  1133. struct stats_kick *kick;
  1134. struct stats_quote *log;
  1135. Context;
  1136. gs = findglobstats(channel);
  1137. if (!gs) {
  1138. dprintf(idx, "<html><body>ERROR! Can't find stats for %s!</body></html>\n", channel);
  1139. return;
  1140. }
  1141. setslglobs(gs->chan, gs->peak[S_TOTAL], countstatmembers(gs), gs->started);
  1142. dprintf(idx, "<html><head><META http-equiv=\"Pragma\" content=\"no-cache\">"
  1143. "<META http-equiv=\"Expires\" content=\"now\"><title>%s</title>\n",
  1144. SLMISCTITLE);
  1145. long_dprintf(idx, SLCSS);
  1146. dprintf(idx, "</head>\n");
  1147. dprintf(idx, "%s\n", SLBODYTAG);
  1148. long_dprintf(idx, SLHEADER);
  1149. dprintf(idx, "%s<br>\n", SLMISCHEAD);
  1150. do_globwordstats(gs);
  1151. max = 0.0;
  1152. wert = nr = 0; /* I'm recycling these vars, so ignore the strange names */
  1153. for (i = 0; i < 24; i++) {
  1154. if (i < 12) {
  1155. if (gs->users[S_USERCOUNTS][i] > 0)
  1156. wert = 1;
  1157. } else {
  1158. if (gs->users[S_USERCOUNTS][i] > 0)
  1159. nr = 1;
  1160. }
  1161. if (gs->users[S_USERCOUNTS][i] > 0)
  1162. if ((((float) gs->users[S_USERSUM][i]) / ((float) gs->users[S_USERCOUNTS][i])) > max)
  1163. max = ((float) gs->users[S_USERSUM][i]) / ((float) gs->users[S_USERCOUNTS][i]);
  1164. }
  1165. if (display_average_users && (max > 0.0)) {
  1166. dprintf(idx, "%s<br><font size=\"-5\">\n", SLMAUSERS);
  1167. if (wert && nr)
  1168. dprintf(idx, "<table border=0 width=\"75%%\"><tr><td width=\"50%%\" align=\"center\" valign=\"bottom\">\n");
  1169. else
  1170. dprintf(idx, "<table border=0 width=\"37%%\"><tr><td width=\"100%%\" align=\"center\" valign=\"bottom\">\n");
  1171. dprintf(idx, "<table border=%d width=\"100%%\">", table_border);
  1172. onep = max / 100.0;
  1173. for (i = 0; i < 24; i++) {
  1174. if ((i == 12) && (wert && nr))
  1175. dprintf(idx, "</table></td><td width=\"50%%\" align=\"center\" valign=\"bottom\"><table border=%d width=\"100%%\">", table_border);
  1176. if (gs->users[S_USERCOUNTS][i] > 0) {
  1177. f = ((float) gs->users[S_USERSUM][i]) / ((float) gs->users[S_USERCOUNTS][i]);
  1178. dprintf(idx, "<tr><td width=\"1%%\"><font size=\"-5\">%d.00-%d.59</font></td><td width=\"99%%\"><table width=\"100%%\"><tr>", i, i);
  1179. if (((int) (f / onep)) > 0)
  1180. 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);
  1181. else if ((f / onep) > 0.0)
  1182. dprintf(idx, "<td width=\"100%%\"><font size=\"-5\">%.2f</font></td></tr></table></td>", f);
  1183. else
  1184. dprintf(idx, "<td width=\"100%%\"><font size=\"-5\">%.2f</font></td></tr></table></td>", f);
  1185. dprintf(idx, "</tr>\n");
  1186. }
  1187. }
  1188. dprintf(idx, "</table>");
  1189. dprintf(idx, "</td></tr></table>");
  1190. dprintf(idx, "</font>\n");
  1191. }
  1192. if (gs->topics) {
  1193. dprintf(idx, "<br><br>%s<br>\n<table border=%d>", SLMTOPICS, table_border);
  1194. i = 0;
  1195. for (t = gs->topics; t; t = t->next)
  1196. i++;
  1197. wert = table_color;
  1198. b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16;
  1199. wert = fade_table_to;
  1200. b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16;
  1201. rstep = (r2 - r) / i;
  1202. gstep = (g2 - g) / i;
  1203. bstep = (b2 - b) / i;
  1204. for (t = gs->topics; t; t = t->next) {
  1205. strftime(ts, 20, "%H:%M", localtime(&t->when));
  1206. setslnick(t->by);
  1207. dprintf(idx, "<tr bgcolor=#%02x%02x%02x><td>\"%s\"</td><td>",
  1208. (int) r, (int) g, (int) b, filt2(t->topic));
  1209. dprintf(idx, SLMTOPICBY, ts);
  1210. dprintf(idx, "</td></tr>\n");
  1211. r += rstep;
  1212. g += gstep;
  1213. b += bstep;
  1214. }
  1215. dprintf(idx, "</table><br><br>\n");
  1216. }
  1217. if (gs->urls && log_urls) {
  1218. nr = 0;
  1219. for (url = gs->urls; url; url = url->next) {
  1220. nr++;
  1221. url->shown = 0;
  1222. }
  1223. if (nr > log_urls)
  1224. wieoft = log_urls;
  1225. else
  1226. wieoft = nr;
  1227. slglobint = wieoft;
  1228. dprintf(idx, "<br><br><table border=%d><caption>%s</caption>", table_border, SLMURLS);
  1229. wert = table_color;
  1230. b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16;
  1231. wert = fade_table_to;
  1232. b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16;
  1233. rstep = (r2 - r) / wieoft;
  1234. gstep = (g2 - g) / wieoft;
  1235. bstep = (b2 - b) / wieoft;
  1236. while (wieoft > 0) {
  1237. x = random() % nr;
  1238. i = 0;
  1239. url = gs->urls;
  1240. while (url) {
  1241. if (url->shown) {
  1242. url = url->next;
  1243. continue;
  1244. }
  1245. if (i == x) {
  1246. dprintf(idx, "<tr bgcolor=#%02x%02x%02x><td>\"<a href=\"%s\">%s</a>\"</td><td>",
  1247. (int) r, (int) g, (int) b, url->url, url->url);
  1248. strftime(ts, 20, "%H:%M", localtime(&url->when));
  1249. setslnick(url->by);
  1250. dprintf(idx, SLMURLBY, ts);
  1251. dprintf(idx, "</td></tr>\n");
  1252. url->shown = 1;
  1253. nr--;
  1254. r += rstep;
  1255. g += gstep;
  1256. b += bstep;
  1257. break;
  1258. }
  1259. url = url->next;
  1260. i++;
  1261. }
  1262. wieoft--;
  1263. }
  1264. dprintf(idx, "</table>\n");
  1265. }
  1266. if (gs->hosts) {
  1267. tlds = nmalloc(sizeof(globstats));
  1268. tlds->hosts = NULL;
  1269. isps = nmalloc(sizeof(globstats));
  1270. isps->hosts = NULL;
  1271. for (h = gs->hosts; h; h = h->next) {
  1272. // skip IPv6 hosts
  1273. if (strchr(h->host, ':'))
  1274. continue;
  1275. host = strrchr(h->host, '.') + 1;
  1276. if (!atoi(host) && (host[0] != '0')) {
  1277. addhost(host, tlds);
  1278. host = h->host;
  1279. while ((s = strchr(host, '.')) && strchr(s + 1, '.'))
  1280. host = s + 1;
  1281. addhost(host, isps);
  1282. } else {
  1283. addhost("[IP]", tlds);
  1284. addhost("[IP]", isps);
  1285. }
  1286. }
  1287. sorthosts(isps);
  1288. sorthosts(tlds);
  1289. dprintf(idx, "<br><br><table border=%d><tr><th colspan=2>%s</th></tr><tr><th>%s</th><th>%s</th></tr>\n",
  1290. table_border, SLMMOSTUSED, SLMISPS, SLMTLDS);
  1291. i = 0;
  1292. isp = isps->hosts;
  1293. tld = tlds->hosts;
  1294. wert = table_color;
  1295. b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16;
  1296. wert = fade_table_to;
  1297. b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16;
  1298. rstep = (r2 - r) / 5;
  1299. gstep = (g2 - g) / 5;
  1300. bstep = (b2 - b) / 5;
  1301. while ((i <= 5) && (isp || tld)) {
  1302. i++;
  1303. dprintf(idx, "<tr bgcolor=#%02x%02x%02x>\n", (int) r, (int) g, (int) b);
  1304. r += rstep;
  1305. g += gstep;
  1306. b += bstep;
  1307. if (isp)
  1308. dprintf(idx, "<td>%s (%d)</td>", isp->host, isp->nr);
  1309. else
  1310. dprintf(idx, "<td>-</td>");
  1311. if (tld)
  1312. dprintf(idx, "<td>%s (%d)</td>", tld->host, tld->nr);
  1313. else
  1314. dprintf(idx, "<td>-</td>");
  1315. dprintf(idx, "</tr>\n");
  1316. if (isp)
  1317. isp = isp->next;
  1318. if (tld)
  1319. tld = tld->next;
  1320. }
  1321. dprintf(idx, "</table>\n");
  1322. free_hosts(isps->hosts);
  1323. free_hosts(tlds->hosts);
  1324. nfree(isps);
  1325. nfree(tlds);
  1326. }
  1327. if (gs->kicks && (display_kicks > 0)) {
  1328. nr = 0;
  1329. for (kick = gs->kicks; kick; kick = kick->next) {
  1330. nr++;
  1331. kick->shown = 0;
  1332. }
  1333. if (nr > display_kicks)
  1334. wieoft = display_kicks;
  1335. else
  1336. wieoft = nr;
  1337. slglobint = wieoft;
  1338. dprintf(idx, "<br><br><table border=%d><caption>%s</caption>", table_border, SLMKICKS);
  1339. wert = table_color;
  1340. b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16;
  1341. wert = fade_table_to;
  1342. b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16;
  1343. rstep = (r2 - r) / wieoft;
  1344. gstep = (g2 - g) / wieoft;
  1345. bstep = (b2 - b) / wieoft;
  1346. while (wieoft > 0) {
  1347. x = random() % nr;
  1348. i = 0;
  1349. kick = gs->kicks;
  1350. while (kick) {
  1351. if (kick->shown) {
  1352. kick = kick->next;
  1353. continue;
  1354. }
  1355. if (i == x) {
  1356. dprintf(idx, "<tr bgcolor=#%02x%02x%02x><td><cite><font size=-2>", (int) r, (int) g, (int) b);
  1357. for (log = kick->log; log; log = log->next) {
  1358. if (log->next)
  1359. dprintf(idx, "%s<br>", filt2(log->quote));
  1360. else
  1361. dprintf(idx, "</font>%s</b><br>", filt2(log->quote));
  1362. }
  1363. dprintf(idx, "</cite></td></tr>\n");
  1364. kick->shown = 1;
  1365. nr--;
  1366. r += rstep;
  1367. g += gstep;
  1368. b += bstep;
  1369. break;
  1370. }
  1371. kick = kick->next;
  1372. i++;
  1373. }
  1374. wieoft--;
  1375. }
  1376. dprintf(idx, "</table>\n");
  1377. }
  1378. if (gs->words) {
  1379. nr = 0;
  1380. for (ws = gs->words; ws; ws = ws->next)
  1381. nr++;
  1382. dprintf(idx, "<br><br>"); dprintf(idx, SLMCWORDSTATS, nr); dprintf(idx, "<br>\n");
  1383. dprintf(idx, "%s<br><table border=%d>\n", SLMMOSTUSEDWORDS, table_border);
  1384. wert = table_color;
  1385. b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16;
  1386. wert = fade_table_to;
  1387. b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16;
  1388. rstep = (r2 - r) / 10;
  1389. gstep = (g2 - g) / 10;
  1390. bstep = (b2 - b) / 10;
  1391. ws = gs->words;
  1392. nr = 0;
  1393. while (ws && (nr < 10)) {
  1394. nr++;
  1395. dprintf(idx, "<tr bgcolor=#%02x%02x%02x><td>%d.</td><td>%s</td><td>(%d)</td></tr>\n",
  1396. (int) r, (int) g, (int) b, nr, filt2(ws->word), ws->nr);
  1397. r += rstep;
  1398. g += gstep;
  1399. b += bstep;
  1400. ws = ws->next;
  1401. }
  1402. dprintf(idx, "</table>\n");
  1403. }
  1404. dprintf(idx, "<br><br><table border=%d>\n", table_border);
  1405. for (l = slangs; l; l = l->next) {
  1406. if ((!l->lang && !slgloblang) || (l->lang && slgloblang && !strcasecmp(l->lang, slgloblang))) {
  1407. i = 0;
  1408. for (ty = l->bignumbers; ty; ty = ty->next)
  1409. i++;
  1410. wert = table_color;
  1411. b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16;
  1412. wert = fade_table_to;
  1413. b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16;
  1414. rstep = (r2 - r) / i;
  1415. gstep = (g2 - g) / i;
  1416. bstep = (b2 - b) / i;
  1417. for (ty = l->bignumbers; ty; ty = ty->next) {
  1418. i = typetoi(ty->type);
  1419. sortstats(gs, i, S_DAILY);
  1420. tr = 0;
  1421. for (p = ty->places; p; p = p->next) {
  1422. nr = 1;
  1423. if (i < 0)
  1424. pitype = (i * -1) + (TOTAL_TYPES - 1);
  1425. else
  1426. pitype = i;
  1427. ls = gs->slocal[S_DAILY][pitype];
  1428. while (ls && (nr < p->place)) {
  1429. nr++;
  1430. ls = ls->snext[S_DAILY][pitype];
  1431. }
  1432. // just skip this entry if any vital information is missing.
  1433. if (!ls)
  1434. continue;
  1435. else if ((i >= 0) && !ls->values[S_DAILY][i])
  1436. continue;
  1437. else if ((i == T_WPL) && (!ls->values[S_DAILY][T_WORDS] || !ls->values[S_DAILY][T_LINES]))
  1438. continue;
  1439. else if ((i == T_IDLE) && (!ls->values[S_DAILY][T_MINUTES] || !ls->values[S_DAILY][T_LINES]))
  1440. continue;
  1441. else if ((i == T_VOCABLES) && !ls->vocables)
  1442. continue;
  1443. if (!tr) {
  1444. dprintf(idx, "<tr bgcolor=#%02x%02x%02x><td>\n", (int) r, (int) g, (int) b);
  1445. r += rstep;
  1446. g += gstep;
  1447. b += bstep;
  1448. tr = 1;
  1449. }
  1450. slgloblocstats = ls;
  1451. slglobtype = ty->type;
  1452. x = random() % p->entries;
  1453. txt = p->texts;
  1454. while (txt) {
  1455. if (!x)
  1456. dprintf(idx, "%s\n", dynamicslang(txt->text));
  1457. x--;
  1458. txt = txt->next;
  1459. }
  1460. }
  1461. if (tr)
  1462. dprintf(idx, "</td></tr>\n");
  1463. }
  1464. }
  1465. }
  1466. dprintf(idx, "</table>\n");
  1467. dprintf(idx, "<br><br><hr>\n");
  1468. dprintf(idx, "<table width=100%% border=0>\n");
  1469. dprintf(idx, "<tr><td align=center><table width=100%% border=0><tr>\n");
  1470. dprintf(idx, "<td width=25%% align=center><font size=-1><a href=\"../top/total/words/\">top%d</a></font></td>\n", webnr);
  1471. dprintf(idx, "<td width=25%% align=center><font size=-1><%sa href=\"../users/\">%s</a></font></td>\n",
  1472. ISLINK(show_userlist), ISTEXT(show_userlist, SLUSERS));
  1473. dprintf(idx, "<td width=25%% align=center><font size=-1><%sa href=\"../onchan/\">%s</a></font></td>\n",
  1474. ISLINK(show_usersonchan), ISTEXT(show_usersonchan, SLONCHAN));
  1475. dprintf(idx, "<td width=25%% align=center><font size=-1><a href=\"../../\">%s</a></font></td>\n", SLOTHERCHANS);
  1476. dprintf(idx, "</tr></table></td></tr>\n");
  1477. dprintf(idx, "</table>\n");
  1478. dprintf(idx, "<center>Created by <a href=\"http://www.kreativrauschen.de/stats.mod/\">Stats.mod v%s</a></center></body></html>", MODULE_VERSION);
  1479. long_dprintf(idx, SLFOOTER);
  1480. dprintf(idx, "</body></html>");
  1481. }
  1482. static void display_users_on_chan(int idx, char *channel, struct chanset_t *chan)
  1483. {
  1484. memberlist *m;
  1485. struct stats_memberlist *mm;
  1486. int wert;
  1487. float r, g, b;
  1488. float r2, g2, b2;
  1489. float rstep, gstep, bstep;
  1490. int i;
  1491. char s1[121];
  1492. Context;
  1493. dprintf(idx, "<html><head><title>%s</title>\n%s\n</head>\n", SLUSERSONCHANTITLE, SLCSS);
  1494. dprintf(idx, "%s\n", SLBODYTAG);
  1495. long_dprintf(idx, SLHEADER);
  1496. if (show_usersonchan && chan && (chan->channel.members > 0)) {
  1497. dprintf(idx, "<br><br><center><table border=%d>\n<tr><th colspan=3>%s</th></tr>\n", table_border, SLNOWONCHAN);
  1498. dprintf(idx, "<tr><th align=\"center\">nick</th><th align=\"center\">user</th><th align=\"center\">%s</th></tr>\n", SLIDLETIME);
  1499. i = 0;
  1500. for (m = chan->channel.member; m && m->nick[0]; m = m->next)
  1501. i++;
  1502. wert = table_color;
  1503. b = wert & 0xff; g = (wert & 0xff00) >> 8; r = (wert & 0xff0000) >> 16;
  1504. wert = fade_table_to;
  1505. b2 = wert & 0xff; g2 = (wert & 0xff00) >> 8; r2 = (wert & 0xff0000) >> 16;
  1506. rstep = (r2 - r) / i;
  1507. gstep = (g2 - g) / i;
  1508. bstep = (b2 - b) / i;
  1509. for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
  1510. dprintf(idx, "<tr bgcolor=#%02x%02x%02x>", (int) r, (int) g, (int) b);
  1511. dprintf(idx, "<td align=\"left\">%s%s</td>",
  1512. chan_hasop(m) ? "@" : (chan_hasvoice(m) ? "+" : "&nbsp;"),
  1513. m->nick);
  1514. r += rstep;
  1515. g += gstep;
  1516. b += bstep;
  1517. if (!m->user && ((strlen(m->nick) + strlen(m->userhost) + 1) < 120)) {
  1518. sprintf(s1, "%s!%s", m->nick, m->userhost);
  1519. m->user = get_user_by_host(s1);
  1520. }
  1521. if (!use_userfile) {
  1522. mm = nick2suser(m->nick, channel);
  1523. if (mm && mm->user)
  1524. dprintf(idx, "<td align=\"center\"><a href=\"../users/%s/\">%s</a></td>", mm->user->user, mm->user->user);
  1525. else
  1526. dprintf(idx, "<td align=\"center\">-</td>");
  1527. } else {
  1528. if (m->user)
  1529. dprintf(idx, "<td align=\"center\"><a href=\"../users/%s/\">%s</a></td>", m->user->handle, m->user->handle);
  1530. else
  1531. dprintf(idx, "<td align=\"center\">-</td>");
  1532. }
  1533. if (chan_issplit(m))
  1534. dprintf(idx, "<td align=\"right\">%s</td>", SLNETSPLITTED);
  1535. else if (!rfc_casecmp(m->nick, botname))
  1536. dprintf(idx, "<td align=\"right\">%s</td>", SLITSME);
  1537. else
  1538. dprintf(idx, "<td align=\"right\">&nbsp;%s</td>", stats_duration(now - m->last));
  1539. dprintf(idx, "</tr>\n");
  1540. }
  1541. dprintf(idx, "</table></center>\n<br><br>");
  1542. }
  1543. dprintf(idx, "<table width=100%% border=0>\n");
  1544. dprintf(idx, "<tr><td align=center><table width=100%% border=0><tr>\n");
  1545. dprintf(idx, "<td width=25%% align=center><font size=-1><a href=\"../top/total/words/\">top%d</a></font></td>\n", webnr);
  1546. dprintf(idx, "<td width=25%% align=center><font size=-1><%sa href=\"../users/\">%s</a></font></td>\n",
  1547. ISLINK(show_userlist), ISTEXT(show_userlist, SLUSERS));
  1548. dprintf(idx, "<td width=25%% align=center><font size=-1><a href=\"../misc/\">%s</a></font></td>\n", SLMISCSTATS);
  1549. dprintf(idx, "<td width=25%% align=center><font size=-1><a href=\"../../\">%s</a></font></td>\n", SLOTHERCHANS);
  1550. dprintf(idx, "</tr></table></td></tr>\n");
  1551. dprintf(idx, "</table>\n");
  1552. dprintf(idx, "<center>Created by <a href=\"http://www.kreativrauschen.de/stats.mod/\">Stats.mod v%s</a></center></body></html>", MODULE_VERSION);
  1553. long_dprintf(idx, SLFOOTER);
  1554. dprintf(idx, "</body></html>");
  1555. }