/* away <bot> <sock> <message> * null message = unaway */ static void bot_away(int idx, char *par) { char *bot = NULL, *etc = NULL; int sock, partyidx, linking = 0; bot = newsplit(&par); if (bot[0] == '!') { linking = 1; bot++; } if (b_status(idx) & STAT_LINKING) { linking = 1; } etc = newsplit(&par); sock = base64_to_int(etc); if (par[0]) { partystat(bot, sock, PLSTAT_AWAY, 0); partyaway(bot, sock, par); } else { partystat(bot, sock, 0, PLSTAT_AWAY); } partyidx = getparty(bot, sock); if (!linking) { if (par[0]) chanout_but(-1, party[partyidx].chan, "*** (%s) %s %s: %s.\n", conf.bot->hub ? bot : "[botnet]", party[partyidx].nick, "is now away", par); else chanout_but(-1, party[partyidx].chan, "*** (%s) %s %s.\n", conf.bot->hub ? bot : "[botnet]", party[partyidx].nick, "is no longer away"); } botnet_send_away(idx, bot, sock, par, linking); }
static void zapf_assoc(char *botnick, char *code, char *par) { int idx = nextbot(botnick); char *s, *s1, *nick; int linking = 0, chan; if ((idx >= 0) && !(bot_flags(dcc[idx].user) & BOT_ISOLATE)) { if (!egg_strcasecmp(dcc[idx].nick, botnick)) linking = b_status(idx) & STAT_LINKING; s = newsplit(&par); chan = base64_to_int(s); if ((chan > 0) || (chan < GLOBAL_CHANS)) { nick = newsplit(&par); s1 = get_assoc_name(chan); if (linking && ((s1 == NULL) || (s1[0] == 0) || (((intptr_t) get_user(find_entry_type("BOTFL"), dcc[idx].user) & BOT_HUB)))) { add_assoc(par, chan); botnet_send_assoc(idx, chan, nick, par); chanout_but(-1, chan, ASSOC_CHNAME_NAMED, nick, par); } else if (par[0] == '0') { kill_assoc(chan); chanout_but(-1, chan, ASSOC_CHNAME_REM, botnick, nick); } else if (get_assoc(par) != chan) { /* New one i didn't know about -- pass it on */ s1 = get_assoc_name(chan); add_assoc(par, chan); chanout_but(-1, chan, ASSOC_CHNAME_NAMED2, botnick, nick, par); } } } }
static int cmd_files(struct userrec *u, int idx, char *par) { int atr = u ? u->flags : 0; static struct chat_info *ci; Context; if (dccdir[0] == 0) dprintf(idx, "There is no file transfer area.\n"); else if (too_many_filers()) { dprintf(idx, "The maximum of %d people are in the file area right now.\n", dcc_users); dprintf(idx, "Please try again later.\n"); } else { if (!(atr & (USER_MASTER | USER_XFER))) dprintf(idx, "You don't have access to the file area.\n"); else { putlog(LOG_CMDS, "*", "#%s# files", dcc[idx].nick); dprintf(idx, "Entering file system...\n"); if (dcc[idx].u.chat->channel >= 0) { chanout_but(-1, dcc[idx].u.chat->channel, "*** %s has left: file system\n", dcc[idx].nick); if (dcc[idx].u.chat->channel < 100000) botnet_send_part_idx(idx, "file system"); } ci = dcc[idx].u.chat; dcc[idx].u.file = get_data_ptr(sizeof(struct file_info)); dcc[idx].u.file->chat = ci; dcc[idx].type = &DCC_FILES; dcc[idx].status |= STAT_CHAT; if (!welcome_to_files(idx)) { struct chat_info *ci = dcc[idx].u.file->chat; nfree(dcc[idx].u.file); dcc[idx].u.chat = ci; dcc[idx].type = &DCC_CHAT; putlog(LOG_FILES, "*", "File system broken."); if (dcc[idx].u.chat->channel >= 0) { chanout_but(-1, dcc[idx].u.chat->channel, "*** %s has returned.\n", dcc[idx].nick); if (dcc[idx].u.chat->channel < 100000) botnet_send_join_idx(idx, -1); } } else touch_laston(u, "filearea", now); } } return 0; }
/* part <bot> <nick> <sock> [etc..] */ static void bot_part(int idx, char *par) { char *bot = NULL, *nick = NULL, *etc = NULL; struct userrec *u = NULL; int sock, partyidx; int silent = 0; bot = newsplit(&par); if (bot[0] == '!') { silent = 1; bot++; } nick = newsplit(&par); etc = newsplit(&par); sock = base64_to_int(etc); u = get_user_by_handle(userlist, nick); if (u) { simple_snprintf(TBUF, sizeof(TBUF), "@%s", bot); touch_laston(u, TBUF, now); } if ((partyidx = getparty(bot, sock)) != -1) { if (!silent) { register int chan = party[partyidx].chan; if (par[0]) chanout_but(-1, chan, "*** (%s) %s %s %s (%s).\n", conf.bot->hub ? bot : "[botnet]", nick, "has left the", chan ? "channel" : "party line", par); else chanout_but(-1, chan, "*** (%s) %s %s %s.\n", conf.bot->hub ? bot : "[botnet]", nick, "has left the", chan ? "channel" : "party line"); } botnet_send_part_party(idx, partyidx, par, silent); remparty(bot, sock); } /* check if we have a remote idx for them */ int i = 0; for (i = 0; i < dcc_total; i++) { /* This will potentially close all simul-idxs with matching nick, even though they may be connected multiple times but, it won't matter as a new will just be made as needed. */ if (dcc[i].type && dcc[i].simul >= 0 && !strcasecmp(dcc[i].nick, nick)) { dcc[i].simul = -1; lostdcc(i); } } }
/* join <bot> <nick> <chan> <flag><sock> <from> */ static void bot_join(int idx, char *par) { char *bot = NULL, *nick = NULL, *x = NULL, *y = NULL; struct userrec *u = NULL; int i, sock, chan, i2, linking = 0; bot = newsplit(&par); if (bot[0] == '!') { linking = 1; bot++; } if (b_status(idx) & STAT_LINKING) { linking = 1; } nick = newsplit(&par); x = newsplit(&par); chan = base64_to_int(x); y = newsplit(&par); if ((chan < 0) || !y[0]) return; /* Woops! pre 1.2.1's send .chat off'ers * too!! */ if (!y[0]) { y[0] = '-'; sock = 0; } else { sock = base64_to_int(y + 1); } i = nextbot(bot); if (i != idx) { /* Ok, garbage from a 1.0g (who uses that * now?) OR raistlin being evil :) */ fake_alert(idx, "direction", bot, "join"); return; } u = get_user_by_handle(userlist, nick); if (u) { simple_snprintf(TBUF, sizeof(TBUF), "@%s", bot); touch_laston(u, TBUF, now); } i = addparty(bot, nick, chan, y[0], sock, par, &i2); botnet_send_join_party(idx, linking, i2); if (i != chan) { if (i >= 0) { chanout_but(-1, i, "*** (%s) %s %s %s.\n", conf.bot->hub ? bot : "[botnet]", nick, "has left the", i ? "channel" : "party line"); } if (!linking) chanout_but(-1, chan, "*** (%s) %s %s %s.\n", conf.bot->hub ? bot : "[botnet]", nick, "has joined the", chan ? "channel" : "party line"); } }
static int tcl_killdcc(ClientData cd, Tcl_Interp *irp, int argc, char *argv[]) { int idx; BADARGS(2, 3, " idx ?reason?"); idx = findidx(atoi(argv[1])); if (idx < 0) { Tcl_AppendResult(irp, "invalid idx", NULL); return TCL_ERROR; } if ((dcc[idx].sock == STDOUT) && !backgrd) /* Don't kill terminal socket */ return TCL_OK; if (dcc[idx].type->flags & DCT_CHAT) { /* Make sure 'whom' info is updated */ chanout_but(idx, dcc[idx].u.chat->channel, "*** %s has left the %s%s%s\n", dcc[idx].nick, dcc[idx].u.chat ? "channel" : "partyline", argc == 3 ? ": " : "", argc == 3 ? argv[2] : ""); botnet_send_part_idx(idx, argc == 3 ? argv[2] : ""); if ((dcc[idx].u.chat->channel >= 0) && (dcc[idx].u.chat->channel < GLOBAL_CHANS)) check_tcl_chpt(botnetnick, dcc[idx].nick, dcc[idx].sock, dcc[idx].u.chat->channel); check_tcl_chof(dcc[idx].nick, dcc[idx].sock); } killsock(dcc[idx].sock); killtransfer(idx); lostdcc(idx); return TCL_OK; }
/* nc <bot> <sock> <newnick> */ static void bot_nickchange(int idx, char *par) { char *bot, *ssock, *newnick; int sock, i; if (bot_flags(dcc[idx].user) & BOT_ISOLATE) return; bot = newsplit(&par); #ifndef NO_OLD_BOTNET if (dcc[idx].u.bot->numver < NEAT_BOTNET) { fake_alert(idx, "botversion", "NEAT_BOTNET"); return; } #endif i = nextbot(bot); if (i != idx) { fake_alert(idx, "direction", bot); return; } ssock = newsplit(&par); sock = base64_to_int(ssock); newnick = newsplit(&par); i = partynick(bot, sock, newnick); if (i < 0) { fake_alert(idx, "sock#", ssock); return; } chanout_but(-1, party[i].chan, "*** (%s) Nick change: %s -> %s\n", bot, newnick, party[i].nick); botnet_send_nkch_part(idx, i, newnick); }
/* Handle someone being booted from dcc chat. */ void do_boot(int idx, char *by, char *reason) { int files = (dcc[idx].type != &DCC_CHAT); dprintf(idx, DCC_BOOTED1); dprintf(idx, DCC_BOOTED2, files ? "file section" : "bot", by, reason[0] ? ": " : ".", reason); /* If it's a partyliner (chatterer :) */ /* Horrible assumption that DCT_CHAT using structure uses same format * as DCC_CHAT */ if ((dcc[idx].type->flags & DCT_CHAT) && (dcc[idx].u.chat->channel >= 0)) { char x[1024]; egg_snprintf(x, sizeof x, DCC_BOOTED3, by, dcc[idx].nick, reason[0] ? ": " : "", reason); chanout_but(idx, dcc[idx].u.chat->channel, "*** %s.\n", x); if (dcc[idx].u.chat->channel < GLOBAL_CHANS) botnet_send_part_idx(idx, x); } check_tcl_chof(dcc[idx].nick, dcc[idx].sock); if ((dcc[idx].sock != STDOUT) || backgrd) { killsock(dcc[idx].sock); lostdcc(idx); /* Entry must remain in the table so it can be logged by the caller */ } else { dprintf(DP_STDOUT, "\n### SIMULATION RESET\n\n"); dcc_chatter(idx); } return; }
static void eof_dcc_relay(int idx) { register int j; struct chat_info *ci; for (j = 0; dcc[j].sock != dcc[idx].u.relay->sock; j++); dcc[j].status = dcc[j].u.relay->old_status; /* in case echo was off, turn it back on: */ if (dcc[j].status & STAT_TELNET) dprintf(j, "\377\374\001\n"); putlog(LOG_MISC, "*", "%s: %s -> %s", BOT_ENDRELAY1, dcc[j].nick, dcc[idx].nick); dprintf(j, "\n\n*** %s %s\n", BOT_ENDRELAY2, botnetnick); ci = dcc[j].u.relay->chat; nfree(dcc[j].u.relay); dcc[j].u.chat = ci; dcc[j].type = &DCC_CHAT; if (dcc[j].u.chat->channel >= 0) { chanout_but(-1, dcc[j].u.chat->channel, "*** %s %s.\n", dcc[j].nick, BOT_PARTYREJOINED); Context; if (dcc[j].u.chat->channel < 100000) botnet_send_join_idx(j, -1); } check_tcl_chon(dcc[j].nick, dcc[j].sock); check_tcl_chjn(botnetnick, dcc[j].nick, dcc[j].u.chat->channel, geticon(j), dcc[j].sock, dcc[j].host); killsock(dcc[idx].sock); lostdcc(idx); }
static int tcl_control(ClientData cd, Tcl_Interp *irp, int argc, char *argv[]) { int idx; void *hold; BADARGS(3, 3, " idx command"); idx = findidx(atoi(argv[1])); if (idx < 0) { Tcl_AppendResult(irp, "invalid idx", NULL); return TCL_ERROR; } if (dcc[idx].type->flags & DCT_CHAT) { if (dcc[idx].u.chat->channel >= 0) { chanout_but(idx, dcc[idx].u.chat->channel, "*** %s has gone.\n", dcc[idx].nick); check_tcl_chpt(botnetnick, dcc[idx].nick, dcc[idx].sock, dcc[idx].u.chat->channel); botnet_send_part_idx(idx, "gone"); } check_tcl_chof(dcc[idx].nick, dcc[idx].sock); } hold = dcc[idx].u.other; dcc[idx].u.script = get_data_ptr(sizeof(struct script_info)); dcc[idx].u.script->u.other = hold; dcc[idx].u.script->type = dcc[idx].type; dcc[idx].type = &DCC_SCRIPT; /* Do not buffer data anymore. All received and stored data is passed * over to the dcc functions from now on. */ sockoptions(dcc[idx].sock, EGG_OPTION_UNSET, SOCK_BUFFER); strncpyz(dcc[idx].u.script->command, argv[2], 120); return TCL_OK; }
/* part <bot> <nick> <sock> [etc..] */ static void bot_part(int idx, char *par) { char *bot, *nick, *etc; struct userrec *u; int sock, partyidx; int silent = 0; if (bot_flags(dcc[idx].user) & BOT_ISOLATE) return; bot = newsplit(&par); if (bot[0] == '!') { silent = 1; bot++; } nick = newsplit(&par); etc = newsplit(&par); #ifndef NO_OLD_BOTNET if (dcc[idx].u.bot->numver < NEAT_BOTNET) { sock = atoi(etc); silent = 1; } else #endif sock = base64_to_int(etc); if (sock == 0) sock = partysock(bot, nick); u = get_user_by_handle(userlist, nick); if (u) { sprintf(TBUF, "@%s", bot); touch_laston(u, TBUF, now); } if ((partyidx = getparty(bot, sock)) != -1) { if (party[partyidx].chan >= 0) check_tcl_chpt(bot, nick, sock, party[partyidx].chan); if ((dcc[idx].u.bot->numver >= NEAT_BOTNET) && !silent) { register int chan = party[partyidx].chan; if (par[0]) chanout_but(-1, chan, "*** (%s) %s %s %s (%s).\n", bot, nick, NET_LEFTTHE, chan ? "channel" : "party line", par); else chanout_but(-1, chan, "*** (%s) %s %s %s.\n", bot, nick, NET_LEFTTHE, chan ? "channel" : "party line"); } botnet_send_part_party(idx, partyidx, par, silent); remparty(bot, sock); } }
/* actchan <from> <chan> <text> */ static void bot_actchan(int idx, char *par) { char *from = NULL, *p = NULL; int i, chan; from = newsplit(&par); p = strchr(from, '@'); if (p == NULL) { /* How can a bot do an action? */ fake_alert(idx, "user@bot", from, "actchan_i"); return; } *p = 0; if (!partyidle(p + 1, from)) { *p = '@'; fake_alert(idx, "user", from, "actchan_ii"); return; } *p = '@'; p++; i = nextbot(p); if (i != idx) { fake_alert(idx, "direction", p, "actchan_iii"); return; } p = newsplit(&par); chan = base64_to_int(p); for (p = from; *p;) { if ((*p < 32) || (*p == 127)) memmove(p, p + 1, strlen(p)); else p++; } if (!conf.bot->hub) { /* Need to strip out the hub nick */ char *q = NULL, newfrom[HANDLEN + 9 + 1]; /* HANDLEN@[botnet] */ strlcpy(newfrom, from, sizeof(newfrom)); q = strchr(newfrom, '@'); *q = 0; chanout_but(-1, chan, "* %s@[botnet] %s\n", newfrom, par); } else chanout_but(-1, chan, "* %s %s\n", from, par); botnet_send_act(idx, from, NULL, chan, par); }
/* away <bot> <sock> <message> * null message = unaway */ static void bot_away(int idx, char *par) { char *bot, *etc; int sock, partyidx, linking = 0; if (bot_flags(dcc[idx].user) & BOT_ISOLATE) return; bot = newsplit(&par); #ifndef NO_OLD_BOTNET if (dcc[idx].u.bot->numver >= NEAT_BOTNET) #endif if (bot[0] == '!') { linking = 1; bot++; } if (dcc[idx].status & BSTAT_LINKING) linking = 1; etc = newsplit(&par); #ifndef NO_OLD_BOTNET if (dcc[idx].u.bot->numver < NEAT_BOTNET) sock = atoi(etc); else #endif sock = base64_to_int(etc); if (sock == 0) sock = partysock(bot, etc); check_tcl_away(bot, sock, par); if (par[0]) { partystat(bot, sock, PLSTAT_AWAY, 0); partyaway(bot, sock, par); } else partystat(bot, sock, 0, PLSTAT_AWAY); partyidx = getparty(bot, sock); if ((dcc[idx].u.bot->numver >= NEAT_BOTNET) && !linking) { if (par[0]) chanout_but(-1, party[partyidx].chan, "*** (%s) %s %s: %s.\n", bot, party[partyidx].nick, NET_AWAY, par); else chanout_but(-1, party[partyidx].chan, "*** (%s) %s %s.\n", bot, party[partyidx].nick, NET_UNAWAY); } botnet_send_away(idx, bot, sock, par, linking); }
void dcc_chatter(int idx) { int i, j; struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 }; get_user_flagrec(dcc[idx].user, &fr, NULL); show_motd(idx); i = dcc[idx].u.chat->channel; dcc[idx].u.chat->channel = 234567; j = dcc[idx].sock; strcpy(dcc[idx].u.chat->con_chan, "***"); check_tcl_chon(dcc[idx].nick, dcc[idx].sock); /* Still there? */ if ((idx >= dcc_total) || (dcc[idx].sock != j)) return; /* Nope */ /* Tcl script may have taken control */ if (dcc[idx].type == &DCC_CHAT) { if (!strcmp(dcc[idx].u.chat->con_chan, "***")) strcpy(dcc[idx].u.chat->con_chan, "*"); if (dcc[idx].u.chat->channel == 234567) { /* If the chat channel has already been altered it's *highly* * probably join/part messages have been broadcast everywhere, * so dont bother sending them */ if (i == -2) i = 0; dcc[idx].u.chat->channel = i; if ((dcc[idx].u.chat->channel >= 0) && (dcc[idx].u.chat->channel < GLOBAL_CHANS)) botnet_send_join_idx(idx, -1); check_tcl_chjn(botnetnick, dcc[idx].nick, dcc[idx].u.chat->channel, geticon(idx), dcc[idx].sock, dcc[idx].host); } /* But *do* bother with sending it locally */ if (!dcc[idx].u.chat->channel) { chanout_but(-1, 0, "*** %s joined the party line.\n", dcc[idx].nick); } else if (dcc[idx].u.chat->channel > 0) { chanout_but(-1, dcc[idx].u.chat->channel, "*** %s joined the channel.\n", dcc[idx].nick); } } }
static void dcc_files(int idx, char *buf, int i) { Context; if (buf[0] && detect_dcc_flood(&dcc[idx].timeval, dcc[idx].u.file->chat, idx)) return; dcc[idx].timeval = now; strcpy(buf, check_tcl_filt(idx, buf)); if (!buf[0]) return; touch_laston(dcc[idx].user, "filearea", now); if (buf[0] == ',') { for (i = 0; i < dcc_total; i++) { if ((dcc[i].type->flags & DCT_MASTER) && dcc[idx].user && (dcc[idx].user->flags & USER_MASTER) && ((dcc[i].type == &DCC_FILES) || (dcc[i].u.chat->channel >= 0)) && ((i != idx) || (dcc[idx].status & STAT_ECHO))) dprintf(i, "-%s- %s\n", dcc[idx].nick, &buf[1]); } } else if (got_files_cmd(idx, buf)) { dprintf(idx, "*** Ja mata!\n"); flush_lines(idx, dcc[idx].u.file->chat); putlog(LOG_FILES, "*", "DCC user [%s]%s left file system", dcc[idx].nick, dcc[idx].host); set_user(&USERENTRY_DCCDIR, dcc[idx].user, dcc[idx].u.file->dir); if (dcc[idx].status & STAT_CHAT) { struct chat_info *ci; dprintf(idx, "Returning you to command mode...\n"); ci = dcc[idx].u.file->chat; nfree(dcc[idx].u.file); dcc[idx].u.chat = ci; dcc[idx].status &= (~STAT_CHAT); dcc[idx].type = &DCC_CHAT; if (dcc[idx].u.chat->channel >= 0) { chanout_but(-1, dcc[idx].u.chat->channel, "*** %s has returned.\n", dcc[idx].nick); if (dcc[idx].u.chat->channel < 100000) botnet_send_join_idx(idx, -1); } } else { dprintf(idx, "Dropping connection now.\n"); putlog(LOG_FILES, "*", "Left files: [%s]%s/%d", dcc[idx].nick, dcc[idx].host, dcc[idx].port); killsock(dcc[idx].sock); lostdcc(idx); } } if (dcc[idx].status & STAT_PAGE) flush_lines(idx, dcc[idx].u.file->chat); }
/* chan <from> <chan> <text> */ static void bot_chan2(int idx, char *msg) { char *from, *p; int i, chan; if (bot_flags(dcc[idx].user) & BOT_ISOLATE) return; from = newsplit(&msg); p = newsplit(&msg); #ifndef NO_OLD_BOTNET if (dcc[idx].u.bot->numver < NEAT_BOTNET) chan = atoi(p); else #endif chan = base64_to_int(p); /* Strip annoying control chars */ for (p = from; *p;) { if ((*p < 32) || (*p == 127)) strcpy(p, p + 1); else p++; } p = strchr(from, '@'); if (p) { sprintf(TBUF, "<%s> %s", from, msg); *p = 0; if (!partyidle(p + 1, from)) { *p = '@'; fake_alert(idx, "user", from); return; } *p = '@'; p++; } else { sprintf(TBUF, "*** (%s) %s", from, msg); p = from; } i = nextbot(p); if (i != idx) { fake_alert(idx, "direction", p); } else { chanout_but(-1, chan, "%s\n", TBUF); /* Send to new version bots */ if (i >= 0) botnet_send_chan(idx, from, NULL, chan, msg); if (strchr(from, '@') != NULL) check_tcl_chat(from, chan, msg); else check_tcl_bcst(from, chan, msg); } }
/* chan <from> <chan> <text> */ static void bot_chan2(int idx, char *msg) { char *from = NULL, *p = NULL; int i, chan; from = newsplit(&msg); p = newsplit(&msg); chan = base64_to_int(p); /* Strip annoying control chars */ for (p = from; *p;) { if ((*p < 32) || (*p == 127)) memmove(p, p + 1, strlen(p)); else p++; } p = strchr(from, '@'); if (p) { if (!conf.bot->hub) { /* Need to strip out the hub nick */ char *q = NULL, newfrom[HANDLEN + 9 + 1]; /* HANDLEN@[botnet] */ strlcpy(newfrom, from, sizeof(newfrom)); q = strchr(newfrom, '@'); *q = 0; simple_snprintf(TBUF, sizeof(TBUF), "<%s@[botnet]> %s", newfrom, msg); } else simple_snprintf(TBUF, sizeof(TBUF), "<%s> %s", from, msg); *p = 0; if (!partyidle(p + 1, from)) { *p = '@'; fake_alert(idx, "user", from, "chan2_i"); return; } *p = '@'; p++; } else { simple_snprintf(TBUF, sizeof(TBUF), "*** (%s) %s", from, msg); p = from; } i = nextbot(p); if (i != idx) { fake_alert(idx, "direction", p, "chan2_ii"); } else { chanout_but(-1, chan, "%s\n", TBUF); /* Send to new version bots */ if (i >= 0) botnet_send_chan(idx, from, NULL, chan, msg); } }
/* Mark someone on dcc chat as no longer away */ void not_away(int idx) { if (dcc[idx].u.chat->away == NULL) { dprintf(idx, "You weren't away!\n"); return; } if (dcc[idx].u.chat->channel >= 0) { chanout_but(-1, dcc[idx].u.chat->channel, "*** %s is no longer away.\n", dcc[idx].nick); if (dcc[idx].u.chat->channel < GLOBAL_CHANS) { botnet_send_away(-1, botnetnick, dcc[idx].sock, NULL, idx); } } dprintf(idx, "You're not away any more.\n"); nfree(dcc[idx].u.chat->away); dcc[idx].u.chat->away = NULL; check_tcl_away(botnetnick, dcc[idx].sock, NULL); }
/* actchan <from> <chan> <text> */ static void bot_actchan(int idx, char *par) { char *from, *p; int i, chan; if (bot_flags(dcc[idx].user) & BOT_ISOLATE) return; from = newsplit(&par); p = strchr(from, '@'); if (p == NULL) { /* How can a bot do an action? */ fake_alert(idx, "user@bot", from); return; } *p = 0; if (!partyidle(p + 1, from)) { *p = '@'; fake_alert(idx, "user", from); return; } *p = '@'; p++; i = nextbot(p); if (i != idx) { fake_alert(idx, "direction", p); return; } p = newsplit(&par); #ifndef NO_OLD_BOTNET if (dcc[idx].u.bot->numver < NEAT_BOTNET) chan = atoi(p); else #endif chan = base64_to_int(p); for (p = from; *p;) { if ((*p < 32) || (*p == 127)) strcpy(p, p + 1); else p++; } chanout_but(-1, chan, "* %s %s\n", from, par); botnet_send_act(idx, from, NULL, chan, par); check_tcl_act(from, chan, par); }
static int tcl_dccputchan(ClientData cd, Tcl_Interp *irp, int argc, char *argv[]) { int chan; char msg[401]; BADARGS(3, 3, " channel message"); chan = atoi(argv[1]); if ((chan < 0) || (chan > 199999)) { Tcl_AppendResult(irp, "channel out of range; must be 0 through 199999", NULL); return TCL_ERROR; } strncpyz(msg, argv[2], sizeof msg); chanout_but(-1, chan, "*** %s\n", argv[2]); botnet_send_chan(-1, botnetnick, NULL, chan, argv[2]); check_tcl_bcst(botnetnick, chan, argv[2]); return TCL_OK; }
static void cont_tandem_relay(int idx, char *buf, register int i) { register int uidx = (-1); struct relay_info *ri; Context; for (i = 0; i < dcc_total; i++) if ((dcc[i].type == &DCC_PRE_RELAY) && (dcc[i].u.relay->sock == dcc[idx].sock)) uidx = i; if (uidx < 0) { putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER, dcc[i].sock, dcc[i].u.relay->sock); killsock(dcc[i].sock); lostdcc(i); return; } dcc[idx].type = &DCC_RELAY; dcc[idx].u.relay->sock = dcc[uidx].sock; dcc[uidx].u.relay->sock = dcc[idx].sock; dprintf(uidx, "%s %s ...\n", BOT_RELAYSUCCESS, dcc[idx].nick); dprintf(uidx, "%s\n\n", BOT_BYEINFO2); putlog(LOG_MISC, "*", "%s %s -> %s", BOT_RELAYLINK, dcc[uidx].nick, dcc[idx].nick); ri = dcc[uidx].u.relay; /* YEAH */ dcc[uidx].type = &DCC_CHAT; dcc[uidx].u.chat = ri->chat; if (dcc[uidx].u.chat->channel >= 0) { chanout_but(-1, dcc[uidx].u.chat->channel, "*** %s %s\n", dcc[uidx].nick, BOT_PARTYLEFT); if (dcc[uidx].u.chat->channel < 100000) botnet_send_part_idx(uidx, NULL); check_tcl_chpt(botnetnick, dcc[uidx].nick, dcc[uidx].sock, dcc[uidx].u.chat->channel); } check_tcl_chof(dcc[uidx].nick, dcc[uidx].sock); dcc[uidx].type = &DCC_RELAYING; dcc[uidx].u.relay = ri; }
/* nc <bot> <sock> <newnick> */ static void bot_nickchange(int idx, char *par) { char *bot = NULL, *ssock = NULL, *newnick = NULL; int sock, i; bot = newsplit(&par); i = nextbot(bot); if (i != idx) { fake_alert(idx, "direction", bot, "nickchange_i"); return; } ssock = newsplit(&par); sock = base64_to_int(ssock); newnick = newsplit(&par); i = partynick(bot, sock, newnick); if (i < 0) { fake_alert(idx, "sock#", ssock, "nickchange_ii"); return; } chanout_but(-1, party[i].chan, "*** (%s) Nick change: %s -> %s\n", conf.bot->hub ? bot : "[botnet]", newnick, party[i].nick); botnet_send_nkch_part(idx, i, newnick); }
int detect_dcc_flood(time_t *timer, struct chat_info *chat, int idx) { time_t t; if (!dcc_flood_thr) return 0; t = now; if (*timer != t) { *timer = t; chat->msgs_per_sec = 0; } else { chat->msgs_per_sec++; if (chat->msgs_per_sec > dcc_flood_thr) { /* FLOOD */ dprintf(idx, "*** FLOOD: %s.\n", IRC_GOODBYE); /* Evil assumption here that flags&DCT_CHAT implies chat type */ if ((dcc[idx].type->flags & DCT_CHAT) && chat && (chat->channel >= 0)) { char x[1024]; egg_snprintf(x, sizeof x, DCC_FLOODBOOT, dcc[idx].nick); chanout_but(idx, chat->channel, "*** %s", x); if (chat->channel < GLOBAL_CHANS) botnet_send_part_idx(idx, x); } check_tcl_chof(dcc[idx].nick, dcc[idx].sock); if ((dcc[idx].sock != STDOUT) || backgrd) { killsock(dcc[idx].sock); lostdcc(idx); } else { dprintf(DP_STDOUT, "\n### SIMULATION RESET ###\n\n"); dcc_chatter(idx); } return 1; /* <- flood */ } } return 0; }
static void dcc_relaying(int idx, char *buf, int j) { struct chat_info *ci; if (strcasecmp(buf, "*bye*")) { dprintf(-dcc[idx].u.relay->sock, "%s\n", buf); return; } for (j = 0; (dcc[j].sock != dcc[idx].u.relay->sock) || (dcc[j].type != &DCC_RELAY); j++); dcc[idx].status = dcc[idx].u.relay->old_status; /* in case echo was off, turn it back on: */ if (dcc[idx].status & STAT_TELNET) dprintf(idx, "\377\374\001\n"); dprintf(idx, "\n(%s %s.)\n", BOT_BREAKRELAY, dcc[j].nick); dprintf(idx, "%s %s.\n\n", BOT_ABORTRELAY2, botnetnick); putlog(LOG_MISC, "*", "%s: %s -> %s", BOT_RELAYBROKEN, dcc[idx].nick, dcc[j].nick); if (dcc[idx].u.relay->chat->channel >= 0) { chanout_but(-1, dcc[idx].u.relay->chat->channel, "*** %s joined the party line.\n", dcc[idx].nick); Context; if (dcc[idx].u.relay->chat->channel < 100000) botnet_send_join_idx(idx, -1); } ci = dcc[idx].u.relay->chat; nfree(dcc[idx].u.relay); dcc[idx].u.chat = ci; dcc[idx].type = &DCC_CHAT; check_tcl_chon(dcc[idx].nick, dcc[idx].sock); if (dcc[idx].u.chat->channel >= 0) check_tcl_chjn(botnetnick, dcc[idx].nick, dcc[idx].u.chat->channel, geticon(idx), dcc[idx].sock, dcc[idx].host); killsock(dcc[j].sock); lostdcc(j); }
void set_away(int idx, char *s) { if (s == NULL) { not_away(idx); return; } if (!s[0]) { not_away(idx); return; } if (dcc[idx].u.chat->away != NULL) nfree(dcc[idx].u.chat->away); dcc[idx].u.chat->away = nmalloc(strlen(s) + 1); strcpy(dcc[idx].u.chat->away, s); if (dcc[idx].u.chat->channel >= 0) { chanout_but(-1, dcc[idx].u.chat->channel, "*** %s is now away: %s\n", dcc[idx].nick, s); if (dcc[idx].u.chat->channel < GLOBAL_CHANS) { botnet_send_away(-1, botnetnick, dcc[idx].sock, s, idx); } } dprintf(idx, "You are now away.\n"); check_tcl_away(botnetnick, dcc[idx].sock, s); }
static int cmd_assoc(struct userrec *u, int idx, char *par) { char *num; int chan; if (!par[0]) { putlog(LOG_CMDS, "*", "#%s# assoc", dcc[idx].nick); dump_assoc(idx); } else if (!u || !(u->flags & USER_BOTMAST)) dprintf(idx, "%s", MISC_NOSUCHCMD); else { num = newsplit(&par); if (num[0] == '*') { chan = GLOBAL_CHANS + atoi(num + 1); if ((chan < GLOBAL_CHANS) || (chan > 199999)) { dprintf(idx, "%s\n", ASSOC_LCHAN_RANGE); return 0; } } else { chan = atoi(num); if (chan == 0) { dprintf(idx, "%s\n", ASSOC_PARTYLINE); return 0; } else if ((chan < 1) || (chan >= GLOBAL_CHANS)) { dprintf(idx, "%s\n", ASSOC_CHAN_RANGE); return 0; } } if (!par[0]) { /* Remove an association */ if (get_assoc_name(chan) == NULL) { dprintf(idx, ASSOC_NONAME_CHAN, (chan < GLOBAL_CHANS) ? "" : "*", chan % GLOBAL_CHANS); return 0; } kill_assoc(chan); putlog(LOG_CMDS, "*", "#%s# assoc %d", dcc[idx].nick, chan); dprintf(idx, ASSOC_REMNAME_CHAN, (chan < GLOBAL_CHANS) ? "" : "*", chan % GLOBAL_CHANS); chanout_but(-1, chan, ASSOC_REMOUT_CHAN, dcc[idx].nick); if (chan < GLOBAL_CHANS) botnet_send_assoc(-1, chan, dcc[idx].nick, "0"); return 0; } if (strlen(par) > 20) { dprintf(idx, "%s\n", ASSOC_CHNAME_TOOLONG); return 0; } if ((par[0] >= '0') && (par[0] <= '9')) { dprintf(idx, "%s\n", ASSOC_CHNAME_FIRSTCHAR); return 0; } add_assoc(par, chan); putlog(LOG_CMDS, "*", "#%s# assoc %d %s", dcc[idx].nick, chan, par); dprintf(idx, ASSOC_NEWNAME_CHAN, (chan < GLOBAL_CHANS) ? "" : "*", chan % GLOBAL_CHANS, par); chanout_but(-1, chan, ASSOC_NEWOUT_CHAN, dcc[idx].nick, par); if (chan < GLOBAL_CHANS) botnet_send_assoc(-1, chan, dcc[idx].nick, par); } return 0; }
/* join <bot> <nick> <chan> <flag><sock> <from> */ static void bot_join(int idx, char *par) { char *bot, *nick, *x, *y; struct userrec *u; int i, sock, chan, i2, linking = 0; if (bot_flags(dcc[idx].user) & BOT_ISOLATE) return; bot = newsplit(&par); #ifndef NO_OLD_BOTNET if (dcc[idx].u.bot->numver >= NEAT_BOTNET) #endif if (bot[0] == '!') { linking = 1; bot++; } if (dcc[idx].status & BSTAT_LINKING) linking = 1; nick = newsplit(&par); x = newsplit(&par); #ifndef NO_OLD_BOTNET if (dcc[idx].u.bot->numver < NEAT_BOTNET) chan = atoi(x); else #endif chan = base64_to_int(x); y = newsplit(&par); if ((chan < 0) || !y[0]) return; /* Woops! pre 1.2.1's send .chat off'ers * too!! */ if (!y[0]) { y[0] = '-'; sock = 0; } else { #ifndef NO_OLD_BOTNET if (dcc[idx].u.bot->numver < NEAT_BOTNET) sock = atoi(y + 1); else #endif sock = base64_to_int(y + 1); } /* 1.1 bots always send a sock#, even on a channel change * so if sock# is 0, this is from an old bot and we must tread softly * grab old sock# if there is one, otherwise make up one. */ if (sock == 0) sock = partysock(bot, nick); if (sock == 0) sock = fakesock++; i = nextbot(bot); if (i != idx) { /* Ok, garbage from a 1.0g (who uses that * now?) OR raistlin being evil :) */ fake_alert(idx, "direction", bot); return; } u = get_user_by_handle(userlist, nick); if (u) { sprintf(TBUF, "@%s", bot); touch_laston(u, TBUF, now); } i = addparty(bot, nick, chan, y[0], sock, par, &i2); botnet_send_join_party(idx, linking, i2, i); if (i != chan) { if (i >= 0) { if (dcc[idx].u.bot->numver >= NEAT_BOTNET) chanout_but(-1, i, "*** (%s) %s %s %s.\n", bot, nick, NET_LEFTTHE, i ? "channel" : "party line"); check_tcl_chpt(bot, nick, sock, i); } if ((dcc[idx].u.bot->numver >= NEAT_BOTNET) && !linking) chanout_but(-1, chan, "*** (%s) %s %s %s.\n", bot, nick, NET_JOINEDTHE, chan ? "channel" : "party line"); check_tcl_chjn(bot, nick, chan, y[0], sock, par); } }