botcmd.c 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381
  1. /*
  2. * Copyright (C) 1997 Robey Pointer
  3. * Copyright (C) 1999 - 2002 Eggheads Development Team
  4. * Copyright (C) 2002 - 2010 Bryan Drewery
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19. */
  20. /*
  21. * botcmd.c -- handles:
  22. * commands that comes across the botnet
  23. * userfile transfer and update commands from sharebots
  24. *
  25. */
  26. #include "common.h"
  27. #include "botcmd.h"
  28. #include "main.h"
  29. #include "base64.h"
  30. #include "src/mod/share.mod/share.h"
  31. #include "src/mod/update.mod/update.h"
  32. #include "net.h"
  33. #include "binds.h"
  34. #include "misc.h"
  35. #include "dcc.h"
  36. #include "userrec.h"
  37. #include "dccutil.h"
  38. #include "cmds.h"
  39. #include "chanprog.h"
  40. #include "botmsg.h"
  41. #include "botnet.h"
  42. #include "tandem.h"
  43. #include "users.h"
  44. #include "chan.h"
  45. #include "core_binds.h"
  46. #include "egg_timer.h"
  47. static char TBUF[1024] = ""; /* Static buffer for goofy bot stuff */
  48. static void fake_alert(int idx, char *item, char *extra, char *what)
  49. {
  50. static time_t lastfake; /* The last time fake_alert was used */
  51. if ((now - lastfake) > 10) {
  52. /* Don't fake_alert more than once every 10secs */
  53. dprintf(idx, "ct %s NOTICE: %s (%s != %s). (%s)\n", conf.bot->nick, "Fake message rejected", item, extra, what);
  54. putlog(LOG_BOTS, "*", "%s %s (%s != %s). (%s)", dcc[idx].nick, "Fake message rejected", item, extra, what);
  55. lastfake = now;
  56. }
  57. }
  58. /* chan <from> <chan> <text>
  59. */
  60. static void bot_chan2(int idx, char *msg)
  61. {
  62. char *from = NULL, *p = NULL;
  63. int i, chan;
  64. from = newsplit(&msg);
  65. p = newsplit(&msg);
  66. chan = base64_to_int(p);
  67. /* Strip annoying control chars */
  68. for (p = from; *p;) {
  69. if ((*p < 32) || (*p == 127))
  70. memmove(p, p + 1, strlen(p));
  71. else
  72. p++;
  73. }
  74. p = strchr(from, '@');
  75. if (p) {
  76. if (!conf.bot->hub) { /* Need to strip out the hub nick */
  77. char *q = NULL, newfrom[HANDLEN + 9 + 1]; /* HANDLEN@[botnet] */
  78. strlcpy(newfrom, from, sizeof(newfrom));
  79. q = strchr(newfrom, '@');
  80. *q = 0;
  81. simple_snprintf(TBUF, sizeof(TBUF), "<%s@[botnet]> %s", newfrom, msg);
  82. } else
  83. simple_snprintf(TBUF, sizeof(TBUF), "<%s> %s", from, msg);
  84. *p = 0;
  85. if (!partyidle(p + 1, from)) {
  86. *p = '@';
  87. fake_alert(idx, "user", from, "chan2_i");
  88. return;
  89. }
  90. *p = '@';
  91. p++;
  92. } else {
  93. simple_snprintf(TBUF, sizeof(TBUF), "*** (%s) %s", from, msg);
  94. p = from;
  95. }
  96. i = nextbot(p);
  97. if (i != idx) {
  98. fake_alert(idx, "direction", p, "chan2_ii");
  99. } else {
  100. chanout_but(-1, chan, "%s\n", TBUF);
  101. /* Send to new version bots */
  102. if (i >= 0)
  103. botnet_send_chan(idx, from, NULL, chan, msg);
  104. }
  105. }
  106. void bot_cmdpass(int idx, char *par)
  107. {
  108. char *p = strchr(par, ' ');
  109. if (p) {
  110. *p++ = 0;
  111. botnet_send_cmdpass(idx, par, p);
  112. p--;
  113. *p = ' ';
  114. } else {
  115. botnet_send_cmdpass(idx, par, "");
  116. }
  117. set_cmd_pass(par, 0);
  118. }
  119. void bot_set(int idx, char *par)
  120. {
  121. var_userfile_share_line(par, idx, 0);
  122. }
  123. void bot_setbroad(int idx, char *par)
  124. {
  125. var_userfile_share_line(par, idx, 1);
  126. }
  127. void bot_remotecmd(int idx, char *par) {
  128. char *tbot = NULL, *fbot = NULL, *fhnd = NULL, *fidx = NULL;
  129. if (par[0])
  130. tbot = newsplit(&par);
  131. if (par[0])
  132. fbot = newsplit(&par);
  133. if (par[0])
  134. fhnd = newsplit(&par);
  135. if (par[0])
  136. fidx = newsplit(&par);
  137. /* Make sure the bot is valid */
  138. int i = nextbot(fbot);
  139. if (i != idx) {
  140. fake_alert(idx, "direction", fbot, "rc");
  141. return;
  142. }
  143. if (!strcasecmp(tbot, conf.bot->nick)) {
  144. gotremotecmd(tbot, fbot, fhnd, fidx, par);
  145. } else if (!strcmp(tbot, "*")) {
  146. botnet_send_cmd_broad(idx, fbot, fhnd, atoi(fidx), par);
  147. gotremotecmd(tbot, fbot, fhnd, fidx, par);
  148. } else {
  149. if (nextbot(tbot) != idx)
  150. botnet_send_cmd(fbot, tbot, fhnd, atoi(fidx), par);
  151. }
  152. }
  153. void bot_remotereply(int idx, char *par) {
  154. char *tbot = NULL, *fbot = NULL, *fhnd = NULL, *fidx = NULL;
  155. if (par[0])
  156. tbot = newsplit(&par);
  157. if (par[0])
  158. fbot = newsplit(&par);
  159. if (par[0])
  160. fhnd = newsplit(&par);
  161. if (par[0])
  162. fidx = newsplit(&par);
  163. /* Make sure the bot is valid */
  164. int i = nextbot(fbot);
  165. if (i != idx) {
  166. fake_alert(idx, "direction", fbot, "rr");
  167. return;
  168. }
  169. if (!strcasecmp(tbot, conf.bot->nick)) {
  170. gotremotereply(fbot, fhnd, fidx, par);
  171. } else {
  172. if (nextbot(tbot)!= idx)
  173. botnet_send_cmdreply(fbot, tbot, fhnd, fidx, par);
  174. }
  175. }
  176. /* chat <from> <notice> -- only from bots
  177. */
  178. /* this is only sent to hub bots */
  179. static void bot_chat(int idx, char *par)
  180. {
  181. char *from = NULL;
  182. int i;
  183. from = newsplit(&par);
  184. if (strchr(from, '@') != NULL) {
  185. fake_alert(idx, "bot", from, "chat_i");
  186. return;
  187. }
  188. /* Make sure the bot is valid */
  189. i = nextbot(from);
  190. if (i != idx) {
  191. fake_alert(idx, "direction", from, "chat_ii");
  192. return;
  193. }
  194. chatout("*** (%s) %s\n", from, par);
  195. botnet_send_chat(idx, from, par);
  196. }
  197. /* actchan <from> <chan> <text>
  198. */
  199. static void bot_actchan(int idx, char *par)
  200. {
  201. char *from = NULL, *p = NULL;
  202. int i, chan;
  203. from = newsplit(&par);
  204. p = strchr(from, '@');
  205. if (p == NULL) {
  206. /* How can a bot do an action? */
  207. fake_alert(idx, "user@bot", from, "actchan_i");
  208. return;
  209. }
  210. *p = 0;
  211. if (!partyidle(p + 1, from)) {
  212. *p = '@';
  213. fake_alert(idx, "user", from, "actchan_ii");
  214. return;
  215. }
  216. *p = '@';
  217. p++;
  218. i = nextbot(p);
  219. if (i != idx) {
  220. fake_alert(idx, "direction", p, "actchan_iii");
  221. return;
  222. }
  223. p = newsplit(&par);
  224. chan = base64_to_int(p);
  225. for (p = from; *p;) {
  226. if ((*p < 32) || (*p == 127))
  227. memmove(p, p + 1, strlen(p));
  228. else
  229. p++;
  230. }
  231. if (!conf.bot->hub) { /* Need to strip out the hub nick */
  232. char *q = NULL, newfrom[HANDLEN + 9 + 1]; /* HANDLEN@[botnet] */
  233. strlcpy(newfrom, from, sizeof(newfrom));
  234. q = strchr(newfrom, '@');
  235. *q = 0;
  236. chanout_but(-1, chan, "* %s@[botnet] %s\n", newfrom, par);
  237. } else
  238. chanout_but(-1, chan, "* %s %s\n", from, par);
  239. botnet_send_act(idx, from, NULL, chan, par);
  240. }
  241. /* priv <from> <to> <message>
  242. */
  243. static void bot_priv(int idx, char *par)
  244. {
  245. char *from = NULL, *p = NULL, *to = TBUF, *tobot = NULL;
  246. int i;
  247. from = newsplit(&par);
  248. tobot = newsplit(&par);
  249. splitc(to, tobot, '@');
  250. p = strchr(from, '@');
  251. if (p != NULL)
  252. p++;
  253. else
  254. p = from;
  255. i = nextbot(p);
  256. if (i != idx) {
  257. fake_alert(idx, "direction", p, "priv_i");
  258. return;
  259. }
  260. if (!to[0])
  261. return; /* Silently ignore notes to '@bot' this
  262. * is legacy code */
  263. if (!strcasecmp(tobot, conf.bot->nick)) { /* For me! */
  264. if (p == from)
  265. add_note(to, from, par, -2, 0);
  266. else {
  267. i = add_note(to, from, par, -1, 0);
  268. if (from[0] != '@')
  269. switch (i) {
  270. case NOTE_ERROR:
  271. botnet_send_priv(idx, conf.bot->nick, from, NULL, "%s %s.", "No such user", to);
  272. break;
  273. }
  274. }
  275. } else { /* Pass it on */
  276. i = nextbot(tobot);
  277. if (i >= 0)
  278. botnet_send_priv(i, from, to, tobot, "%s", par);
  279. }
  280. }
  281. static void bot_bye(int idx, char *par)
  282. {
  283. char s[1024] = "";
  284. int users, bots;
  285. bots = bots_in_subtree(findbot(dcc[idx].nick));
  286. users = users_in_subtree(findbot(dcc[idx].nick));
  287. simple_snprintf(s, sizeof(s), "%s %s. %s (lost %d bot%s and %d user%s)",
  288. "Disconnected from:",
  289. (conf.bot->hub || (conf.bot->localhub && bot_aggressive_to(dcc[idx].user))) ? dcc[idx].nick : "botnet",
  290. par[0] ? par : "No reason", bots, (bots != 1) ?
  291. "s" : "", users, (users != 1) ? "s" : "");
  292. putlog(LOG_BOTS, "*", "%s", s);
  293. chatout("*** %s\n", s);
  294. botnet_send_unlinked(idx, dcc[idx].nick, s);
  295. dprintf(idx, "*bye\n");
  296. killsock(dcc[idx].sock);
  297. lostdcc(idx);
  298. }
  299. static void remote_tell_who(int idx, char *nick, int chan)
  300. {
  301. int i = 10, k, l, ok = 0;
  302. char s[1024] = "", *realnick = NULL;
  303. struct chanset_t *c = NULL;
  304. realnick = strchr(nick, ':');
  305. if (realnick)
  306. realnick++;
  307. else
  308. realnick = nick;
  309. putlog(LOG_BOTS, "*", "#%s# who", realnick);
  310. strlcpy(s, "Channels: ", sizeof(s));
  311. for (c = chanset; c; c = c->next)
  312. if (!channel_secret(c) && shouldjoin(c)) {
  313. l = strlen(c->dname);
  314. if (i + l < 1021) {
  315. if (i > 10) {
  316. strlcat(s, ", ", sizeof(s));
  317. strlcat(s, c->dname, sizeof(s));
  318. } else {
  319. strlcpy(s, c->dname, sizeof(s));
  320. i += (l + 2);
  321. }
  322. }
  323. }
  324. if (i > 10) {
  325. botnet_send_priv(idx, conf.bot->nick, nick, NULL, "%s (%s)", s, ver);
  326. } else {
  327. botnet_send_priv(idx, conf.bot->nick, nick, NULL, "%s (%s)", "no channels", ver);
  328. }
  329. if (admin[0])
  330. botnet_send_priv(idx, conf.bot->nick, nick, NULL, "Admin: %s", admin);
  331. if (chan == 0) {
  332. botnet_send_priv(idx, conf.bot->nick, nick, NULL,
  333. "Party line members: (^ = admin, * = owner, + = master, @ = op)");
  334. } else {
  335. botnet_send_priv(idx, conf.bot->nick, nick, NULL,
  336. "People on channel %s%d: (^ = admin, * = owner, + = master, @ = op)\n",
  337. (chan < GLOBAL_CHANS) ? "" : "*",
  338. chan % GLOBAL_CHANS);
  339. }
  340. for (i = 0; i < dcc_total; i++) {
  341. if (dcc[i].type && dcc[i].type->flags & DCT_REMOTEWHO) {
  342. if (dcc[i].u.chat->channel == chan) {
  343. k = simple_snprintf(s, sizeof(s), " %c%-15s %s", (geticon(i) == '-' ? ' ' : geticon(i)),
  344. dcc[i].nick, dcc[i].host);
  345. if (now - dcc[i].timeval > 300) {
  346. unsigned long mydays, hrs, mins;
  347. mydays = (now - dcc[i].timeval) / 86400;
  348. hrs = ((now - dcc[i].timeval) - (mydays * 86400)) / 3600;
  349. mins = ((now - dcc[i].timeval) - (hrs * 3600)) / 60;
  350. if (mydays > 0)
  351. simple_snprintf(s + k, sizeof(s) - k, " (idle %lud%luh)", mydays, hrs);
  352. else if (hrs > 0)
  353. simple_snprintf(s + k, sizeof(s) - k, " (idle %luh%lum)", hrs, mins);
  354. else
  355. simple_snprintf(s + k, sizeof(s) - k, " (idle %lum)", mins);
  356. }
  357. botnet_send_priv(idx, conf.bot->nick, nick, NULL, "%s", s);
  358. if (dcc[i].u.chat->away != NULL)
  359. botnet_send_priv(idx, conf.bot->nick, nick, NULL, " AWAY: %s", dcc[i].u.chat->away);
  360. }
  361. }
  362. }
  363. for (i = 0; i < dcc_total; i++) {
  364. if (dcc[i].type && dcc[i].type == &DCC_BOT) {
  365. if (!ok) {
  366. ok = 1;
  367. botnet_send_priv(idx, conf.bot->nick, nick, NULL, "%s:", "Bots connected");
  368. }
  369. simple_snprintf(s, sizeof(s), " %s%c%-15s %s",
  370. dcc[i].status & STAT_CALLED ? "<-" : "->",
  371. dcc[i].status & STAT_SHARE ? '+' : ' ',
  372. dcc[i].nick, dcc[i].u.bot->version);
  373. botnet_send_priv(idx, conf.bot->nick, nick, NULL, "%s", s);
  374. }
  375. }
  376. ok = 0;
  377. for (i = 0; i < dcc_total; i++) {
  378. if (dcc[i].type && dcc[i].type->flags & DCT_REMOTEWHO) {
  379. if (dcc[i].u.chat->channel != chan) {
  380. if (!ok) {
  381. ok = 1;
  382. botnet_send_priv(idx, conf.bot->nick, nick, NULL, "%s:", "Other people on the bot");
  383. }
  384. l = simple_snprintf(s, sizeof(s), " %c%-15s %s", (geticon(i) == '-' ? ' ' : geticon(i)), dcc[i].nick, dcc[i].host);
  385. if (now - dcc[i].timeval > 300) {
  386. k = (now - dcc[i].timeval) / 60;
  387. if (k < 60)
  388. simple_snprintf(s + l, sizeof(s) - l, " (idle %dm)", k);
  389. else
  390. simple_snprintf(s + l, sizeof(s) - l, " (idle %dh%dm)", k / 60, k % 60);
  391. }
  392. botnet_send_priv(idx, conf.bot->nick, nick, NULL, "%s", s);
  393. if (dcc[i].u.chat->away != NULL)
  394. botnet_send_priv(idx, conf.bot->nick, nick, NULL, " AWAY: %s", dcc[i].u.chat->away);
  395. }
  396. }
  397. }
  398. }
  399. static void bot_shellinfo(int idx, char *par)
  400. {
  401. char *username = NULL, *sysname = NULL, *nodename = NULL, *arch = NULL, *botversion = NULL;
  402. username = newsplit(&par);
  403. sysname = newsplit(&par);
  404. nodename = newsplit(&par);
  405. arch = newsplit(&par);
  406. botversion = newsplit(&par);
  407. set_user(&USERENTRY_USERNAME, dcc[idx].user, username);
  408. set_user(&USERENTRY_OS, dcc[idx].user, sysname);
  409. dcc[idx].u.bot->sysname[0] = 0;
  410. struct bot_info dummy;
  411. strlcpy(dcc[idx].u.bot->sysname, sysname, sizeof(dummy.sysname));
  412. set_user(&USERENTRY_NODENAME, dcc[idx].user, nodename);
  413. set_user(&USERENTRY_ARCH, dcc[idx].user, arch);
  414. set_user(&USERENTRY_OSVER, dcc[idx].user, botversion);
  415. }
  416. /* who <from@bot> <tobot> <chan#>
  417. */
  418. static void bot_who(int idx, char *par)
  419. {
  420. char *from = NULL, *to = NULL, *p = NULL;
  421. int i, chan;
  422. from = newsplit(&par);
  423. p = strchr(from, '@');
  424. if (!p) {
  425. simple_snprintf(TBUF, sizeof(TBUF), "%s@%s", from, dcc[idx].nick);
  426. from = TBUF;
  427. }
  428. to = newsplit(&par);
  429. if (!strcasecmp(to, conf.bot->nick))
  430. to[0] = 0; /* (for me) */
  431. chan = base64_to_int(par);
  432. if (to[0]) { /* Pass it on */
  433. i = nextbot(to);
  434. if (i >= 0)
  435. botnet_send_who(i, from, to, chan);
  436. } else {
  437. remote_tell_who(idx, from, chan);
  438. }
  439. }
  440. static void bot_endlink(int idx, char *par)
  441. {
  442. dcc[idx].status &= ~STAT_LINKING;
  443. }
  444. static void bot_ping(int idx, char *par)
  445. {
  446. botnet_send_pong(idx);
  447. }
  448. static void bot_pong(int idx, char *par)
  449. {
  450. dcc[idx].status &= ~STAT_PINGED;
  451. if (dcc[idx].pingtime > (now - 120))
  452. dcc[idx].pingtime -= now;
  453. else
  454. dcc[idx].pingtime = 120;
  455. }
  456. /* link <from@bot> <who> <to-whom>
  457. */
  458. static void bot_link(int idx, char *par)
  459. {
  460. char *from = NULL, *bot = NULL, *rfrom = NULL;
  461. int i;
  462. from = newsplit(&par);
  463. bot = newsplit(&par);
  464. if (!strcasecmp(bot, conf.bot->nick)) {
  465. if ((rfrom = strchr(from, ':')))
  466. rfrom++;
  467. else
  468. rfrom = from;
  469. putlog(LOG_CMDS, "*", "#%s# link %s", rfrom, par);
  470. if (botlink(from, -1, par))
  471. botnet_send_priv(idx, conf.bot->nick, from, NULL, "%s %s ...", "Attempting to link", par);
  472. else
  473. botnet_send_priv(idx, conf.bot->nick, from, NULL, "%s.", "Can't link there");
  474. } else {
  475. i = nextbot(bot);
  476. if (i >= 0)
  477. botnet_send_link(i, from, bot, par);
  478. }
  479. }
  480. /*
  481. bot_log
  482. - forwards to all hubs linked directly if a hub (excluding the one who sent it)
  483. - leaf bots display and do not pass along.
  484. */
  485. static void bot_log(int idx, char *par)
  486. {
  487. char *from = newsplit(&par);
  488. int i = nextbot(from);
  489. if (i != idx) {
  490. fake_alert(idx, "direction", from, "log");
  491. return;
  492. }
  493. if (egg_isdigit(par[0])) {
  494. int type = atoi(newsplit(&par));
  495. if (conf.bot->hub || conf.bot->localhub)
  496. botnet_send_log(idx, from, type, par);
  497. if (conf.bot->hub)
  498. putlog(type, "@", "(%s) %s", from, par);
  499. } else {
  500. putlog(LOG_ERRORS, "*", "Malformed HL line from %s: %s", from, par);
  501. }
  502. }
  503. /* unlink <from@bot> <linking-bot> <undesired-bot> <reason>
  504. */
  505. static void bot_unlink(int idx, char *par)
  506. {
  507. char *from = NULL, *bot = NULL, *rfrom = NULL, *p = NULL, *undes = NULL;
  508. int i;
  509. from = newsplit(&par);
  510. bot = newsplit(&par);
  511. undes = newsplit(&par);
  512. if (!strcasecmp(bot, conf.bot->nick)) {
  513. if ((rfrom = strchr(from, ':')))
  514. rfrom++;
  515. else
  516. rfrom = from;
  517. putlog(LOG_CMDS, "*", "#%s# unlink %s (%s)", rfrom, undes, par[0] ? par : "No reason");
  518. i = botunlink(-3, undes, par[0] ? par : NULL);
  519. if (i == 1) {
  520. p = strchr(from, '@');
  521. if (p) {
  522. /* idx will change after unlink -- get new idx
  523. *
  524. * TODO: This has changed with the new lostdcc() behaviour. Check
  525. * if we can optimise the situation.
  526. */
  527. i = nextbot(p + 1);
  528. if (i >= 0)
  529. botnet_send_priv(i, conf.bot->nick, from, NULL, "Unlinked from %s.", undes);
  530. }
  531. } else if (i == 0) {
  532. botnet_send_unlinked(-1, undes, "");
  533. p = strchr(from, '@');
  534. if (p) {
  535. /* Ditto above, about idx */
  536. i = nextbot(p + 1);
  537. if (i >= 0)
  538. botnet_send_priv(i, conf.bot->nick, from, NULL, "%s %s.", "Can't unlink", undes);
  539. }
  540. } else {
  541. p = strchr(from, '@');
  542. if (p) {
  543. i = nextbot(p + 1);
  544. if (i >= 0)
  545. botnet_send_priv(i, conf.bot->nick, from, NULL, "Can't remotely unlink sharebots.");
  546. }
  547. }
  548. } else {
  549. i = nextbot(bot);
  550. if (i >= 0)
  551. botnet_send_unlink(i, from, bot, undes, par);
  552. }
  553. }
  554. /* Bot next share?
  555. */
  556. static void bot_update(int idx, char *par)
  557. {
  558. char *bot = NULL, x, *vversion = NULL, *vcommit = NULL;
  559. int vlocalhub = 0;
  560. time_t vbuildts = 0L;
  561. bot = newsplit(&par);
  562. x = par[0];
  563. if (x)
  564. par++;
  565. newsplit(&par); /* vnum */
  566. if (par[0])
  567. vlocalhub = atoi(newsplit(&par));
  568. if (par[0])
  569. vbuildts = atol(newsplit(&par));
  570. if (par[0])
  571. vcommit = newsplit(&par);
  572. if (par[0])
  573. vversion = newsplit(&par);
  574. if (in_chain(bot))
  575. updatebot(idx, bot, x, vlocalhub, vbuildts, vcommit, vversion);
  576. }
  577. /* Newbot next share?
  578. */
  579. static void bot_nlinked(int idx, char *par)
  580. {
  581. char *newbot = NULL, *next = NULL, *p = NULL, s[1024] = "", x = 0, *vversion = NULL, *vcommit = NULL;
  582. int i, vlocalhub = 0;
  583. time_t vbuildts = 0L;
  584. bool bogus = 0;
  585. newbot = newsplit(&par);
  586. next = newsplit(&par);
  587. s[0] = 0;
  588. if (!next[0]) {
  589. putlog(LOG_BOTS, "*", "Invalid eggnet protocol from %s (zapfing)", dcc[idx].nick);
  590. simple_snprintf(s, sizeof(s), "Disconnected %s (invalid bot)", dcc[idx].nick);
  591. dprintf(idx, "error invalid eggnet protocol for 'nlinked'\n");
  592. } else if ((in_chain(newbot)) || (!strcasecmp(newbot, conf.bot->nick))) {
  593. /* Loop! */
  594. putlog(LOG_BOTS, "*", "Loop detected %s (mutual: %s)", dcc[idx].nick, newbot);
  595. simple_snprintf(s, sizeof(s), "Detected loop: two bots exist named %s: disconnecting %s", newbot, dcc[idx].nick);
  596. dprintf(idx, "error Loop (%s)\n", newbot);
  597. }
  598. if (!s[0]) {
  599. for (p = newbot; *p; p++)
  600. if ((*p < 32) || (*p == 127))
  601. bogus = 1;
  602. i = nextbot(next);
  603. if (i != idx)
  604. bogus = 1;
  605. if (bogus) {
  606. putlog(LOG_BOTS, "*", "Bogus link notice from %s! (%s -> %s)", dcc[idx].nick, next, newbot);
  607. simple_snprintf(s, sizeof(s), "Bogus link notice from: %s Disconnected", dcc[idx].nick);
  608. dprintf(idx, "error Bogus link notice from (%s -> %s)\n", next, newbot);
  609. }
  610. }
  611. if (s[0]) {
  612. chatout("*** %s\n", s);
  613. botnet_send_unlinked(idx, dcc[idx].nick, s);
  614. dprintf(idx, "bye %s\n", s);
  615. killsock(dcc[idx].sock);
  616. lostdcc(idx);
  617. return;
  618. }
  619. x = par[0];
  620. if (x)
  621. par++;
  622. else
  623. x = '-';
  624. if (par[0])
  625. newsplit(&par); /* vnum */
  626. if (par[0])
  627. vlocalhub = atoi(newsplit(&par));
  628. if (par[0])
  629. vbuildts = atol(newsplit(&par));
  630. if (par[0])
  631. vcommit = newsplit(&par);
  632. if (par[0])
  633. vversion = newsplit(&par);
  634. botnet_send_nlinked(idx, newbot, next, x, vlocalhub, vbuildts, vcommit, vversion);
  635. if (x == '!') {
  636. if (conf.bot->hub)
  637. chatout("*** (%s) %s %s.\n", next, "Linked to", newbot);
  638. else
  639. chatout("*** %s linked to botnet.\n", newbot);
  640. x = '-';
  641. }
  642. addbot(newbot, dcc[idx].nick, next, x, vlocalhub, vbuildts, vcommit, vversion ? vversion : (char *) "");
  643. }
  644. static void bot_unlinked(int idx, char *par)
  645. {
  646. int i;
  647. char *bot = NULL;
  648. bot = newsplit(&par);
  649. i = nextbot(bot);
  650. if ((i >= 0) && (i != idx)) /* Bot is NOT downstream along idx, so
  651. * BOGUS! */
  652. fake_alert(idx, "direction", bot, "unlinked");
  653. else if (i >= 0) { /* Valid bot downstream of idx */
  654. if (par[0])
  655. /* #ifdef HUB */
  656. chatout("*** (%s) %s\n", lastbot(bot), par);
  657. /*
  658. #else
  659. chatout("*** %s unlinked from botnet.\n", par);
  660. #endif
  661. */
  662. botnet_send_unlinked(idx, bot, par);
  663. unvia(idx, findbot(bot));
  664. rembot(bot);
  665. }
  666. /* Otherwise it's not even a valid bot, so just ignore! */
  667. }
  668. /* trace <from@bot> <dest> <chain:chain..>
  669. */
  670. static void bot_trace(int idx, char *par)
  671. {
  672. char *from = NULL, *dest = NULL;
  673. int i;
  674. from = newsplit(&par);
  675. dest = newsplit(&par);
  676. simple_snprintf(TBUF, sizeof(TBUF), "%s:%s", par, conf.bot->nick);
  677. botnet_send_traced(idx, from, TBUF);
  678. if (strcasecmp(dest, conf.bot->nick) && ((i = nextbot(dest)) > 0))
  679. botnet_send_trace(i, from, dest, par);
  680. }
  681. /* traced <to@bot> <chain:chain..>
  682. */
  683. static void bot_traced(int idx, char *par)
  684. {
  685. char *to = NULL, *p = NULL;
  686. int i, sock;
  687. to = newsplit(&par);
  688. p = strchr(to, '@');
  689. if (p == NULL)
  690. p = to;
  691. else {
  692. *p = 0;
  693. p++;
  694. }
  695. if (!strcasecmp(p, conf.bot->nick)) {
  696. time_t t = 0;
  697. char *p2 = par, *ss = TBUF;
  698. splitc(ss, to, ':');
  699. if (ss[0])
  700. sock = atoi(ss);
  701. else
  702. sock = (-1);
  703. if (par[0] == ':') {
  704. t = atoi(par + 1);
  705. p2 = strchr(par + 1, ':');
  706. if (p2)
  707. p2++;
  708. else
  709. p2 = par + 1;
  710. }
  711. for (i = 0; i < dcc_total; i++) {
  712. if (dcc[i].type && (dcc[i].type->flags & DCT_CHAT) && (!strcasecmp(dcc[i].nick, to)) &&
  713. ((sock == (-1)) || (sock == dcc[i].sock))) {
  714. if (t) {
  715. int j=0;
  716. register char *c = p2;
  717. for (; *c != '\0'; c++) if (*c == ':') j++;
  718. time_t tm;
  719. egg_timeval_t tv;
  720. timer_get_now(&tv);
  721. tm = ((tv.sec % 10000) * 100 + (tv.usec * 100) / (1000000)) - t;
  722. dprintf(i, "%s -> %s (%d.%d secs, %d hop%s)\n", "Trace result", p2,
  723. (int)(tm / 100), (int)(tm % 100), j, (j != 1) ? "s" : "");
  724. } else
  725. dprintf(i, "%s -> %s\n", "Trace result", p);
  726. }
  727. }
  728. } else {
  729. i = nextbot(p);
  730. if (p != to)
  731. *--p = '@';
  732. if (i >= 0)
  733. botnet_send_traced(i, to, par);
  734. }
  735. }
  736. static void bot_timesync(int idx, char *par)
  737. {
  738. // putlog(LOG_DEBUG, "@", "Got timesync from %s: %s (%li - %li)", dcc[idx].nick, par, atol(par), now);
  739. timesync = atol(par) - now;
  740. if (conf.bot->hub || conf.bot->localhub)
  741. send_timesync(-1);
  742. }
  743. /* reject <from> <bot>
  744. */
  745. static void bot_reject(int idx, char *par)
  746. {
  747. char *from = NULL, *who = NULL, *destbot = NULL, *frombot = NULL;
  748. struct userrec *u = NULL;
  749. int i;
  750. from = newsplit(&par);
  751. frombot = strchr(from, '@');
  752. if (frombot)
  753. frombot++;
  754. else
  755. frombot = from;
  756. i = nextbot(frombot);
  757. if (i != idx) {
  758. fake_alert(idx, "direction", frombot, "reject");
  759. return;
  760. }
  761. who = newsplit(&par);
  762. if (!(destbot = strchr(who, '@'))) {
  763. /* Rejecting a bot */
  764. i = nextbot(who);
  765. if (i < 0) {
  766. botnet_send_priv(idx, conf.bot->nick, from, NULL, "Can't unlink %s (doesn't exist)", who);
  767. } else if (!strcasecmp(dcc[i].nick, who)) {
  768. char s[1024];
  769. /* I'm the connection to the rejected bot */
  770. putlog(LOG_BOTS, "*", "%s rejected %s", from, dcc[i].nick);
  771. dprintf(i, "bye %s\n", par[0] ? par : "rejected");
  772. simple_sprintf(s, "Disconnected %s (%s: %s)", dcc[i].nick, from, par[0] ? par : "rejected");
  773. chatout("*** %s\n", s);
  774. botnet_send_unlinked(i, dcc[i].nick, s);
  775. killsock(dcc[i].sock);
  776. lostdcc(i);
  777. } else {
  778. if (i >= 0)
  779. botnet_send_reject(i, from, NULL, who, NULL, par);
  780. }
  781. } else { /* Rejecting user */
  782. *destbot++ = 0;
  783. if (!strcasecmp(destbot, conf.bot->nick)) {
  784. /* Kick someone here! */
  785. for (i = 0; i < dcc_total; i++) {
  786. if (dcc[i].type && dcc[i].simul == -1 && !strcasecmp(who, dcc[i].nick) && (dcc[i].type->flags & DCT_CHAT)) {
  787. u = get_user_by_handle(userlist, from);
  788. if (u) {
  789. if (!whois_access(u, dcc[idx].user)) {
  790. add_note(from, conf.bot->nick, "Sorry, you cannot boot them.", -1, 0);
  791. return;
  792. }
  793. do_boot(i, from, par);
  794. putlog(LOG_CMDS, "*", "#%s# boot %s (%s)", from, who, par[0] ? par : "No reason");
  795. }
  796. }
  797. }
  798. } else {
  799. i = nextbot(destbot);
  800. *--destbot = '@';
  801. if (i >= 0)
  802. botnet_send_reject(i, from, NULL, who, NULL, par);
  803. }
  804. }
  805. }
  806. static void bot_thisbot(int idx, char *par)
  807. {
  808. if (strcasecmp(par, dcc[idx].nick)) {
  809. char s[1024] = "";
  810. putlog(LOG_BOTS, "*", "Wrong bot--wanted %s, got %s", dcc[idx].nick, par);
  811. dprintf(idx, "bye imposter\n");
  812. simple_snprintf(s, sizeof(s), "Disconnected %s (imposter)", dcc[idx].nick);
  813. chatout("*** %s\n", s);
  814. botnet_send_unlinked(idx, dcc[idx].nick, s);
  815. unvia(idx, findbot(dcc[idx].nick));
  816. killsock(dcc[idx].sock);
  817. lostdcc(idx);
  818. return;
  819. }
  820. /* Set capitalization the way they want it */
  821. noshare = 1;
  822. change_handle(dcc[idx].user, par);
  823. noshare = 0;
  824. strlcpy(dcc[idx].nick, par, sizeof(dcc[idx].nick));
  825. }
  826. /* Used to send a direct msg from Tcl on one bot to Tcl on another
  827. * zapf <frombot> <tobot> <code [param]>
  828. */
  829. static void bot_zapf(int idx, char *par)
  830. {
  831. char *from = NULL, *to = NULL;
  832. int i;
  833. from = newsplit(&par);
  834. to = newsplit(&par);
  835. i = nextbot(from);
  836. if (i != idx) {
  837. fake_alert(idx, "direction", from, "zapf");
  838. return;
  839. }
  840. if (!strcasecmp(to, conf.bot->nick)) {
  841. /* For me! */
  842. char *opcode;
  843. opcode = newsplit(&par);
  844. check_bind_bot(from, opcode, par);
  845. return;
  846. } else {
  847. i = nextbot(to);
  848. if (i >= 0)
  849. botnet_send_zapf(i, from, to, par);
  850. }
  851. }
  852. /* Used to send a global msg from Tcl on one bot to every other bot
  853. * zapf-broad <frombot> <code [param]>
  854. */
  855. static void bot_zapfbroad(int idx, char *par)
  856. {
  857. char *from = NULL, *opcode = NULL;
  858. int i;
  859. from = newsplit(&par);
  860. opcode = newsplit(&par);
  861. i = nextbot(from);
  862. if (i != idx) {
  863. fake_alert(idx, "direction", from, "zapfb");
  864. return;
  865. }
  866. check_bind_bot(from, opcode, par);
  867. botnet_send_zapf_broad(idx, from, opcode, par);
  868. }
  869. static void bot_error(int idx, char *par)
  870. {
  871. putlog(LOG_MISC | LOG_BOTS, "*", "%s: %s", dcc[idx].nick, par);
  872. }
  873. /* nc <bot> <sock> <newnick>
  874. */
  875. static void bot_nickchange(int idx, char *par)
  876. {
  877. char *bot = NULL, *ssock = NULL, *newnick = NULL;
  878. int sock, i;
  879. bot = newsplit(&par);
  880. i = nextbot(bot);
  881. if (i != idx) {
  882. fake_alert(idx, "direction", bot, "nickchange_i");
  883. return;
  884. }
  885. ssock = newsplit(&par);
  886. sock = base64_to_int(ssock);
  887. newnick = newsplit(&par);
  888. i = partynick(bot, sock, newnick);
  889. if (i < 0) {
  890. fake_alert(idx, "sock#", ssock, "nickchange_ii");
  891. return;
  892. }
  893. chanout_but(-1, party[i].chan, "*** (%s) Nick change: %s -> %s\n",
  894. conf.bot->hub ? bot : "[botnet]", newnick, party[i].nick);
  895. botnet_send_nkch_part(idx, i, newnick);
  896. }
  897. /* join <bot> <nick> <chan> <flag><sock> <from>
  898. */
  899. static void bot_join(int idx, char *par)
  900. {
  901. char *bot = NULL, *nick = NULL, *x = NULL, *y = NULL;
  902. struct userrec *u = NULL;
  903. int i, sock, chan, i2, linking = 0;
  904. bot = newsplit(&par);
  905. if (bot[0] == '!') {
  906. linking = 1;
  907. bot++;
  908. }
  909. if (b_status(idx) & STAT_LINKING) {
  910. linking = 1;
  911. }
  912. nick = newsplit(&par);
  913. x = newsplit(&par);
  914. chan = base64_to_int(x);
  915. y = newsplit(&par);
  916. if ((chan < 0) || !y[0])
  917. return; /* Woops! pre 1.2.1's send .chat off'ers
  918. * too!! */
  919. if (!y[0]) {
  920. y[0] = '-';
  921. sock = 0;
  922. } else {
  923. sock = base64_to_int(y + 1);
  924. }
  925. i = nextbot(bot);
  926. if (i != idx) { /* Ok, garbage from a 1.0g (who uses that
  927. * now?) OR raistlin being evil :) */
  928. fake_alert(idx, "direction", bot, "join");
  929. return;
  930. }
  931. u = get_user_by_handle(userlist, nick);
  932. if (u) {
  933. simple_snprintf(TBUF, sizeof(TBUF), "@%s", bot);
  934. touch_laston(u, TBUF, now);
  935. }
  936. i = addparty(bot, nick, chan, y[0], sock, par, &i2);
  937. botnet_send_join_party(idx, linking, i2);
  938. if (i != chan) {
  939. if (i >= 0) {
  940. chanout_but(-1, i, "*** (%s) %s %s %s.\n", conf.bot->hub ? bot : "[botnet]", nick, "has left the", i ? "channel" : "party line");
  941. }
  942. if (!linking)
  943. chanout_but(-1, chan, "*** (%s) %s %s %s.\n", conf.bot->hub ? bot : "[botnet]", nick, "has joined the", chan ? "channel" : "party line");
  944. }
  945. }
  946. /* part <bot> <nick> <sock> [etc..]
  947. */
  948. static void bot_part(int idx, char *par)
  949. {
  950. char *bot = NULL, *nick = NULL, *etc = NULL;
  951. struct userrec *u = NULL;
  952. int sock, partyidx;
  953. int silent = 0;
  954. bot = newsplit(&par);
  955. if (bot[0] == '!') {
  956. silent = 1;
  957. bot++;
  958. }
  959. nick = newsplit(&par);
  960. etc = newsplit(&par);
  961. sock = base64_to_int(etc);
  962. u = get_user_by_handle(userlist, nick);
  963. if (u) {
  964. simple_snprintf(TBUF, sizeof(TBUF), "@%s", bot);
  965. touch_laston(u, TBUF, now);
  966. }
  967. if ((partyidx = getparty(bot, sock)) != -1) {
  968. if (!silent) {
  969. register int chan = party[partyidx].chan;
  970. if (par[0])
  971. chanout_but(-1, chan, "*** (%s) %s %s %s (%s).\n", conf.bot->hub ? bot : "[botnet]", nick,
  972. "has left the",
  973. chan ? "channel" : "party line", par);
  974. else
  975. chanout_but(-1, chan, "*** (%s) %s %s %s.\n", conf.bot->hub ? bot : "[botnet]", nick,
  976. "has left the",
  977. chan ? "channel" : "party line");
  978. }
  979. botnet_send_part_party(idx, partyidx, par, silent);
  980. remparty(bot, sock);
  981. }
  982. /* check if we have a remote idx for them */
  983. int i = 0;
  984. for (i = 0; i < dcc_total; i++) {
  985. /* This will potentially close all simul-idxs with matching nick, even though they may be connected multiple times
  986. but, it won't matter as a new will just be made as needed. */
  987. if (dcc[i].type && dcc[i].simul >= 0 && !strcasecmp(dcc[i].nick, nick)) {
  988. dcc[i].simul = -1;
  989. lostdcc(i);
  990. }
  991. }
  992. }
  993. /* away <bot> <sock> <message>
  994. * null message = unaway
  995. */
  996. static void bot_away(int idx, char *par)
  997. {
  998. char *bot = NULL, *etc = NULL;
  999. int sock, partyidx, linking = 0;
  1000. bot = newsplit(&par);
  1001. if (bot[0] == '!') {
  1002. linking = 1;
  1003. bot++;
  1004. }
  1005. if (b_status(idx) & STAT_LINKING) {
  1006. linking = 1;
  1007. }
  1008. etc = newsplit(&par);
  1009. sock = base64_to_int(etc);
  1010. if (par[0]) {
  1011. partystat(bot, sock, PLSTAT_AWAY, 0);
  1012. partyaway(bot, sock, par);
  1013. } else {
  1014. partystat(bot, sock, 0, PLSTAT_AWAY);
  1015. }
  1016. partyidx = getparty(bot, sock);
  1017. if (!linking) {
  1018. if (par[0])
  1019. chanout_but(-1, party[partyidx].chan,
  1020. "*** (%s) %s %s: %s.\n", conf.bot->hub ? bot : "[botnet]",
  1021. party[partyidx].nick, "is now away", par);
  1022. else
  1023. chanout_but(-1, party[partyidx].chan,
  1024. "*** (%s) %s %s.\n", conf.bot->hub ? bot : "[botnet]",
  1025. party[partyidx].nick, "is no longer away");
  1026. }
  1027. botnet_send_away(idx, bot, sock, par, linking);
  1028. }
  1029. /* (a courtesy info to help during connect bursts)
  1030. * idle <bot> <sock> <#secs> [away msg]
  1031. */
  1032. static void bot_idle(int idx, char *par)
  1033. {
  1034. char *bot = NULL, *work = NULL;
  1035. int sock, idle;
  1036. bot = newsplit(&par);
  1037. work = newsplit(&par);
  1038. sock = base64_to_int(work);
  1039. work = newsplit(&par);
  1040. idle = base64_to_int(work);
  1041. partysetidle(bot, sock, idle);
  1042. if (par[0]) {
  1043. partystat(bot, sock, PLSTAT_AWAY, 0);
  1044. partyaway(bot, sock, par);
  1045. }
  1046. botnet_send_idle(idx, bot, sock, idle, par);
  1047. }
  1048. void bot_share(int idx, char *par)
  1049. {
  1050. sharein(idx, par);
  1051. }
  1052. void bot_shareupdate(int idx, char *par)
  1053. {
  1054. updatein(idx, par);
  1055. }
  1056. /* v <frombot> <tobot> <idx:nick>
  1057. */
  1058. static void bot_versions(int sock, char *par)
  1059. {
  1060. char *frombot = newsplit(&par), *tobot = NULL, *from = NULL;
  1061. if (nextbot(frombot) != sock)
  1062. fake_alert(sock, "direction", frombot, "versions");
  1063. else if (strcasecmp(tobot = newsplit(&par), conf.bot->nick)) {
  1064. if ((sock = nextbot(tobot)) >= 0)
  1065. dprintf(sock, "v %s %s %s\n", frombot, tobot, par);
  1066. } else {
  1067. from = newsplit(&par);
  1068. botnet_send_priv(sock, conf.bot->nick, from, frombot, "Modules loaded:\n");
  1069. /* wtf?
  1070. for (me = module_list; me; me = me->next)
  1071. botnet_send_priv(sock, conf.bot->nick, from, frombot, " Module: %s\n", me->name);
  1072. */
  1073. botnet_send_priv(sock, conf.bot->nick, from, frombot, "End of module list.\n");
  1074. }
  1075. }
  1076. /* BOT COMMANDS
  1077. *
  1078. * function call should be:
  1079. * int bot_whatever(idx,"parameters");
  1080. *
  1081. * SORT these, dcc_bot uses a shortcut which requires them sorted
  1082. *
  1083. * yup, those are tokens there to allow a more efficient botnet as
  1084. * time goes on (death to slowly upgrading llama's)
  1085. */
  1086. botcmd_t C_bot[] =
  1087. {
  1088. {"a", bot_actchan, 0},
  1089. {"aw", bot_away, 0},
  1090. {"bye", bot_bye, 0},
  1091. {"c", bot_chan2, 0},
  1092. {"cp", bot_cmdpass, 0},
  1093. {"ct", bot_chat, 0},
  1094. {"e", bot_error, 0},
  1095. {"el", bot_endlink, 0},
  1096. {"i", bot_idle, 0},
  1097. {"j", bot_join, 0},
  1098. {"l", bot_link, 0},
  1099. {"lo", bot_log, 0},
  1100. {"n", bot_nlinked, 0},
  1101. {"nc", bot_nickchange, 0},
  1102. {"p", bot_priv, 0},
  1103. {"pi", bot_ping, 0},
  1104. {"po", bot_pong, 0},
  1105. {"pt", bot_part, 0},
  1106. {"r", bot_reject, 0},
  1107. {"rc", bot_remotecmd, 0},
  1108. {"rr", bot_remotereply, 0},
  1109. {"s", bot_share, 0},
  1110. {"sb", bot_shareupdate, 0},
  1111. {"si", bot_shellinfo, 0},
  1112. {"t", bot_trace, 0},
  1113. {"tb", bot_thisbot, 0},
  1114. {"td", bot_traced, 0},
  1115. {"ts", bot_timesync, 0},
  1116. {"u", bot_update, 0},
  1117. {"ul", bot_unlink, 0},
  1118. {"un", bot_unlinked, 0},
  1119. {"v", bot_versions, 0},
  1120. {"va", bot_set, 0},
  1121. {"vab", bot_setbroad, 0},
  1122. {"w", bot_who, 0},
  1123. {"z", bot_zapf, 0},
  1124. {"zb", bot_zapfbroad, 0},
  1125. {NULL, NULL, 0}
  1126. };
  1127. static int comp_botcmd_t(const void *m1, const void *m2) {
  1128. const botcmd_t *mi1 = (const botcmd_t *) m1;
  1129. const botcmd_t *mi2 = (const botcmd_t *) m2;
  1130. return strcasecmp(mi1->name, mi2->name);
  1131. }
  1132. const botcmd_t *search_botcmd_t(const botcmd_t *table, const char* keyString, size_t elements) {
  1133. botcmd_t key;
  1134. key.name = keyString;
  1135. return (const botcmd_t*) bsearch(&key, table, elements, sizeof(botcmd_t), comp_botcmd_t);
  1136. }
  1137. void parse_botcmd(int idx, const char* code, const char* msg) {
  1138. const botcmd_t *cmd = search_botcmd_t((const botcmd_t*)&C_bot, code, lengthof(C_bot) - 1);
  1139. if (cmd) {
  1140. /* Found a match */
  1141. if (have_cmd(NULL, cmd->type))
  1142. (cmd->func) (idx, (char*)msg);
  1143. }
  1144. }
  1145. void send_remote_simul(int idx, char *bot, char *cmd, char *par)
  1146. {
  1147. char msg[SGRAB - 110] = "";
  1148. simple_snprintf(msg, sizeof msg, "r-s %d %s %d %s %lu %s %s", idx, dcc[idx].nick, dcc[idx].u.chat->con_flags,
  1149. dcc[idx].u.chat->con_chan, dcc[idx].status, cmd, par);
  1150. putbot(bot, msg);
  1151. }
  1152. /* idx nick conmask cmd par */
  1153. static void bot_rsim(char *botnick, char *code, char *msg)
  1154. {
  1155. int ridx = -1, idx = -1, i = 0, rconmask;
  1156. unsigned long status = 0;
  1157. char *nick = NULL, *cmd = NULL, *rconchan = NULL, buf[UHOSTMAX] = "", *par = NULL, *parp = NULL;
  1158. struct userrec *u = get_user_by_handle(userlist, botnick);
  1159. if (bot_hublevel(u) == 999) {
  1160. putlog(LOG_WARN, "*", "BOTCMD received from a leaf. HIJACK.");
  1161. return;
  1162. }
  1163. par = parp = strdup(msg);
  1164. ridx = atoi(newsplit(&par));
  1165. nick = newsplit(&par);
  1166. rconmask = atoi(newsplit(&par));
  1167. rconchan = newsplit(&par);
  1168. if (egg_isdigit(par[0]))
  1169. status = (unsigned long) atoi(newsplit(&par));
  1170. cmd = newsplit(&par);
  1171. if (ridx < 0 || !nick || !cmd) {
  1172. free(parp);
  1173. return;
  1174. }
  1175. for (i = 0; i < dcc_total; i++) {
  1176. /* See if we can find a simul-idx for the same ridx/nick */
  1177. if (dcc[i].type && dcc[i].simul == ridx && !strcasecmp(dcc[i].nick, nick)) {
  1178. putlog(LOG_DEBUG, "*", "Simul found old idx for %s: %d (ridx: %d)", nick, i, ridx);
  1179. dcc[i].simultime = now;
  1180. idx = i;
  1181. break;
  1182. }
  1183. }
  1184. if (idx < 0) {
  1185. idx = new_dcc(&DCC_CHAT, sizeof(struct chat_info));
  1186. putlog(LOG_DEBUG, "*", "Making new idx for %s@%s: %d ridx: %d", nick, botnick, idx, ridx);
  1187. dcc[idx].sock = -1;
  1188. dcc[idx].timeval = now;
  1189. dcc[idx].simultime = now;
  1190. dcc[idx].simul = ridx;
  1191. dcc[idx].status = status;
  1192. strlcpy(dcc[idx].simulbot, botnick, sizeof(dcc[idx].simulbot));
  1193. dcc[idx].u.chat->con_flags = rconmask;
  1194. struct chat_info dummy;
  1195. strlcpy(dcc[idx].u.chat->con_chan, rconchan, sizeof(dummy.con_chan));
  1196. dcc[idx].u.chat->strip_flags = STRIP_ALL;
  1197. strlcpy(dcc[idx].nick, nick, sizeof(dcc[idx].nick));
  1198. simple_snprintf(buf, sizeof buf, "%s@%s", nick, botnick);
  1199. strlcpy(dcc[idx].host, buf, sizeof(dcc[idx].host));
  1200. dcc[idx].addr = 0L;
  1201. dcc[idx].user = get_user_by_handle(userlist, nick);
  1202. }
  1203. rmspace(par);
  1204. check_bind_dcc(cmd, idx, par);
  1205. free(parp);
  1206. }
  1207. void bounce_simul(int idx, char *buf)
  1208. {
  1209. char rmsg[SGRAB - 110] = "";
  1210. if (!buf || !buf[0] || !dcc[idx].simulbot || !dcc[idx].simulbot[0] || idx < 0)
  1211. return;
  1212. /* Truncate out the newline that was put in from the dprintf() */
  1213. char *p = strchr(buf, '\n');
  1214. if (p)
  1215. *p = 0;
  1216. simple_snprintf(rmsg, sizeof rmsg, "r-sr %d %s %s", dcc[idx].simul, dcc[idx].user->handle, buf); /* remote-simul[r]eturn idx buf */
  1217. putbot(dcc[idx].simulbot, rmsg);
  1218. }
  1219. static void bot_rsimr(char *botnick, char *code, char *msg)
  1220. {
  1221. if (msg[0]) {
  1222. char * par = strdup(msg), *parp = par;
  1223. int idx = atoi(newsplit(&par, ' ', 0));
  1224. char *nick = newsplit(&par, ' ', 0);
  1225. if (dcc[idx].type && (dcc[idx].type == &DCC_CHAT) && dcc[idx].user && !strcmp(dcc[idx].user->handle, nick)) {
  1226. dprintf(idx, "[%s] %s\n", botnick, par);
  1227. }
  1228. free(parp);
  1229. }
  1230. }
  1231. static void bot_rd(char* botnick, char* code, char* msg)
  1232. {
  1233. size_t len = atoi(newsplit(&msg));
  1234. if (msg[0]) {
  1235. int idx = atoi(newsplit(&msg));
  1236. if (msg[0])
  1237. dprintf_real(idx, msg, len, len);
  1238. }
  1239. }
  1240. static cmd_t my_bot[] =
  1241. {
  1242. {"rd", "", (Function) bot_rd, NULL, 0},
  1243. {"r-sr", "", (Function) bot_rsimr, NULL, HUB},
  1244. {"r-s", "", (Function) bot_rsim, NULL, 0},
  1245. {NULL, NULL, NULL, NULL, 0}
  1246. };
  1247. void init_botcmd()
  1248. {
  1249. add_builtins("bot", my_bot);
  1250. }