/[cvs]/eggdrop1.8/src/botcmd.c
ViewVC logotype

Contents of /eggdrop1.8/src/botcmd.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.2.2.2 - (show annotations) (download) (as text)
Tue Feb 8 22:06:01 2011 UTC (8 years, 3 months ago) by thommey
Branch: gettext
Changes since 1.2.2.1: +10 -16 lines
File MIME type: text/x-chdr
merge changes from master into gettext

1 /*
2 * botcmd.c -- handles:
3 * commands that comes across the botnet
4 * userfile transfer and update commands from sharebots
5 *
6 * $Id: botcmd.c,v 1.2.2.1 2010/11/10 13:39:19 pseudo Exp $
7 */
8 /*
9 * Copyright (C) 1997 Robey Pointer
10 * Copyright (C) 1999 - 2010 Eggheads Development Team
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 */
26
27 #include "main.h"
28 #include "tandem.h"
29 #include "users.h"
30 #include "chan.h"
31 #include "modules.h"
32
33 extern char botnetnick[], ver[], admin[], network[], motdfile[];
34 extern int dcc_total, remote_boots, noshare;
35 #ifdef TLS
36 extern int tls_vfybots;
37 extern int tls_vfyclients;
38 extern SSL_CTX *ssl_ctx;
39 #endif
40 extern struct dcc_t *dcc;
41 extern struct chanset_t *chanset;
42 extern struct userrec *userlist;
43 extern Tcl_Interp *interp;
44 extern time_t now, online_since;
45 extern party_t *party;
46 extern module_entry *module_list;
47
48 static char TBUF[1024]; /* Static buffer for goofy bot stuff */
49
50 static char base64to[256] = {
51 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
52 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
53 0, 0, 0, 0, 0, 0, 0, 0, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0,
54 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
55 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 62, 0, 63, 0, 0, 0, 26, 27, 28,
56 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
57 49, 50, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
58 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
59 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
60 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
61 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
62 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
63 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
64 };
65
66
67 int base64_to_int(char *buf)
68 {
69 int i = 0;
70
71 while (*buf) {
72 i = i << 6;
73 i += base64to[(int) *buf];
74 buf++;
75 }
76 return i;
77 }
78
79 /* Used for 1.0 compatibility: if a join message arrives with no sock#,
80 * i'll just grab the next "fakesock" # (incrementing to assure uniqueness)
81 */
82 static int fakesock = 2300;
83
84 static void fake_alert(int idx, char *item, char *extra)
85 {
86 static unsigned long lastfake; /* The last time fake_alert was used */
87
88 if (now - lastfake > 10) {
89 #ifndef NO_OLD_BOTNET
90 if (b_numver(idx) < NEAT_BOTNET)
91 dprintf(idx, "chat %s NOTICE: %s (%s != %s).\n",
92 botnetnick, _("Fake message rejected"), item, extra);
93 else
94 #endif
95 dprintf(idx, "ct %s NOTICE: %s (%s != %s).\n",
96 botnetnick, _("Fake message rejected"), item, extra);
97 putlog(LOG_BOTS, "*", _("%s Fake message rejected (%s != %s)."),
98 dcc[idx].nick, item, extra);
99 lastfake = now;
100 }
101 }
102
103 /* chan <from> <chan> <text>
104 */
105 static void bot_chan2(int idx, char *msg)
106 {
107 char *from, *p, *s;
108 int i, chan;
109
110 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
111 return;
112 from = newsplit(&msg);
113 p = newsplit(&msg);
114 #ifndef NO_OLD_BOTNET
115 if (b_numver(idx) < NEAT_BOTNET)
116 chan = atoi(p);
117 else
118 #endif
119 chan = base64_to_int(p);
120 /* Strip annoying control chars */
121 for (p = s = from; *s; s++)
122 if ((*s > 31) && (*s != 127))
123 *p++ = *s;
124 if (*p)
125 *p = 0;
126 p = strchr(from, '@');
127 if (p) {
128 snprintf(TBUF, sizeof(TBUF), "<%s> %s", from, msg);
129 *p = 0;
130 if (!partyidle(p + 1, from)) {
131 *p = '@';
132 fake_alert(idx, "user", from);
133 return;
134 }
135 *p = '@';
136 p++;
137 } else {
138 sprintf(TBUF, "*** (%s) %s", from, msg);
139 p = from;
140 }
141 i = nextbot(p);
142 if (i != idx) {
143 fake_alert(idx, "direction", p);
144 } else {
145 chanout_but(-1, chan, "%s\n", TBUF);
146 /* Send to new version bots */
147 if (i >= 0)
148 botnet_send_chan(idx, from, NULL, chan, msg);
149 if (strchr(from, '@') != NULL)
150 check_tcl_chat(from, chan, msg);
151 else
152 check_tcl_bcst(from, chan, msg);
153 }
154 }
155
156 /* chat <from> <notice> -- only from bots
157 */
158 static void bot_chat(int idx, char *par)
159 {
160 char *from;
161 int i;
162
163 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
164 return;
165 from = newsplit(&par);
166 if (strchr(from, '@') != NULL) {
167 fake_alert(idx, "bot", from);
168 return;
169 }
170 /* Make sure the bot is valid */
171 i = nextbot(from);
172 if (i != idx) {
173 fake_alert(idx, "direction", from);
174 return;
175 }
176 chatout("*** (%s) %s\n", from, par);
177 botnet_send_chat(idx, from, par);
178 check_tcl_bcst(from, -1, par);
179 }
180
181 /* actchan <from> <chan> <text>
182 */
183 static void bot_actchan(int idx, char *par)
184 {
185 char *from, *p, *s;
186 int i, chan;
187
188 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
189 return;
190 from = newsplit(&par);
191 p = strchr(from, '@');
192 if (p == NULL) {
193 /* How can a bot do an action? */
194 fake_alert(idx, "user@bot", from);
195 return;
196 }
197 *p = 0;
198 if (!partyidle(p + 1, from)) {
199 *p = '@';
200 fake_alert(idx, "user", from);
201 return;
202 }
203 *p = '@';
204 p++;
205 i = nextbot(p);
206 if (i != idx) {
207 fake_alert(idx, "direction", p);
208 return;
209 }
210 p = newsplit(&par);
211 #ifndef NO_OLD_BOTNET
212 if (b_numver(idx) < NEAT_BOTNET)
213 chan = atoi(p);
214 else
215 #endif
216 chan = base64_to_int(p);
217 for (p = s = from; *s; s++)
218 if ((*s > 31) && (*s != 127))
219 *p++ = *s;
220 if (*p)
221 *p = 0;
222 chanout_but(-1, chan, "* %s %s\n", from, par);
223 botnet_send_act(idx, from, NULL, chan, par);
224 check_tcl_act(from, chan, par);
225 }
226
227 /* priv <from> <to> <message>
228 */
229 static void bot_priv(int idx, char *par)
230 {
231 char *from, *p, *to = TBUF, *tobot;
232 int i;
233
234 from = newsplit(&par);
235 tobot = newsplit(&par);
236 splitc(to, tobot, '@');
237 p = strchr(from, '@');
238 if (p != NULL)
239 p++;
240 else
241 p = from;
242 i = nextbot(p);
243 if (i != idx) {
244 fake_alert(idx, "direction", p);
245 return;
246 }
247 if (!to[0])
248 return; /* Silently ignore notes to '@bot' */
249 if (!egg_strcasecmp(tobot, botnetnick)) { /* For me! */
250 if (p == from)
251 add_note(to, from, par, -2, 0);
252 else {
253 i = add_note(to, from, par, -1, 0);
254 if (from[0] != '@')
255 switch (i) {
256 case NOTE_ERROR:
257 botnet_send_priv(idx, botnetnick, from, NULL,
258 _("No such user %s."), to);
259 break;
260 case NOTE_STORED:
261 botnet_send_priv(idx, botnetnick, from, NULL,
262 _("Not online; note stored."));
263 break;
264 case NOTE_FULL:
265 botnet_send_priv(idx, botnetnick, from, NULL,
266 _("Notebox is full, sorry."));
267 break;
268 case NOTE_AWAY:
269 botnet_send_priv(idx, botnetnick, from, NULL,
270 _("%s is away; note stored."), to);
271 break;
272 case NOTE_FWD:
273 botnet_send_priv(idx, botnetnick, from, NULL,
274 _("Not online; note forwarded to: %s"), to);
275 break;
276 case NOTE_REJECT:
277 botnet_send_priv(idx, botnetnick, from, NULL,
278 _("%s rejected your note."), to);
279 break;
280 case NOTE_TCL:
281 break; /* Do nothing */
282 case NOTE_OK:
283 botnet_send_priv(idx, botnetnick, from, NULL,
284 _("Note sent to %s."), to);
285 break;
286 }
287 }
288 } else { /* Pass it on */
289 i = nextbot(tobot);
290 if (i >= 0)
291 botnet_send_priv(i, from, to, tobot, "%s", par);
292 }
293 }
294
295 static void bot_bye(int idx, char *par)
296 {
297 char s[1024];
298 int users, bots;
299
300 bots = bots_in_subtree(findbot(dcc[idx].nick));
301 users = users_in_subtree(findbot(dcc[idx].nick));
302 simple_sprintf(s, _("Disconnected from: %s. %s (lost %d %s and %d %s)"),
303 dcc[idx].nick, par[0] ? par : "No reason",
304 bots, P_("bot", "bots", bots),
305 users, P_("user", "users", users));
306 putlog(LOG_BOTS, "*", "%s", s);
307 chatout("*** %s\n", s);
308 botnet_send_unlinked(idx, dcc[idx].nick, s);
309 dprintf(idx, "*bye\n");
310 killsock(dcc[idx].sock);
311 lostdcc(idx);
312 }
313
314 static void remote_tell_who(int idx, char *nick, int chan)
315 {
316 int i = 10, k, l, ok = 0;
317 char s[1024], *realnick;
318 struct chanset_t *c;
319
320 realnick = strchr(nick, ':');
321 if (realnick)
322 realnick++;
323 else
324 realnick = nick;
325 putlog(LOG_BOTS, "*", "#%s# who", realnick);
326 strcpy(s, _("Channels: "));
327 for (c = chanset; c; c = c->next)
328 if (!channel_secret(c) && !channel_inactive(c)) {
329 l = strlen(c->dname);
330 if (i + l < 1021) {
331 if (i > 10)
332 sprintf(s, "%s, %s", s, c->dname);
333 else {
334 strcpy(s, c->dname);
335 i += (l + 2);
336 }
337 }
338 }
339 if (i > 10) {
340 botnet_send_priv(idx, botnetnick, nick, NULL, "%s (%s)", s, ver);
341 } else
342 botnet_send_priv(idx, botnetnick, nick, NULL, _("no channels (%s)"), ver);
343 if (admin[0])
344 botnet_send_priv(idx, botnetnick, nick, NULL, _("Admin: %s"), admin);
345 if (chan == 0)
346 botnet_send_priv(idx, botnetnick, nick, NULL, _("Party line members: "
347 "(* = owner, + = master, %% = botmaster, "
348 "@ = op, ^ = halfop)"));
349 else {
350 simple_sprintf(s, "assoc %d", chan);
351 if ((Tcl_Eval(interp, s) != TCL_OK) || tcl_resultempty())
352 botnet_send_priv(idx, botnetnick, nick, NULL, _("People on channel %s%d: "
353 "(* = owner, + = master, %% = botmaster, @ = op, "
354 "^ = halfop)\n"), (chan < GLOBAL_CHANS) ? "" : "*",
355 chan % GLOBAL_CHANS);
356 else
357 botnet_send_priv(idx, botnetnick, nick, NULL, _("People on channel '%s' "
358 "(%s%d): (* = owner, + = master, %% = botmaster, "
359 "@ = op, ^ = halfop)\n"), tcl_resultstring(),
360 (chan < GLOBAL_CHANS) ? "" : "*", chan % GLOBAL_CHANS);
361 }
362 for (i = 0; i < dcc_total; i++)
363 if (dcc[i].type->flags & DCT_REMOTEWHO)
364 if (dcc[i].u.chat->channel == chan) {
365 k = sprintf(s, " %c%-15s %s", (geticon(i) == '-' ? ' ' : geticon(i)),
366 dcc[i].nick, dcc[i].host);
367 if (now - dcc[i].timeval > 300) {
368 unsigned long days, hrs, mins;
369
370 days = (now - dcc[i].timeval) / 86400;
371 hrs = ((now - dcc[i].timeval) - (days * 86400)) / 3600;
372 mins = ((now - dcc[i].timeval) - (hrs * 3600)) / 60;
373 if (days > 0)
374 sprintf(s + k, _(" (idle %lud%luh)"), days, hrs);
375 else if (hrs > 0)
376 sprintf(s + k, _(" (idle %luh%lum)"), hrs, mins);
377 else
378 sprintf(s + k, _(" (idle %lum)"), mins);
379 }
380 botnet_send_priv(idx, botnetnick, nick, NULL, "%s", s);
381 if (dcc[i].u.chat->away != NULL)
382 botnet_send_priv(idx, botnetnick, nick, NULL, _(" AWAY: %s"),
383 dcc[i].u.chat->away);
384 }
385 for (i = 0; i < dcc_total; i++)
386 if (dcc[i].type == &DCC_BOT) {
387 if (!ok) {
388 ok = 1;
389 botnet_send_priv(idx, botnetnick, nick, NULL, _("Bots connected:"));
390 }
391 sprintf(s, " %s%c%-15s %s",
392 dcc[i].status & STAT_CALLED ? "<-" : "->",
393 dcc[i].status & STAT_SHARE ? '+' : ' ',
394 dcc[i].nick, dcc[i].u.bot->version);
395 botnet_send_priv(idx, botnetnick, nick, NULL, "%s", s);
396 }
397 ok = 0;
398 for (i = 0; i < dcc_total; i++)
399 if (dcc[i].type->flags & DCT_REMOTEWHO)
400 if (dcc[i].u.chat->channel != chan) {
401 if (!ok) {
402 ok = 1;
403 botnet_send_priv(idx, botnetnick, nick, NULL,
404 _("Other people on the bot:"));
405 }
406 l = sprintf(s, " %c%-15s %s", (geticon(i) == '-' ? ' ' : geticon(i)),
407 dcc[i].nick, dcc[i].host);
408 if (now - dcc[i].timeval > 300) {
409 k = (now - dcc[i].timeval) / 60;
410 if (k < 60)
411 sprintf(s + l, _(" (idle %dm)"), k);
412 else
413 sprintf(s + l, _(" (idle %dh%dm)"), k / 60, k % 60);
414 }
415 botnet_send_priv(idx, botnetnick, nick, NULL, "%s", s);
416 if (dcc[i].u.chat->away != NULL)
417 botnet_send_priv(idx, botnetnick, nick, NULL,
418 _(" AWAY: %s"), dcc[i].u.chat->away);
419 }
420 }
421
422 /* who <from@bot> <tobot> <chan#>
423 */
424 static void bot_who(int idx, char *par)
425 {
426 char *from, *to, *p;
427 int i, chan;
428
429 from = newsplit(&par);
430 p = strchr(from, '@');
431 if (!p) {
432 sprintf(TBUF, "%s@%s", from, dcc[idx].nick);
433 from = TBUF;
434 }
435 to = newsplit(&par);
436 if (!egg_strcasecmp(to, botnetnick))
437 to[0] = 0;
438 #ifndef NO_OLD_BOTNET
439 if (b_numver(idx) < NEAT_BOTNET)
440 chan = atoi(par);
441 else
442 #endif
443 chan = base64_to_int(par);
444 if (to[0]) {
445 i = nextbot(to);
446 if (i >= 0)
447 botnet_send_who(i, from, to, chan);
448 } else
449 remote_tell_who(idx, from, chan);
450 }
451
452 static void bot_endlink(int idx, char *par)
453 {
454 dcc[idx].status &= ~STAT_LINKING;
455 }
456
457 /* info? <from@bot> -> send priv
458 */
459 static void bot_infoq(int idx, char *par)
460 {
461 char s[200], s2[32], *realnick;
462 struct chanset_t *chan;
463 time_t now2;
464 int hr, min;
465
466 /* Strip the idx from user@bot */
467 realnick = strchr(par, ':');
468 if (realnick)
469 realnick++;
470 else
471 realnick = par;
472 putlog(LOG_BOTS, "*", "#%s# botinfo", realnick);
473
474 now2 = now - online_since;
475 s2[0] = 0;
476 if (now2 > 86400) {
477 int days = now2 / 86400;
478
479 /* Days */
480 sprintf(s2, "%d %s,", days, P_("day", "days", days));
481 now2 -= days * 86400;
482 }
483 hr = (time_t) ((int) now2 / 3600);
484 now2 -= (hr * 3600);
485 min = (time_t) ((int) now2 / 60);
486 sprintf(&s2[strlen(s2)], "%02d:%02d", (int) hr, (int) min);
487 if (module_find("server", 0, 0)) {
488 s[0] = 0;
489 for (chan = chanset; chan; chan = chan->next) {
490 if (!channel_secret(chan)) {
491 if ((strlen(s) + strlen(chan->dname) + strlen(network)
492 + strlen(botnetnick) + strlen(ver) + 1) >= 200) {
493 strcat(s, "++ ");
494 break; /* Yegads..! */
495 }
496 strcat(s, chan->dname);
497 strcat(s, ", ");
498 }
499 }
500 if (s[0]) {
501 s[strlen(s) - 2] = 0;
502 botnet_send_priv(idx, botnetnick, par, NULL,
503 _("%s <%s> (%s) [UP %s]"), ver, network, s, s2);
504 } else
505 botnet_send_priv(idx, botnetnick, par, NULL, _("%s <%s> (no channels) "
506 "[UP %s]"), ver, network, s2);
507 } else
508 botnet_send_priv(idx, botnetnick, par, NULL,
509 _("%s <NO_IRC> [UP %s]"), ver, s2);
510 botnet_send_infoq(idx, par);
511 }
512
513 static void bot_ping(int idx, char *par)
514 {
515 botnet_send_pong(idx);
516 }
517
518 static void bot_pong(int idx, char *par)
519 {
520 dcc[idx].status &= ~STAT_PINGED;
521 }
522
523 /* link <from@bot> <who> <to-whom>
524 */
525 static void bot_link(int idx, char *par)
526 {
527 char *from, *bot, *rfrom;
528 int i;
529
530 from = newsplit(&par);
531 bot = newsplit(&par);
532
533 if (!egg_strcasecmp(bot, botnetnick)) {
534 if ((rfrom = strchr(from, ':')))
535 rfrom++;
536 else
537 rfrom = from;
538 putlog(LOG_CMDS, "*", "#%s# link %s", rfrom, par);
539 if (botlink(from, -1, par))
540 botnet_send_priv(idx, botnetnick, from, NULL,
541 _("Attempting to link %s ..."), par);
542 else
543 botnet_send_priv(idx, botnetnick, from, NULL, _("Can't link there."));
544 } else {
545 i = nextbot(bot);
546 if (i >= 0)
547 botnet_send_link(i, from, bot, par);
548 }
549 }
550
551 /* unlink <from@bot> <linking-bot> <undesired-bot> <reason>
552 */
553 static void bot_unlink(int idx, char *par)
554 {
555 char *from, *bot, *rfrom, *p, *undes;
556 int i;
557
558 from = newsplit(&par);
559 bot = newsplit(&par);
560 undes = newsplit(&par);
561 if (!egg_strcasecmp(bot, botnetnick)) {
562 if ((rfrom = strchr(from, ':')))
563 rfrom++;
564 else
565 rfrom = from;
566 putlog(LOG_CMDS, "*", "#%s# unlink %s (%s)", rfrom, undes, par[0] ? par :
567 "No reason");
568 i = botunlink(-3, undes, par[0] ? par : NULL, rfrom);
569 if (i == 1) {
570 p = strchr(from, '@');
571 if (p) {
572 /* idx will change after unlink -- get new idx
573 *
574 * TODO: This has changed with the new lostdcc() behaviour. Check
575 * if we can optimise the situation.
576 */
577 i = nextbot(p + 1);
578 if (i >= 0)
579 botnet_send_priv(i, botnetnick, from, NULL,
580 "Unlinked from %s.", undes);
581 }
582 } else if (i == 0) {
583 botnet_send_unlinked(-1, undes, "");
584 p = strchr(from, '@');
585 if (p) {
586 /* Ditto above, about idx */
587 i = nextbot(p + 1);
588 if (i >= 0)
589 botnet_send_priv(i, botnetnick, from, NULL,
590 _("Can't unlink %s."), undes);
591 }
592 } else {
593 p = strchr(from, '@');
594 if (p) {
595 i = nextbot(p + 1);
596 if (i >= 0)
597 botnet_send_priv(i, botnetnick, from, NULL,
598 _("Can't remotely unlink sharebots."));
599 }
600 }
601 } else {
602 i = nextbot(bot);
603 if (i >= 0)
604 botnet_send_unlink(i, from, bot, undes, par);
605 }
606 }
607
608 /* Bot next share?
609 */
610 static void bot_update(int idx, char *par)
611 {
612 char *bot, x;
613 int vnum;
614
615 bot = newsplit(&par);
616 x = par[0];
617 if (x)
618 par++;
619 #ifndef NO_OLD_BOTNET
620 if (b_numver(idx) < NEAT_BOTNET)
621 vnum = atoi(par);
622 else
623 #endif
624 vnum = base64_to_int(par);
625 if (in_chain(bot))
626 updatebot(idx, bot, x, vnum);
627 }
628
629 /* Newbot next share?
630 */
631 static void bot_nlinked(int idx, char *par)
632 {
633 char *newbot, *next, *p, s[1024], x;
634 int bogus = 0, i;
635 struct userrec *u;
636
637 newbot = newsplit(&par);
638 next = newsplit(&par);
639 s[0] = 0;
640 if (!next[0]) {
641 putlog(LOG_BOTS, "*", _("Invalid eggnet protocol from %s (zapfing)"),
642 dcc[idx].nick);
643 simple_sprintf(s, _("Disconnected %s (invalid bot)"), dcc[idx].nick);
644 dprintf(idx, "error invalid eggnet protocol for 'nlinked'\n");
645 } else if ((in_chain(newbot)) || (!egg_strcasecmp(newbot, botnetnick))) {
646 /* Loop! */
647 putlog(LOG_BOTS, "*", _("Loop detected %s (mutual: %s)"),
648 dcc[idx].nick, newbot);
649 simple_sprintf(s, _("Detected loop: two bots exist named %s: "
650 "disconnecting %s"), newbot, dcc[idx].nick);
651 dprintf(idx, "error Loop (%s)\n", newbot);
652 }
653 if (!s[0]) {
654 for (p = newbot; *p; p++)
655 if ((*p < 32) || (*p == 127) || ((p - newbot) >= HANDLEN))
656 bogus = 1;
657 i = nextbot(next);
658 if (i != idx)
659 bogus = 1;
660 }
661 if (bogus) {
662 putlog(LOG_BOTS, "*", _("Bogus link notice from %s! (%s -> %s)"),
663 dcc[idx].nick, next, newbot);
664 simple_sprintf(s, _("Bogus link notice from: %s. Disconnected"),
665 dcc[idx].nick);
666 dprintf(idx, "error %s (%s -> %s)\n", _("Bogus link notice from"),
667 next, newbot);
668 }
669 if (bot_flags(dcc[idx].user) & BOT_LEAF) {
670 putlog(LOG_BOTS, "*", _("Disconnected left %s (Linked to %s)"),
671 dcc[idx].nick, newbot);
672 simple_sprintf(s, _("Illegal link by leaf %s (to %s): Disconnected"),
673 dcc[idx].nick, newbot);
674 dprintf(idx, "error %s\n", _("You are supposed to be a leaf!"));
675 }
676 if (s[0]) {
677 chatout("*** %s\n", s);
678 botnet_send_unlinked(idx, dcc[idx].nick, s);
679 dprintf(idx, "bye %s\n", _("Illegal link by leaf"));
680 killsock(dcc[idx].sock);
681 lostdcc(idx);
682 return;
683 }
684 x = par[0];
685 if (x)
686 par++;
687 else
688 x = '-';
689 #ifndef NO_OLD_BOTNET
690 if (b_numver(idx) < NEAT_BOTNET)
691 i = atoi(par);
692 else
693 #endif
694 i = base64_to_int(par);
695 botnet_send_nlinked(idx, newbot, next, x, i);
696 if (x == '!') {
697 chatout(_("*** (%s) Linked to %s.\n"), next, newbot);
698 x = '-';
699 }
700 addbot(newbot, dcc[idx].nick, next, x, i);
701 check_tcl_link(newbot, next);
702 u = get_user_by_handle(userlist, newbot);
703 if (bot_flags(u) & BOT_REJECT) {
704 botnet_send_reject(idx, botnetnick, NULL, newbot, NULL, NULL);
705 putlog(LOG_BOTS, "*", _("Rejecting bot %s from %s"), newbot,
706 dcc[idx].nick);
707 }
708 }
709
710 #ifndef NO_OLD_BOTNET
711 static void bot_linked(int idx, char *par)
712 {
713 char s[1024];
714 int bots, users;
715
716 bots = bots_in_subtree(findbot(dcc[idx].nick));
717 users = users_in_subtree(findbot(dcc[idx].nick));
718 putlog(LOG_BOTS, "*", _("Older bot detected (unsupported)"));
719 simple_sprintf(s, _("Disconnected %s (outdated) (lost %d %s and %d %s"),
720 dcc[idx].nick, bots, P_("bot", "bots", bots),
721 users, P_("user", "users", users));
722 chatout("*** %s\n", s);
723 botnet_send_unlinked(idx, dcc[idx].nick, s);
724 killsock(dcc[idx].sock);
725 lostdcc(idx);
726 }
727 #endif /* !NO_OLD_BOTNET */
728
729 static void bot_unlinked(int idx, char *par)
730 {
731 int i;
732 char *bot;
733
734 bot = newsplit(&par);
735 i = nextbot(bot);
736 if ((i >= 0) && (i != idx)) /* Bot is NOT downstream along idx, so
737 * BOGUS! */
738 fake_alert(idx, "direction", bot);
739 else if (i >= 0) { /* Valid bot downstream of idx */
740 if (par[0])
741 chatout("*** (%s) %s\n", lastbot(bot), par);
742 botnet_send_unlinked(idx, bot, par);
743 unvia(idx, findbot(bot));
744 rembot(bot);
745 }
746 /* Otherwise it's not even a valid bot, so just ignore! */
747 }
748
749 /* trace <from@bot> <dest> <chain:chain..>
750 */
751 static void bot_trace(int idx, char *par)
752 {
753 char *from, *dest;
754 int i;
755
756 from = newsplit(&par);
757 dest = newsplit(&par);
758 simple_sprintf(TBUF, "%s:%s", par, botnetnick);
759 botnet_send_traced(idx, from, TBUF);
760 if (egg_strcasecmp(dest, botnetnick) && ((i = nextbot(dest)) > 0))
761 botnet_send_trace(i, from, dest, par);
762 }
763
764 /* traced <to@bot> <chain:chain..>
765 */
766 static void bot_traced(int idx, char *par)
767 {
768 char *to, *p;
769 int i, sock;
770
771 to = newsplit(&par);
772 p = strchr(to, '@');
773 if (p == NULL)
774 p = to;
775 else {
776 *p = 0;
777 p++;
778 }
779 if (!egg_strcasecmp(p, botnetnick)) {
780 time_t t = 0;
781 char *p = par, *ss = TBUF;
782
783 splitc(ss, to, ':');
784 if (ss[0])
785 sock = atoi(ss);
786 else
787 sock = -1;
788 if (par[0] == ':') {
789 t = atoi(par + 1);
790 p = strchr(par + 1, ':');
791 if (p)
792 p++;
793 else
794 p = par + 1;
795 }
796 for (i = 0; i < dcc_total; i++)
797 if ((dcc[i].type->flags & DCT_CHAT) &&
798 (!egg_strcasecmp(dcc[i].nick, to)) &&
799 ((sock == -1) || (sock == dcc[i].sock))) {
800 if (t) {
801 int j = 0;
802
803 {
804 register char *c = p;
805
806 for (; *c != '\0'; c++)
807 if (*c == ':')
808 j++;
809 }
810 dprintf(i, _("Trace result -> %s (%lu secs, %d %s)\n"), p, now - t,
811 P_("sec", "secs", now - t), j, P_("hop", "hops", j));
812 } else
813 dprintf(i, _("Trace result -> %s\n"), p);
814 }
815 } else {
816 i = nextbot(p);
817 if (p != to)
818 *--p = '@';
819 if (i >= 0)
820 botnet_send_traced(i, to, par);
821 }
822 }
823
824 /* reject <from> <bot>
825 */
826 static void bot_reject(int idx, char *par)
827 {
828 char *from, *who, *destbot, *frombot;
829 struct userrec *u;
830 int i;
831
832 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
833 return;
834 from = newsplit(&par);
835 frombot = strchr(from, '@');
836 if (frombot)
837 frombot++;
838 else
839 frombot = from;
840 i = nextbot(frombot);
841 if (i != idx) {
842 fake_alert(idx, "direction", frombot);
843 return;
844 }
845 who = newsplit(&par);
846 if (!(destbot = strchr(who, '@'))) {
847 /* Rejecting a bot */
848 i = nextbot(who);
849 if (i < 0) {
850 botnet_send_priv(idx, botnetnick, from, NULL,
851 _("Can't unlink %s (doesn't exist)"), who);
852 } else if (!egg_strcasecmp(dcc[i].nick, who)) {
853 char s[1024];
854
855 /* I'm the connection to the rejected bot */
856 putlog(LOG_BOTS, "*", _("%s rejected %s"), from, dcc[i].nick);
857 dprintf(i, "bye %s\n", par[0] ? par : "rejected");
858 if (par[0])
859 simple_sprintf(s, _("Disconnected %s (%s: %s)"), dcc[i].nick,
860 from, par);
861 else
862 simple_sprintf(s, _("Disconnected %s (%s: rejected)"),
863 dcc[i].nick, from);
864 chatout("*** %s\n", s);
865 botnet_send_unlinked(i, dcc[i].nick, s);
866 killsock(dcc[i].sock);
867 lostdcc(i);
868 } else {
869 if (i >= 0)
870 botnet_send_reject(i, from, NULL, who, NULL, par);
871 }
872 } else { /* Rejecting user */
873 *destbot++ = 0;
874 if (!egg_strcasecmp(destbot, botnetnick)) {
875 /* Kick someone here! */
876 int ok = 0;
877
878 if (remote_boots == 1) {
879 frombot = strchr(from, '@');
880 if (frombot == NULL)
881 frombot = from;
882 else
883 frombot++;
884 u = get_user_by_handle(userlist, frombot);
885 if (!(bot_flags(u) & BOT_SHARE)) {
886 add_note(from, botnetnick, _("No non sharebot boots."), -1, 0);
887 ok = 1;
888 }
889 } else if (remote_boots == 0) {
890 botnet_send_priv(idx, botnetnick, from, NULL,
891 _("Remote boots are not allowed."));
892 ok = 1;
893 }
894 for (i = 0; (i < dcc_total) && (!ok); i++)
895 if ((!egg_strcasecmp(who, dcc[i].nick)) &&
896 (dcc[i].type->flags & DCT_CHAT)) {
897 u = get_user_by_handle(userlist, dcc[i].nick);
898 if (u && (u->flags & USER_OWNER)) {
899 add_note(from, botnetnick, _("Can't boot the bot owner."), -1, 0);
900 return;
901 }
902 do_boot(i, from, par);
903 ok = 1;
904 putlog(LOG_CMDS, "*", "#%s# boot %s (%s)", from, who,
905 par[0] ? par : _("No reason"));
906 }
907 } else {
908 i = nextbot(destbot);
909 *--destbot = '@';
910 if (i >= 0)
911 botnet_send_reject(i, from, NULL, who, NULL, par);
912 }
913 }
914 }
915
916 static void bot_thisbot(int idx, char *par)
917 {
918 if (egg_strcasecmp(par, dcc[idx].nick)) {
919 char s[1024];
920
921 putlog(LOG_BOTS, "*", _("Wrong bot--wanted %s, got %s"), dcc[idx].nick, par);
922 dprintf(idx, "bye %s\n", _("imposter"));
923 simple_sprintf(s, _("Disconnected %s (imposter)"), dcc[idx].nick);
924 chatout("*** %s\n", s);
925 botnet_send_unlinked(idx, dcc[idx].nick, s);
926 unvia(idx, findbot(dcc[idx].nick));
927 killsock(dcc[idx].sock);
928 lostdcc(idx);
929 return;
930 }
931 if (bot_flags(dcc[idx].user) & BOT_LEAF)
932 dcc[idx].status |= STAT_LEAF;
933 /* Set capitalization the way they want it */
934 noshare = 1;
935 change_handle(dcc[idx].user, par);
936 noshare = 0;
937 strcpy(dcc[idx].nick, par);
938 }
939
940 static void bot_handshake(int idx, char *par)
941 {
942 struct userrec *u = get_user_by_handle(userlist, dcc[idx].nick);
943
944 /* We *don't* want botnet passwords migrating */
945 noshare = 1;
946 set_user(&USERENTRY_PASS, u, par);
947 noshare = 0;
948 }
949
950 /* Used to send a direct msg from Tcl on one bot to Tcl on another
951 * zapf <frombot> <tobot> <code [param]>
952 */
953 static void bot_zapf(int idx, char *par)
954 {
955 char *from, *to;
956 int i;
957
958 from = newsplit(&par);
959 to = newsplit(&par);
960 i = nextbot(from);
961 if (i != idx) {
962 fake_alert(idx, "direction", from);
963 return;
964 }
965 if (!egg_strcasecmp(to, botnetnick)) {
966 /* For me! */
967 char *opcode;
968
969 opcode = newsplit(&par);
970 check_tcl_bot(from, opcode, par);
971 return;
972 }
973 i = nextbot(to);
974 if (i >= 0)
975 botnet_send_zapf(i, from, to, par);
976 }
977
978 /* Used to send a global msg from Tcl on one bot to every other bot
979 * zapf-broad <frombot> <code [param]>
980 */
981 static void bot_zapfbroad(int idx, char *par)
982 {
983 char *from, *opcode;
984 int i;
985
986 from = newsplit(&par);
987 opcode = newsplit(&par);
988
989 i = nextbot(from);
990 if (i != idx) {
991 fake_alert(idx, "direction", from);
992 return;
993 }
994 check_tcl_bot(from, opcode, par);
995 botnet_send_zapf_broad(idx, from, opcode, par);
996 }
997
998 /* Show motd to someone
999 */
1000 static void bot_motd(int idx, char *par)
1001 {
1002 FILE *vv;
1003 char *s = TBUF, *who, *p;
1004 int i;
1005 struct flag_record fr = { FR_BOT, USER_BOT, 0, 0, 0, 0 };
1006
1007 who = newsplit(&par);
1008 if (!par[0] || !egg_strcasecmp(par, botnetnick)) {
1009 int irc = 0;
1010
1011 p = strchr(who, ':');
1012 if (p)
1013 p++;
1014 else
1015 p = who;
1016 if (who[0] == '!') {
1017 irc = HELP_IRC;
1018 fr.global |=USER_HIGHLITE;
1019
1020 who++;
1021 } else if (who[0] == '#') {
1022 fr.global |=USER_HIGHLITE;
1023
1024 who++;
1025 }
1026 putlog(LOG_CMDS, "*", "#%s# motd", p);
1027 vv = fopen(motdfile, "r");
1028 if (vv != NULL) {
1029 botnet_send_priv(idx, botnetnick, who, NULL, _("--- MOTD file:\n"));
1030 help_subst(NULL, NULL, 0, irc, NULL);
1031 while (!feof(vv)) {
1032 fgets(s, 120, vv);
1033 if (!feof(vv)) {
1034 if (s[strlen(s) - 1] == '\n')
1035 s[strlen(s) - 1] = 0;
1036 if (!s[0])
1037 strcpy(s, " ");
1038 help_subst(s, who, &fr, HELP_DCC, dcc[idx].nick);
1039 if (s[0])
1040 botnet_send_priv(idx, botnetnick, who, NULL, "%s", s);
1041 }
1042 }
1043 fclose(vv);
1044 } else
1045 botnet_send_priv(idx, botnetnick, who, NULL, _("No MOTD file. :("));
1046 } else {
1047 /* Pass it on */
1048 i = nextbot(par);
1049 if (i >= 0)
1050 botnet_send_motd(i, who, par);
1051 }
1052 }
1053
1054 /* These are still here, so that they will pass the relevant
1055 * requests through even if no filesys is loaded.
1056 *
1057 * filereject <bot:filepath> <sock:nick@bot> <reason...>
1058 */
1059 static void bot_filereject(int idx, char *par)
1060 {
1061 char *path, *to, *tobot, *p;
1062 int i;
1063
1064 path = newsplit(&par);
1065 to = newsplit(&par);
1066 if ((tobot = strchr(to, '@')))
1067 tobot++;
1068 else
1069 tobot = to; /* Bot wants a file?! :) */
1070 if (egg_strcasecmp(tobot, botnetnick)) { /* for me! */
1071 p = strchr(to, ':');
1072 if (p != NULL) {
1073 *p = 0;
1074 for (i = 0; i < dcc_total; i++) {
1075 if (dcc[i].sock == atoi(to))
1076 dprintf(i, _("FILE TRANSFER REJECTED (%s): %s\n"), path, par);
1077 }
1078 *p = ':';
1079 }
1080 /* No ':'? malformed */
1081 putlog(LOG_FILES, "*", _("%s rejected: %s"), path, par);
1082 } else { /* Pass it on */
1083 i = nextbot(tobot);
1084 if (i >= 0)
1085 botnet_send_filereject(i, path, to, par);
1086 }
1087 }
1088
1089 /* filereq <sock:nick@bot> <bot:file>
1090 */
1091 static void bot_filereq(int idx, char *tobot)
1092 {
1093 char *from, *path;
1094 int i;
1095
1096 from = newsplit(&tobot);
1097 if ((path = strchr(tobot, ':'))) {
1098 *path++ = 0;
1099
1100 if (!egg_strcasecmp(tobot, botnetnick)) { /* For me! */
1101 /* Process this */
1102 module_entry *fs = module_find("filesys", 0, 0);
1103
1104 if (fs == NULL)
1105 botnet_send_priv(idx, botnetnick, from, NULL, _("Filesys module not loaded."));
1106 else {
1107 Function f = fs->funcs[FILESYS_REMOTE_REQ];
1108
1109 f(idx, from, path);
1110 }
1111 } else { /* Pass it on */
1112 i = nextbot(tobot);
1113 if (i >= 0)
1114 botnet_send_filereq(i, from, tobot, path);
1115 }
1116 }
1117 }
1118
1119 /* filesend <bot:path> <sock:nick@bot> <IP#> <port> <size>
1120 */
1121 static void bot_filesend(int idx, char *par)
1122 {
1123 char *botpath, *to, *tobot, *nick;
1124 int i;
1125 char *nfn;
1126
1127 botpath = newsplit(&par);
1128 to = newsplit(&par);
1129 if ((tobot = strchr(to, '@'))) {
1130 *tobot = 0;
1131 tobot++;
1132 } else
1133 tobot = to;
1134 if (!egg_strcasecmp(tobot, botnetnick)) { /* For me! */
1135 nfn = strrchr(botpath, '/');
1136 if (nfn == NULL) {
1137 nfn = strrchr(botpath, ':');
1138 if (nfn == NULL)
1139 nfn = botpath; /* That's odd. */
1140 else
1141 nfn++;
1142 } else
1143 nfn++;
1144 if ((nick = strchr(to, ':')))
1145 nick++;
1146 else
1147 nick = to;
1148 /* Send it to 'nick' as if it's from me */
1149 dprintf(DP_SERVER, "PRIVMSG %s :\001DCC SEND %s %s\001\n", nick, nfn, par);
1150 } else {
1151 i = nextbot(tobot);
1152 if (i >= 0) {
1153 *--tobot = '@';
1154 botnet_send_filesend(i, botpath, to, par);
1155 }
1156 }
1157 }
1158
1159 static void bot_error(int idx, char *par)
1160 {
1161 putlog(LOG_MISC | LOG_BOTS, "*", "%s: %s", dcc[idx].nick, par);
1162 }
1163
1164 /* nc <bot> <sock> <newnick>
1165 */
1166 static void bot_nickchange(int idx, char *par)
1167 {
1168 char *bot, *ssock, *newnick;
1169 int sock, i;
1170
1171 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
1172 return;
1173 bot = newsplit(&par);
1174 #ifndef NO_OLD_BOTNET
1175 if (b_numver(idx) < NEAT_BOTNET) {
1176 fake_alert(idx, "botversion", "NEAT_BOTNET");
1177 return;
1178 }
1179 #endif
1180 i = nextbot(bot);
1181 if (i != idx) {
1182 fake_alert(idx, "direction", bot);
1183 return;
1184 }
1185 ssock = newsplit(&par);
1186 sock = base64_to_int(ssock);
1187 newnick = newsplit(&par);
1188 i = partynick(bot, sock, newnick);
1189 if (i < 0) {
1190 fake_alert(idx, "sock#", ssock);
1191 return;
1192 }
1193 chanout_but(-1, party[i].chan, _("*** (%s) Nick change: %s -> %s\n"),
1194 bot, newnick, party[i].nick);
1195 botnet_send_nkch_part(idx, i, newnick);
1196 }
1197
1198 /* join <bot> <nick> <chan> <flag><sock> <from>
1199 */
1200 static void bot_join(int idx, char *par)
1201 {
1202 char *bot, *nick, *x, *y;
1203 struct userrec *u;
1204 int i, sock, chan, i2, linking = 0;
1205
1206 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
1207 return;
1208 bot = newsplit(&par);
1209 #ifndef NO_OLD_BOTNET
1210 if (b_numver(idx) >= NEAT_BOTNET)
1211 #endif
1212 if (bot[0] == '!') {
1213 linking = 1;
1214 bot++;
1215 }
1216 if (b_status(idx) & STAT_LINKING) {
1217 linking = 1;
1218 }
1219 nick = newsplit(&par);
1220 x = newsplit(&par);
1221 #ifndef NO_OLD_BOTNET
1222 if (b_numver(idx) < NEAT_BOTNET)
1223 chan = atoi(x);
1224 else
1225 #endif
1226 chan = base64_to_int(x);
1227 y = newsplit(&par);
1228 if ((chan < 0) || !y[0])
1229 return; /* Woops! pre 1.2.1's send .chat off'ers
1230 * too!! */
1231 if (!y[0]) {
1232 y[0] = '-';
1233 sock = 0;
1234 } else {
1235 #ifndef NO_OLD_BOTNET
1236 if (b_numver(idx) < NEAT_BOTNET)
1237 sock = atoi(y + 1);
1238 else
1239 #endif
1240 sock = base64_to_int(y + 1);
1241 }
1242 /* 1.1 bots always send a sock#, even on a channel change
1243 * so if sock# is 0, this is from an old bot and we must tread softly
1244 * grab old sock# if there is one, otherwise make up one.
1245 */
1246 if (sock == 0)
1247 sock = partysock(bot, nick);
1248 if (sock == 0)
1249 sock = fakesock++;
1250 i = nextbot(bot);
1251 if (i != idx) { /* Ok, garbage from a 1.0g (who uses that
1252 * now?) OR raistlin being evil :) */
1253 fake_alert(idx, "direction", bot);
1254 return;
1255 }
1256 u = get_user_by_handle(userlist, nick);
1257 if (u) {
1258 sprintf(TBUF, "@%s", bot);
1259 touch_laston(u, TBUF, now);
1260 }
1261 i = addparty(bot, nick, chan, y[0], sock, par, &i2);
1262 botnet_send_join_party(idx, linking, i2, i);
1263 if (i != chan) {
1264 if (i >= 0) {
1265 if (b_numver(idx) >= NEAT_BOTNET) {
1266 if (i)
1267 chanout_but(-1, i, _("*** (%s) %s has left the channel"));
1268 else
1269 chanout_but(-1, i, _("*** (%s) %s has left the party line"));
1270 }
1271 check_tcl_chpt(bot, nick, sock, i);
1272 }
1273 if ((b_numver(idx) >= NEAT_BOTNET) && !linking) {
1274 if (chan)
1275 chanout_but(-1, chan, _("*** (%s) %s has joined the channel.\n"),
1276 bot, nick);
1277 else
1278 chanout_but(-1, chan, _("*** (%s) %s has joined the party line.\n"),
1279 bot, nick);
1280 }
1281 check_tcl_chjn(bot, nick, chan, y[0], sock, par);
1282 }
1283 }
1284
1285 /* part <bot> <nick> <sock> [etc..]
1286 */
1287 static void bot_part(int idx, char *par)
1288 {
1289 char *bot, *nick, *etc;
1290 struct userrec *u;
1291 int sock, partyidx;
1292 int silent = 0;
1293
1294 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
1295 return;
1296 bot = newsplit(&par);
1297 if (bot[0] == '!') {
1298 silent = 1;
1299 bot++;
1300 }
1301 nick = newsplit(&par);
1302 etc = newsplit(&par);
1303 #ifndef NO_OLD_BOTNET
1304 if (b_numver(idx) < NEAT_BOTNET) {
1305 sock = atoi(etc);
1306 silent = 1;
1307 } else
1308 #endif
1309 sock = base64_to_int(etc);
1310 if (sock == 0)
1311 sock = partysock(bot, nick);
1312 u = get_user_by_handle(userlist, nick);
1313 if (u) {
1314 sprintf(TBUF, "@%s", bot);
1315 touch_laston(u, TBUF, now);
1316 }
1317 if ((partyidx = getparty(bot, sock)) != -1) {
1318 if (party[partyidx].chan >= 0)
1319 check_tcl_chpt(bot, nick, sock, party[partyidx].chan);
1320 if ((b_numver(idx) >= NEAT_BOTNET) && !silent) {
1321 register int chan = party[partyidx].chan;
1322
1323 if (par[0]) {
1324 if (chan)
1325 chanout_but(-1, chan, _("*** (%s) %s has left the channel (%s).\n"),
1326 bot, nick, par);
1327 else
1328 chanout_but(-1, chan, _("*** (%s) %s has left the partyline (%s).\n"),
1329 bot, nick, par);
1330 }
1331 }
1332 botnet_send_part_party(idx, partyidx, par, silent);
1333 remparty(bot, sock);
1334 }
1335 }
1336
1337 /* away <bot> <sock> <message>
1338 * null message = unaway
1339 */
1340 static void bot_away(int idx, char *par)
1341 {
1342 char *bot, *etc;
1343 int sock, partyidx, linking = 0;
1344
1345 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
1346 return;
1347 bot = newsplit(&par);
1348 #ifndef NO_OLD_BOTNET
1349 if (b_numver(idx) >= NEAT_BOTNET)
1350 #endif
1351 if (bot[0] == '!') {
1352 linking = 1;
1353 bot++;
1354 }
1355 if (b_status(idx) & STAT_LINKING) {
1356 linking = 1;
1357 }
1358 etc = newsplit(&par);
1359 #ifndef NO_OLD_BOTNET
1360 if (b_numver(idx) < NEAT_BOTNET)
1361 sock = atoi(etc);
1362 else
1363 #endif
1364 sock = base64_to_int(etc);
1365 if (sock == 0)
1366 sock = partysock(bot, etc);
1367 check_tcl_away(bot, sock, par);
1368 if (par[0]) {
1369 partystat(bot, sock, PLSTAT_AWAY, 0);
1370 partyaway(bot, sock, par);
1371 } else
1372 partystat(bot, sock, 0, PLSTAT_AWAY);
1373 partyidx = getparty(bot, sock);
1374 if ((b_numver(idx) >= NEAT_BOTNET) && !linking) {
1375 if (par[0])
1376 chanout_but(-1, party[partyidx].chan,
1377 _("*** (%s) %s is now away: %s.\n"), bot,
1378 party[partyidx].nick, par);
1379 else
1380 chanout_but(-1, party[partyidx].chan,
1381 _("*** (%s) %s is no longer away.\n"), bot,
1382 party[partyidx].nick);
1383 }
1384 botnet_send_away(idx, bot, sock, par, linking);
1385 }
1386
1387 /* (a courtesy info to help during connect bursts)
1388 * idle <bot> <sock> <#secs> [away msg]
1389 */
1390 static void bot_idle(int idx, char *par)
1391 {
1392 char *bot, *work;
1393 int sock, idle;
1394
1395 if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
1396 return;
1397 bot = newsplit(&par);
1398 work = newsplit(&par);
1399 #ifndef NO_OLD_BOTNET
1400 if (b_numver(idx) < NEAT_BOTNET)
1401 sock = atoi(work);
1402 else
1403 #endif
1404 sock = base64_to_int(work);
1405 if (sock == 0)
1406 sock = partysock(bot, work);
1407 work = newsplit(&par);
1408 #ifndef NO_OLD_BOTNET
1409 if (b_numver(idx) < NEAT_BOTNET)
1410 idle = atoi(work);
1411 else
1412 #endif
1413 idle = base64_to_int(work);
1414 partysetidle(bot, sock, idle);
1415 if (par[0]) {
1416 partystat(bot, sock, PLSTAT_AWAY, 0);
1417 partyaway(bot, sock, par);
1418 }
1419 botnet_send_idle(idx, bot, sock, idle, par);
1420 }
1421
1422 #ifndef NO_OLD_BOTNET
1423
1424 static void bot_ufno(int idx, char *par)
1425 {
1426 putlog(LOG_BOTS, "*", _("User file rejected by %s: %s"), dcc[idx].nick, par);
1427 dcc[idx].status &= ~STAT_OFFERED;
1428 if (!(dcc[idx].status & STAT_GETTING))
1429 dcc[idx].status &= ~STAT_SHARE;
1430 }
1431
1432 static void bot_old_userfile(int idx, char *par)
1433 {
1434 putlog(LOG_BOTS, "*", _("Old style share request by %s"), dcc[idx].nick);
1435 dprintf(idx, "uf-no %s\n", _("Antiquated sharing request"));
1436 }
1437
1438 #endif /* !NO_OLD_BOTNET */
1439
1440 void bot_share(int idx, char *par)
1441 {
1442 sharein(idx, par);
1443 }
1444
1445 /* v <frombot> <tobot> <idx:nick>
1446 */
1447 static void bot_versions(int sock, char *par)
1448 {
1449 char *frombot = newsplit(&par), *tobot, *from;
1450 module_entry *me;
1451
1452 if (nextbot(frombot) != sock)
1453 fake_alert(sock, "versions-direction", frombot);
1454 else if (egg_strcasecmp(tobot = newsplit(&par), botnetnick)) {
1455 if ((sock = nextbot(tobot)) >= 0)
1456 dprintf(sock, "v %s %s %s\n", frombot, tobot, par);
1457 } else {
1458 from = newsplit(&par);
1459 botnet_send_priv(sock, botnetnick, from, frombot, _("Modules loaded:\n"));
1460 for (me = module_list; me; me = me->next)
1461 botnet_send_priv(sock, botnetnick, from, frombot,
1462 _(" Module: %s (v%d.%d)\n"), me->name, me->major,
1463 me->minor);
1464 botnet_send_priv(sock, botnetnick, from, frombot,
1465 _("End of module list.\n"));
1466 }
1467 }
1468
1469 #ifdef TLS
1470 /* Negotiate an encrypted session over the existing link
1471 * starttls <c/s>
1472 */
1473 static void bot_starttls(int idx, char *par)
1474 {
1475 char *con;
1476 /* We're already using ssl, ignore the request */
1477 if (dcc[idx].ssl)
1478 return;
1479
1480 con = newsplit(&par);
1481 /* check who's going to play the server */
1482 if (!egg_strcasecmp(con, "s")) { /* we're server */
1483 putlog(LOG_BOTS, "*", _("Got STARTTLS from %s. Replying..."),
1484 dcc[idx].nick);
1485 dprintf(idx, "starttls c\n");
1486 ssl_handshake(dcc[idx].sock, TLS_LISTEN, tls_vfybots, LOG_BOTS,
1487 dcc[idx].host, NULL);
1488 } else { /* we're client, don't reply or we'll be in the loop forever */
1489 ssl_handshake(dcc[idx].sock, TLS_CONNECT, tls_vfybots, LOG_BOTS,
1490 dcc[idx].host, NULL);
1491 }
1492 dcc[idx].ssl = 1;
1493 }
1494 #endif
1495
1496 /* BOT COMMANDS
1497 *
1498 * function call should be:
1499 * int bot_whatever(idx,"parameters");
1500 *
1501 * SORT these, dcc_bot uses a shortcut which requires them sorted
1502 *
1503 * yup, those are tokens there to allow a more efficient botnet as
1504 * time goes on (death to slowly upgrading llama's)
1505 */
1506 botcmd_t C_bot[] =
1507 {
1508 {"a", (IntFunc) bot_actchan},
1509 #ifndef NO_OLD_BOTNET
1510 {"actchan", (IntFunc) bot_actchan},
1511 #endif
1512 {"aw", (IntFunc) bot_away},
1513 {"away", (IntFunc) bot_away},
1514 {"bye", (IntFunc) bot_bye},
1515 {"c", (IntFunc) bot_chan2},
1516 #ifndef NO_OLD_BOTNET
1517 {"chan", (IntFunc) bot_chan2},
1518 {"chat", (IntFunc) bot_chat},
1519 #endif
1520 {"ct", (IntFunc) bot_chat},
1521 {"e", (IntFunc) bot_error},
1522 {"el", (IntFunc) bot_endlink},
1523 #ifndef NO_OLD_BOTNET
1524 {"error", (IntFunc) bot_error},
1525 #endif
1526 {"f!", (IntFunc) bot_filereject},
1527 #ifndef NO_OLD_BOTNET
1528 {"filereject", (IntFunc) bot_filereject},
1529 {"filereq", (IntFunc) bot_filereq},
1530 {"filesend", (IntFunc) bot_filesend},
1531 #endif
1532 {"fr", (IntFunc) bot_filereq},
1533 {"fs", (IntFunc) bot_filesend},
1534 {"h", (IntFunc) bot_handshake},
1535 #ifndef NO_OLD_BOTNET
1536 {"handshake", (IntFunc) bot_handshake},
1537 #endif
1538 {"i", (IntFunc) bot_idle},
1539 {"i?", (IntFunc) bot_infoq},
1540 #ifndef NO_OLD_BOTNET
1541 {"idle", (IntFunc) bot_idle},
1542 {"info?", (IntFunc) bot_infoq},
1543 #endif
1544 {"j", (IntFunc) bot_join},
1545 #ifndef NO_OLD_BOTNET
1546 {"join", (IntFunc) bot_join},
1547 #endif
1548 {"l", (IntFunc) bot_link},
1549 #ifndef NO_OLD_BOTNET
1550 {"link", (IntFunc) bot_link},
1551 {"linked", (IntFunc) bot_linked},
1552 #endif
1553 {"m", (IntFunc) bot_motd},
1554 #ifndef NO_OLD_BOTNET
1555 {"motd", (IntFunc) bot_motd},
1556 #endif
1557 {"n", (IntFunc) bot_nlinked},
1558 {"nc", (IntFunc) bot_nickchange},
1559 #ifndef NO_OLD_BOTNET
1560 {"nlinked", (IntFunc) bot_nlinked},
1561 #endif
1562 {"p", (IntFunc) bot_priv},
1563 #ifndef NO_OLD_BOTNET
1564 {"part", (IntFunc) bot_part},
1565 #endif
1566 {"pi", (IntFunc) bot_ping},
1567 #ifndef NO_OLD_BOTNET
1568 {"ping", (IntFunc) bot_ping},
1569 #endif
1570 {"po", (IntFunc) bot_pong},
1571 #ifndef NO_OLD_BOTNET
1572 {"pong", (IntFunc) bot_pong},
1573 {"priv", (IntFunc) bot_priv},
1574 #endif
1575 {"pt", (IntFunc) bot_part},
1576 {"r", (IntFunc) bot_reject},
1577 #ifndef NO_OLD_BOTNET
1578 {"reject", (IntFunc) bot_reject},
1579 #endif
1580 {"s", (IntFunc) bot_share},
1581 #ifdef TLS
1582 {"starttls", (IntFunc) bot_starttls},
1583 #endif
1584 {"t", (IntFunc) bot_trace},
1585 {"tb", (IntFunc) bot_thisbot},
1586 {"td", (IntFunc) bot_traced},
1587 #ifndef NO_OLD_BOTNET
1588 {"thisbot", (IntFunc) bot_thisbot},
1589 {"trace", (IntFunc) bot_trace},
1590 {"traced", (IntFunc) bot_traced},
1591 #endif
1592 {"u", (IntFunc) bot_update},
1593 #ifndef NO_OLD_BOTNET
1594 {"uf-no", (IntFunc) bot_ufno},
1595 #endif
1596 {"ul", (IntFunc) bot_unlink},
1597 {"un", (IntFunc) bot_unlinked},
1598 #ifndef NO_OLD_BOTNET
1599 {"unaway", (IntFunc) bot_away},
1600 {"unlink", (IntFunc) bot_unlink},
1601 {"unlinked", (IntFunc) bot_unlinked},
1602 {"update", (IntFunc) bot_update},
1603 {"userfile?", (IntFunc) bot_old_userfile},
1604 #endif
1605 {"v", (IntFunc) bot_versions},
1606 {"w", (IntFunc) bot_who},
1607 #ifndef NO_OLD_BOTNET
1608 {"who", (IntFunc) bot_who},
1609 #endif
1610 {"z", (IntFunc) bot_zapf},
1611 #ifndef NO_OLD_BOTNET
1612 {"zapf", (IntFunc) bot_zapf},
1613 {"zapf-broad", (IntFunc) bot_zapfbroad},
1614 #endif
1615 {"zb", (IntFunc) bot_zapfbroad},
1616 {NULL, NULL}
1617 };

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23