static void bs_cmd_set_nobot(sourceinfo_t *si, int parc, char *parv[]) { char *channel = parv[0]; char *option = parv[1]; mychan_t *mc; metadata_t *md; if (parc < 2 || !channel || !option) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET NOBOT"); command_fail(si, fault_needmoreparams, _("Syntax: SET <#channel> NOBOT {ON|OFF}")); return; } mc = mychan_find(channel); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), channel); return; } if (!si->smu) { command_fail(si, fault_noprivs, _("You are not logged in.")); return; } if (!has_priv(si, PRIV_CHAN_ADMIN)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } if (!irccasecmp(option, "ON")) { metadata_add(mc, "private:botserv:no-bot", "ON"); if ((md = metadata_find(mc, "private:botserv:bot-assigned")) != NULL) { if (mc->flags & MC_GUARD && (!config_options.leave_chans || (mc->chan != NULL && LIST_LENGTH(&mc->chan->members) > 1))) join(mc->name, chansvs.nick); part(mc->name, md->value); metadata_delete(mc, "private:botserv:bot-assigned"); metadata_delete(mc, "private:botserv:bot-handle-fantasy"); } command_success_nodata(si, _("No Bot mode is now \2ON\2 on channel %s."), mc->name); } else if(!irccasecmp(option, "OFF")) { metadata_delete(mc, "private:botserv:no-bot"); command_success_nodata(si, _("No Bot mode is now \2OFF\2 on channel %s."), mc->name); } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "SET NOBOT"); command_fail(si, fault_badparams, _("Syntax: SET <#channel> NOBOT {ON|OFF}")); } }
static void bs_cmd_set_saycaller(struct sourceinfo *si, int parc, char *parv[]) { char *channel = parv[0]; char *option = parv[1]; struct mychan *mc; struct metadata *md; if (parc < 2 || !channel || !option) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET SAYCALLER"); command_fail(si, fault_needmoreparams, _("Syntax: SET <#channel> SAYCALLER {ON|OFF}")); return; } mc = mychan_find(channel); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), channel); return; } if (!chanacs_source_has_flag(mc, si, CA_SET)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } if (metadata_find(mc, "private:frozen:freezer")) { command_fail(si, fault_noprivs, _("\2%s\2 is frozen."), mc->name); return; } if (!irccasecmp(option, "ON")) { if ((md = metadata_find(mc, "private:botserv:bot-assigned")) != NULL) metadata_add(mc, "private:botserv:saycaller", md->value); logcommand(si, CMDLOG_SET, "SET:SAYCALLER:ON: \2%s\2", mc->name); command_success_nodata(si, _("Say Caller is now \2ON\2 on channel %s."), mc->name); } else if(!irccasecmp(option, "OFF")) { metadata_delete(mc, "private:botserv:saycaller"); logcommand(si, CMDLOG_SET, "SET:SAYCALLER:OFF: \2%s\2", mc->name); command_success_nodata(si, _("Say Caller is now \2OFF\2 on channel %s."), mc->name); } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "SET SAYCALLER"); command_fail(si, fault_badparams, _("Syntax: SET <#channel> SAYCALLER {ON|OFF}")); } }
static void bs_cmd_set_fantasy(sourceinfo_t *si, int parc, char *parv[]) { char *channel = parv[0]; char *option = parv[1]; mychan_t *mc; metadata_t *md; if (parc < 2 || !channel || !option) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET FANTASY"); command_fail(si, fault_needmoreparams, _("Syntax: SET <#channel> FANTASY {ON|OFF}")); return; } mc = mychan_find(channel); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), channel); return; } if (!si->smu) { command_fail(si, fault_noprivs, _("You are not logged in.")); return; } if (!chanacs_source_has_flag(mc, si, CA_SET)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } if (!irccasecmp(option, "ON")) { if ((md = metadata_find(mc, "private:botserv:bot-assigned")) != NULL) metadata_add(mc, "private:botserv:bot-handle-fantasy", md->value); command_success_nodata(si, _("Fantasy mode is now \2ON\2 on channel %s."), mc->name); } else if(!irccasecmp(option, "OFF")) { metadata_delete(mc, "private:botserv:bot-handle-fantasy"); command_success_nodata(si, _("Fantasy mode is now \2OFF\2 on channel %s."), mc->name); } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "SET FANTASY"); command_fail(si, fault_badparams, _("Syntax: SET <#channel> FANTASY {ON|OFF}")); } }
static void bs_cmd_set_fantasy(struct sourceinfo *si, int parc, char *parv[]) { char *channel = parv[0]; char *option = parv[1]; struct mychan *mc; struct metadata *md; if (parc < 2 || !channel || !option) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET FANTASY"); command_fail(si, fault_needmoreparams, _("Syntax: SET <#channel> FANTASY {ON|OFF}")); return; } mc = mychan_find(channel); if (!mc) { command_fail(si, fault_nosuch_target, STR_IS_NOT_REGISTERED, channel); return; } if (!chanacs_source_has_flag(mc, si, CA_SET)) { command_fail(si, fault_noprivs, STR_NOT_AUTHORIZED); return; } if (!irccasecmp(option, "ON")) { if ((md = metadata_find(mc, "private:botserv:bot-assigned")) != NULL) metadata_add(mc, "private:botserv:bot-handle-fantasy", md->value); logcommand(si, CMDLOG_SET, "SET:FANTASY:ON: \2%s\2", mc->name); command_success_nodata(si, _("Fantasy mode is now \2ON\2 on channel %s."), mc->name); } else if(!irccasecmp(option, "OFF")) { metadata_delete(mc, "private:botserv:bot-handle-fantasy"); logcommand(si, CMDLOG_SET, "SET:FANTASY:OFF: \2%s\2", mc->name); command_success_nodata(si, _("Fantasy mode is now \2OFF\2 on channel %s."), mc->name); } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "SET FANTASY"); command_fail(si, fault_badparams, _("Syntax: SET <#channel> FANTASY {ON|OFF}")); } }
static void nick_ungroup(hook_user_req_t *hdata) { user_t *u; u = hdata->si->su != NULL && !irccasecmp(hdata->si->su->nick, hdata->mn->nick) ? hdata->si->su : user_find_named(hdata->mn->nick); if (u != NULL && !nicksvs.no_nick_ownership) sts(":%s ENCAP * IDENTIFIED %s %s OFF", ME, CLIENT_NAME(u), u->nick); }
static void nick_group(hook_user_req_t *hdata) { user_t *u; u = hdata->si->su != NULL && !irccasecmp(hdata->si->su->nick, hdata->mn->nick) ? hdata->si->su : user_find_named(hdata->mn->nick); if (u != NULL && should_reg_umode(u)) sts(":%s ENCAP * IDENTIFIED %s %s", ME, CLIENT_NAME(u), u->nick); }
static void nick_ungroup(hook_user_req_t *hdata) { user_t *u; u = hdata->si->su != NULL && !irccasecmp(hdata->si->su->nick, hdata->mn->nick) ? hdata->si->su : user_find_named(hdata->mn->nick); if (u != NULL && !nicksvs.no_nick_ownership) sts(":%s ENCAP * SVSMODE %s %lu -r", nicksvs.nick, u->nick, (unsigned long)u->ts); }
static void nick_group(hook_user_req_t *hdata) { user_t *u; u = hdata->si->su != NULL && !irccasecmp(hdata->si->su->nick, hdata->mn->nick) ? hdata->si->su : user_find_named(hdata->mn->nick); if (u != NULL && should_reg_umode(u)) sts(":%s ENCAP * SVSMODE %s %lu +rd %lu", nicksvs.nick, u->nick, (unsigned long)u->ts, (unsigned long)CURRTIME); }
static void cs_cmd_drop(char *origin) { user_t *u = user_find_named(origin); mychan_t *mc; char *name = strtok(NULL, " "); if (!name) { notice(chansvs.nick, origin, STR_INSUFFICIENT_PARAMS, "DROP"); notice(chansvs.nick, origin, "Syntax: DROP <#channel>"); return; } if (*name != '#') { notice(chansvs.nick, origin, STR_INVALID_PARAMS, "DROP"); notice(chansvs.nick, origin, "Syntax: DROP <#channel>"); return; } if (!(mc = mychan_find(name))) { notice(chansvs.nick, origin, "\2%s\2 is not registered.", name); return; } if (!is_founder(mc, u->myuser) && !has_priv(u, PRIV_CHAN_ADMIN)) { notice(chansvs.nick, origin, "You are not authorized to perform this operation."); return; } if (metadata_find(mc, METADATA_CHANNEL, "private:close:closer") && !has_priv(u, PRIV_CHAN_ADMIN)) { logcommand(chansvs.me, u, CMDLOG_REGISTER, "%s failed DROP (closed)", mc->name); notice(chansvs.nick, origin, "The channel \2%s\2 is closed; it cannot be dropped.", mc->name); return; } if (!is_founder(mc, u->myuser)) { logcommand(chansvs.me, u, CMDLOG_ADMIN, "%s DROP", mc->name); wallops("%s dropped the channel \2%s\2", origin, name); } else logcommand(chansvs.me, u, CMDLOG_REGISTER, "%s DROP", mc->name); snoop("DROP: \2%s\2 by \2%s\2 as \2%s\2", mc->name, u->nick, u->myuser->name); hook_call_event("channel_drop", mc); if ((config_options.chan && irccasecmp(mc->name, config_options.chan)) || !config_options.chan) part(mc->name, chansvs.nick); mychan_delete(mc->name); notice(chansvs.nick, origin, "The channel \2%s\2 has been dropped.", name); return; }
static void os_cmd_jupe(sourceinfo_t *si, int parc, char *parv[]) { char *server = parv[0]; char *reason = parv[1]; char reasonbuf[BUFSIZE]; if (!server || !reason) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "JUPE"); command_fail(si, fault_needmoreparams, _("Usage: JUPE <server> <reason>")); return; } /* Disallow * in a jupe as a minimal sanity check; it makes it hard to * squit safely. */ if (!strchr(server, '.') || strchr(server, '*') || strchr(server, '?')) { command_fail(si, fault_badparams, _("\2%s\2 is not a valid server name."), server); return; } if (!irccasecmp(server, me.name)) { command_fail(si, fault_noprivs, _("\2%s\2 is the services server; it cannot be jupitered!"), server); return; } if (!irccasecmp(server, me.actual)) { command_fail(si, fault_noprivs, _("\2%s\2 is the current uplink; it cannot be jupitered!"), server); return; } logcommand(si, CMDLOG_ADMIN, "JUPE: \2%s\2 (reason: \2%s\2)", server, reason); wallops(_("%s jupitered server \2%s\2 (%s)."), get_oper_name(si), server, reason); snprintf(reasonbuf, BUFSIZE, "[%s] %s", get_oper_name(si), reason); jupe(server, reasonbuf); command_success_nodata(si, _("\2%s\2 has been jupitered."), server); }
static void plexus_sethost_sts(user_t *source, user_t *target, const char *host) { if (!me.connected) return; if (irccasecmp(target->host, host)) numeric_sts(me.me, 396, target, "%s :is now your hidden host (set by %s)", host, source->nick); else { numeric_sts(me.me, 396, target, "%s :hostname reset by %s", host, source->nick); sts(":%s ENCAP * SVSMODE %s %lu -x", CLIENT_NAME(source), CLIENT_NAME(target), (unsigned long)target->ts); } sts(":%s ENCAP * CHGHOST %s :%s", ME, CLIENT_NAME(target), host); }
static void list_one(sourceinfo_t *si, myuser_t *mu, mynick_t *mn) { char buf[BUFSIZE]; if (mn != NULL) mu = mn->owner; *buf = '\0'; if (metadata_find(mu, "private:freeze:freezer")) { if (*buf) mowgli_strlcat(buf, " ", BUFSIZE); mowgli_strlcat(buf, "\2[frozen]\2", BUFSIZE); } if (metadata_find(mu, "private:mark:setter")) { if (*buf) mowgli_strlcat(buf, " ", BUFSIZE); mowgli_strlcat(buf, "\2[marked]\2", BUFSIZE); } if (metadata_find(mu, "private:restrict:setter")) { if (*buf) mowgli_strlcat(buf, " ", BUFSIZE); mowgli_strlcat(buf, "\2[restricted]\2", BUFSIZE); } if (mu->flags & MU_HOLD) { if (*buf) mowgli_strlcat(buf, " ", BUFSIZE); mowgli_strlcat(buf, "\2[held]\2", BUFSIZE); } if (mu->flags & MU_WAITAUTH) { if (*buf) mowgli_strlcat(buf, " ", BUFSIZE); mowgli_strlcat(buf, "\2[unverified]\2", BUFSIZE); } if (mn == NULL || !irccasecmp(mn->nick, entity(mu)->name)) command_success_nodata(si, "- %s (%s) %s", entity(mu)->name, mu->email, buf); else command_success_nodata(si, "- %s (%s) (%s) %s", mn->nick, mu->email, entity(mu)->name, buf); }
static void ns_cmd_ungroup(sourceinfo_t *si, int parc, char *parv[]) { mynick_t *mn; const char *target; hook_user_req_t hdata; if (parc >= 1) target = parv[0]; else if (si->su != NULL) target = si->su->nick; else target = "?"; mn = mynick_find(target); if (mn == NULL) { command_fail(si, fault_nosuch_target, _("Nick \2%s\2 is not registered."), target); return; } if (mn->owner != si->smu) { command_fail(si, fault_noprivs, _("Nick \2%s\2 is not registered to your account."), mn->nick); return; } if (!irccasecmp(mn->nick, entity(si->smu)->name)) { command_fail(si, fault_noprivs, _("Nick \2%s\2 is your account name; you may not remove it."), mn->nick); return; } logcommand(si, CMDLOG_REGISTER, "UNGROUP: \2%s\2", mn->nick); hdata.si = si; hdata.mu = si->smu; hdata.mn = mn; hook_call_nick_ungroup(&hdata); holdnick_sts(si->service->me, 0, mn->nick, NULL); command_success_nodata(si, _("Nick \2%s\2 has been removed from your account."), mn->nick); object_unref(mn); }
static void bs_cmd_set_private(sourceinfo_t *si, int parc, char *parv[]) { char *botserv = parv[0]; char *option = parv[1]; botserv_bot_t *bot; if (parc < 2 || !botserv || !option) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET PRIVATE"); command_fail(si, fault_needmoreparams, _("Syntax: SET <botnick> PRIVATE {ON|OFF}")); return; } bot = botserv_bot_find(botserv); if (!bot) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not a bot."), botserv); return; } if (!si->smu) { command_fail(si, fault_noprivs, _("You are not logged in.")); return; } if (!has_priv(si, PRIV_CHAN_ADMIN)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } if (!irccasecmp(option, "ON")) { bot->private = true; botserv_save_database(NULL); command_success_nodata(si, _("Private mode of bot %s is now \2ON\2."), bot->nick); }
static void cs_cmd_unban(sourceinfo_t *si, int parc, char *parv[]) { const char *channel = parv[0]; const char *target = parv[1]; channel_t *c = channel_find(channel); mychan_t *mc = mychan_find(channel); user_t *tu; chanban_t *cb; if (!channel) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "UNBAN"); command_fail(si, fault_needmoreparams, _("Syntax: UNBAN <#channel> <nickname|hostmask>")); return; } if (!target) { if (si->su == NULL) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "UNBAN"); command_fail(si, fault_needmoreparams, _("Syntax: UNBAN <#channel> <nickname|hostmask>")); return; } target = si->su->nick; } if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), channel); return; } if (!c) { command_fail(si, fault_nosuch_target, _("\2%s\2 is currently empty."), channel); return; } if (!chanacs_source_has_flag(mc, si, CA_REMOVE) && (si->su == NULL || !chanacs_source_has_flag(mc, si, CA_EXEMPT) || irccasecmp(target, si->su->nick))) { command_fail(si, fault_noprivs, STR_NOT_AUTHORIZED); return; } if ((tu = user_find_named(target))) { mowgli_node_t *n, *tn; char hostbuf2[BUFSIZE]; int count = 0; snprintf(hostbuf2, BUFSIZE, "%s!%s@%s", tu->nick, tu->user, tu->vhost); for (n = next_matching_ban(c, tu, 'b', c->bans.head); n != NULL; n = next_matching_ban(c, tu, 'b', tn)) { tn = n->next; cb = n->data; logcommand(si, CMDLOG_DO, "UNBAN: \2%s\2 on \2%s\2 (for user \2%s\2)", cb->mask, mc->name, hostbuf2); modestack_mode_param(chansvs.nick, c, MTYPE_DEL, cb->type, cb->mask); chanban_delete(cb); count++; } if (count > 0) command_success_nodata(si, _("Unbanned \2%s\2 on \2%s\2 (%d ban%s removed)."), target, channel, count, (count != 1 ? "s" : "")); else command_success_nodata(si, _("No bans found matching \2%s\2 on \2%s\2."), target, channel); return; } else if ((cb = chanban_find(c, target, 'b')) != NULL || validhostmask(target)) { if (cb) { modestack_mode_param(chansvs.nick, c, MTYPE_DEL, 'b', target); chanban_delete(cb); logcommand(si, CMDLOG_DO, "UNBAN: \2%s\2 on \2%s\2", target, mc->name); if (si->su == NULL || !chanuser_find(mc->chan, si->su)) command_success_nodata(si, _("Unbanned \2%s\2 on \2%s\2."), target, channel); } else command_fail(si, fault_nosuch_key, _("No such ban \2%s\2 on \2%s\2."), target, channel); return; } else { command_fail(si, fault_badparams, _("Invalid nickname/hostmask provided: \2%s\2"), target); command_fail(si, fault_badparams, _("Syntax: UNBAN <#channel> [nickname|hostmask]")); return; } }
static void m_nick(sourceinfo_t *si, int parc, char *parv[]) { server_t *s; user_t *u; bool realchange; /* -> NICK jilles 1 1136143909 ~jilles 192.168.1.5 jaguar.test :Jilles Tjoelker */ if (parc == 7) { s = server_find(parv[5]); if (!s) { slog(LG_DEBUG, "m_nick(): new user on nonexistant server: %s", parv[5]); return; } slog(LG_DEBUG, "m_nick(): new user on `%s': %s", s->name, parv[0]); u = user_add(parv[0], parv[3], parv[4], NULL, NULL, NULL, parv[6], s, atoi(parv[2])); if (u == NULL) return; /* Ok, we have the user ready to go. * Here's the deal -- if the user's SVID is before * the start time, and not 0, then check to see * if it's a registered account or not. * * If it IS registered, deal with that accordingly, * via handle_burstlogin(). --nenolod */ handle_nickchange(u); } /* if it's only 2 then it's a nickname change */ else if (parc == 2) { if (!si->su) { slog(LG_DEBUG, "m_nick(): server trying to change nick: %s", si->s != NULL ? si->s->name : "<none>"); return; } slog(LG_DEBUG, "m_nick(): nickname change from `%s': %s", si->su->nick, parv[0]); realchange = irccasecmp(si->su->nick, parv[0]); if (user_changenick(si->su, parv[0], atoi(parv[1]))) return; /* fix up +r if necessary -- jilles */ if (realchange && should_reg_umode(si->su)) /* changed nick to registered one, reset +r */ sts(":%s SVSMODE %s +rd %lu", nicksvs.nick, parv[0], (unsigned long)CURRTIME); handle_nickchange(si->su); } else { int i; slog(LG_DEBUG, "m_nick(): got NICK with wrong number of params"); for (i = 0; i < parc; i++) slog(LG_DEBUG, "m_nick(): parv[%d] = %s", i, parv[i]); } }
static void cs_cmd_unban(struct sourceinfo *si, int parc, char *parv[]) { const char *channel = parv[0]; const char *target = parv[1]; struct channel *c = channel_find(channel); struct mychan *mc = mychan_find(channel); struct user *tu; struct chanban *cb; if (si->su == NULL) { command_fail(si, fault_noprivs, STR_IRC_COMMAND_ONLY, "UNBAN"); return; } if (!channel) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "UNBAN"); command_fail(si, fault_needmoreparams, _("Syntax: UNBAN <#channel>")); return; } if (target && irccasecmp(target, si->su->nick)) { command_fail(si, fault_noprivs, _("You may only unban yourself via %s."), si->service->nick); if (validhostmask(target)) command_fail(si, fault_noprivs, _("Try \2/mode %s -b %s\2"), channel, target); return; } target = si->su->nick; if (!mc) { command_fail(si, fault_nosuch_target, STR_IS_NOT_REGISTERED, channel); return; } if (!c) { command_fail(si, fault_nosuch_target, STR_CHANNEL_IS_EMPTY, channel); return; } if (!si->smu) { command_fail(si, fault_noprivs, STR_NOT_LOGGED_IN); return; } if (!chanacs_source_has_flag(mc, si, CA_REMOVE) && !chanacs_source_has_flag(mc, si, CA_EXEMPT)) { command_fail(si, fault_noprivs, STR_NOT_AUTHORIZED); return; } tu = si->su; { mowgli_node_t *n, *tn; char hostbuf2[BUFSIZE]; unsigned int count = 0; snprintf(hostbuf2, BUFSIZE, "%s!%s@%s", tu->nick, tu->user, tu->vhost); for (n = next_matching_ban(c, tu, 'b', c->bans.head); n != NULL; n = next_matching_ban(c, tu, 'b', tn)) { tn = n->next; cb = n->data; logcommand(si, CMDLOG_DO, "UNBAN: \2%s\2 \2%s\2 (for user \2%s\2)", mc->name, cb->mask, hostbuf2); modestack_mode_param(chansvs.nick, c, MTYPE_DEL, cb->type, cb->mask); chanban_delete(cb); count++; } if (count > 0) command_success_nodata(si, ngettext(N_("Unbanned \2%s\2 on \2%s\2 (%u ban removed)."), N_("Unbanned \2%s\2 on \2%s\2 (%u bans removed)."), count), target, channel, count); else command_success_nodata(si, _("No bans found matching \2%s\2 on \2%s\2."), target, channel); return; } }
/* * user_add(const char *nick, const char *user, const char *host, const char *vhost, const char *ip, * const char *uid, const char *gecos, server_t *server, time_t ts); * * User object factory. * * Inputs: * - nickname of new user * - username of new user * - hostname of new user * - virtual hostname of new user if applicable otherwise NULL * - ip of user if applicable otherwise NULL * - unique identifier (UID) of user if appliable otherwise NULL * - gecos of new user * - pointer to server new user is on * - user's timestamp * * Outputs: * - on success, a new user * - on failure, NULL * * Side Effects: * - if successful, a user is created and added to the users DTree. * - if unsuccessful, a kill has been sent if necessary */ user_t *user_add(const char *nick, const char *user, const char *host, const char *vhost, const char *ip, const char *uid, const char *gecos, server_t *server, time_t ts) { user_t *u, *u2; hook_user_nick_t hdata; slog(LG_DEBUG, "user_add(): %s (%s@%s) -> %s", nick, user, host, server->name); u2 = user_find_named(nick); if (u2 != NULL) { if (server == me.me) { /* caller should not let this happen */ slog(LG_ERROR, "user_add(): tried to add local nick %s which already exists", nick); return NULL; } slog(LG_INFO, "user_add(): nick collision on %s", nick); if (u2->server == me.me) { if (uid != NULL) { /* If the new client has a UID, our * client will have a UID too and the * remote server will send us a kill * if it kills our client. So just kill * their client and continue. */ kill_id_sts(NULL, uid, "Nick collision with services (new)"); return NULL; } if (ts == u2->ts || ((ts < u2->ts) ^ (!irccasecmp(user, u2->user) && !irccasecmp(host, u2->host)))) { /* If the TSes are equal, or if their TS * is less than our TS and the u@h differs, * or if our TS is less than their TS and * the u@h is equal, our client will be * killed. * * Hope that a kill has arrived just before * for our client; we will have reintroduced * it. */ return NULL; } else /* Our client will not be killed. */ return NULL; } else { wallops("Server %s is introducing nick %s which already exists on %s", server->name, nick, u2->server->name); if (uid != NULL && u2->uid != NULL) { kill_id_sts(NULL, uid, "Ghost detected via nick collision (new)"); kill_id_sts(NULL, u2->uid, "Ghost detected via nick collision (old)"); user_delete(u2, "Ghost detected via nick collision (old)"); } else { /* There is no way we can do this properly. */ kill_id_sts(NULL, nick, "Ghost detected via nick collision"); user_delete(u2, "Ghost detected via nick collision"); } return NULL; } } u = mowgli_heap_alloc(user_heap); object_init(object(u), nick, (destructor_t) user_delete); if (uid != NULL) { u->uid = strshare_get(uid); mowgli_patricia_add(uidlist, u->uid, u); } u->nick = strshare_get(nick); u->user = strshare_get(user); u->host = strshare_get(host); u->gecos = strshare_get(gecos); u->chost = strshare_get(vhost ? vhost : host); u->vhost = strshare_get(vhost ? vhost : host); if (ip && strcmp(ip, "0") && strcmp(ip, "0.0.0.0") && strcmp(ip, "255.255.255.255")) u->ip = strshare_get(ip); u->server = server; u->server->users++; mowgli_node_add(u, &u->snode, &u->server->userlist); u->ts = ts ? ts : CURRTIME; mowgli_patricia_add(userlist, u->nick, u); cnt.user++; hdata.u = u; hdata.oldnick = NULL; hook_call_user_add(&hdata); return hdata.u; }
static GLOBAL_FUNC(cmd_notice) { struct globalMessage *message = NULL; const char *recipient = NULL, *text; char *sender; long target = 0; assert(argc >= 3); sender = user->handle_info->handle; if(!irccasecmp(argv[1], "all")) { target = MESSAGE_RECIPIENT_ALL; } else if(!irccasecmp(argv[1], "users")) { target = MESSAGE_RECIPIENT_LUSERS; } else if(!irccasecmp(argv[1], "authed")) { target = MESSAGE_RECIPIENT_AUTHED; } else if(!irccasecmp(argv[1], "helpers")) { target = MESSAGE_RECIPIENT_HELPERS; } else if(!irccasecmp(argv[1], "opers")) { target = MESSAGE_RECIPIENT_OPERS; } else if(!irccasecmp(argv[1], "staff") || !irccasecmp(argv[1], "privileged")) { target |= MESSAGE_RECIPIENT_HELPERS | MESSAGE_RECIPIENT_OPERS; } else if(!irccasecmp(argv[1], "announcement") || !irccasecmp(argv[1], "announce")) { target |= MESSAGE_RECIPIENT_ANNOUNCE; } else if(!irccasecmp(argv[1], "channels")) { target = MESSAGE_RECIPIENT_CHANNELS; } else if(!irccasecmp(argv[1], "rchannels")) { target = MESSAGE_RECIPIENT_RCHANNELS; } else { global_notice(user, "GMSG_INVALID_TARGET", argv[1]); return 0; } if(!irccasecmp(argv[2], "from")) { if (argc < 5) { reply("MSG_MISSING_PARAMS", argv[0]); GLOBAL_SYNTAX(); return 0; } sender = argv[3]; text = unsplit_string(argv + 4, argc - 4, NULL); } else { text = unsplit_string(argv + 2, argc - 2, NULL); } message = message_add(target | MESSAGE_OPTION_IMMEDIATE, now, 0, sender, text); if(!message) return 0; recipient = messageType(message); message_send(message); message_del(message); global_notice(user, "GMSG_MESSAGE_SENT", recipient); return 1; }
static void ns_cmd_fungroup(sourceinfo_t *si, int parc, char *parv[]) { mynick_t *mn, *mn2 = NULL; myuser_t *mu; hook_user_req_t hdata; if (parc < 1) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "FUNGROUP"); command_fail(si, fault_needmoreparams, _("Syntax: FUNGROUP <nickname> [newaccountname]")); return; } mn = mynick_find(parv[0]); if (mn == NULL) { command_fail(si, fault_nosuch_target, _("Nick \2%s\2 is not registered."), parv[0]); return; } mu = mn->owner; if (!irccasecmp(mn->nick, entity(mu)->name)) { if (MOWGLI_LIST_LENGTH(&mu->nicks) <= 1 || !module_find_published("nickserv/set_accountname")) { command_fail(si, fault_noprivs, _("Nick \2%s\2 is an account name; you may not remove it."), mn->nick); return; } if (is_conf_soper(mu)) { command_fail(si, fault_noprivs, _("You may not modify \2%s\2's account name because their operclass is defined in the configuration file."), entity(mu)->name); return; } if (parc < 2) { command_fail(si, fault_needmoreparams, _("Please specify a new account name for \2%s\2."), entity(mu)->name); command_fail(si, fault_needmoreparams, _("Syntax: FUNGROUP <nickname> <newaccountname>")); return; } mn2 = mynick_find(parv[1]); if (mn2 == NULL) { command_fail(si, fault_nosuch_target, _("Nick \2%s\2 is not registered."), parv[1]); return; } if (mn2 == mn) { command_fail(si, fault_noprivs, _("The new account name must be different from the nick to be ungrouped.")); return; } if (mn2->owner != mu) { command_fail(si, fault_noprivs, _("Nick \2%s\2 is not registered to \2%s\2."), mn2->nick, entity(mu)->name); return; } } else if (parc > 1) { command_fail(si, fault_badparams, _("Nick \2%s\2 is not an account name so no new account name is needed."), mn->nick); return; } if (mn2 != NULL) { logcommand(si, CMDLOG_ADMIN | LG_REGISTER, "FUNGROUP: \2%s\2 from \2%s\2 (new account name: \2%s\2)", mn->nick, entity(mu)->name, mn2->nick); wallops("%s dropped the nick \2%s\2 from %s, changing account name to \2%s\2", get_oper_name(si), mn->nick, entity(mu)->name, mn2->nick); myuser_rename(mu, mn2->nick); } else { logcommand(si, CMDLOG_ADMIN | LG_REGISTER, "FUNGROUP: \2%s\2 from \2%s\2", mn->nick, entity(mu)->name); wallops("%s dropped the nick \2%s\2 from %s", get_oper_name(si), mn->nick, entity(mu)->name); } hdata.si = si; hdata.mu = mu; hdata.mn = mn; hook_call_nick_ungroup(&hdata); holdnick_sts(si->service->me, 0, mn->nick, NULL); if (mn2 != NULL) command_success_nodata(si, _("Nick \2%s\2 has been removed from account \2%s\2, name changed to \2%s\2."), mn->nick, entity(mu)->name, mn2->nick); else command_success_nodata(si, _("Nick \2%s\2 has been removed from account \2%s\2."), mn->nick, entity(mu)->name); object_unref(mn); }
static void cs_cmd_unban(sourceinfo_t *si, int parc, char *parv[]) { const char *channel = parv[0]; const char *target = parv[1]; channel_t *c = channel_find(channel); mychan_t *mc = mychan_find(channel); user_t *tu; chanban_t *cb; if (si->su == NULL) { command_fail(si, fault_noprivs, _("\2%s\2 can only be executed via IRC."), "UNBAN"); return; } if (!channel) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "UNBAN"); command_fail(si, fault_needmoreparams, _("Syntax: UNBAN <#channel>")); return; } if (target && irccasecmp(target, si->su->nick)) { command_fail(si, fault_noprivs, _("You may only unban yourself via %s."), si->service->nick); if (validhostmask(target)) command_fail(si, fault_noprivs, _("Try \2/mode %s -b %s\2"), channel, target); return; } target = si->su->nick; if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), channel); return; } if (!c) { command_fail(si, fault_nosuch_target, _("\2%s\2 is currently empty."), channel); return; } if (!si->smu) { command_fail(si, fault_noprivs, _("You are not logged in.")); return; } if (!chanacs_source_has_flag(mc, si, CA_REMOVE)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } tu = si->su; { mowgli_node_t *n, *tn; char hostbuf2[BUFSIZE]; int count = 0; snprintf(hostbuf2, BUFSIZE, "%s!%s@%s", tu->nick, tu->user, tu->vhost); for (n = next_matching_ban(c, tu, 'b', c->bans.head); n != NULL; n = next_matching_ban(c, tu, 'b', tn)) { tn = n->next; cb = n->data; logcommand(si, CMDLOG_DO, "UNBAN: \2%s\2 \2%s\2 (for user \2%s\2)", mc->name, cb->mask, hostbuf2); modestack_mode_param(chansvs.nick, c, MTYPE_DEL, cb->type, cb->mask); chanban_delete(cb); count++; } if (count > 0) command_success_nodata(si, _("Unbanned \2%s\2 on \2%s\2 (%d ban%s removed)."), target, channel, count, (count != 1 ? "s" : "")); else command_success_nodata(si, _("No bans found matching \2%s\2 on \2%s\2."), target, channel); return; } }
static void m_nick(sourceinfo_t *si, int parc, char *parv[]) { server_t *s; user_t *u; /* got the right number of args for an introduction? */ if (parc == 8) { s = server_find(parv[6]); if (!s) { slog(LG_DEBUG, "m_nick(): new user on nonexistant server: %s", parv[6]); return; } slog(LG_DEBUG, "m_nick(): new user on `%s': %s", s->name, parv[0]); u = user_add(parv[0], parv[4], parv[5], NULL, NULL, NULL, parv[7], s, atoi(parv[2])); if (u == NULL) return; user_mode(u, parv[3]); /* If server is not yet EOB we will do this later. * This avoids useless "please identify" -- jilles */ if (s->flags & SF_EOB) handle_nickchange(user_find(parv[0])); } /* if it's only 2 then it's a nickname change */ else if (parc == 2) { bool realchange; if (!si->su) { slog(LG_DEBUG, "m_nick(): server trying to change nick: %s", si->s != NULL ? si->s->name : "<none>"); return; } slog(LG_DEBUG, "m_nick(): nickname change from `%s': %s", si->su->nick, parv[0]); realchange = irccasecmp(si->su->nick, parv[0]); if (user_changenick(si->su, parv[0], atoi(parv[1]))) return; /* fix up +e if necessary -- jilles */ if (realchange && should_reg_umode(si->su)) /* changed nick to registered one, reset +e */ sts(":%s ENCAP * IDENTIFIED %s %s", ME, CLIENT_NAME(si->su), si->su->nick); /* It could happen that our PING arrived late and the * server didn't acknowledge EOB yet even though it is * EOB; don't send double notices in that case -- jilles */ if (si->su->server->flags & SF_EOB) handle_nickchange(si->su); } else { int i; slog(LG_DEBUG, "m_nick(): got NICK with wrong number of params"); for (i = 0; i < parc; i++) slog(LG_DEBUG, "m_nick(): parv[%d] = %s", i, parv[i]); } }
int slist_compare_two(const void *pa, const void *pb) { return irccasecmp(*(const char**)pa, *(const char **)pb); }
static struct globalMessage* message_create(struct userNode *user, unsigned int argc, char *argv[]) { unsigned long duration = 0; char *text = NULL; char *sender; long flags = 0; unsigned int i; sender = user->handle_info->handle; for(i = 0; i < argc; i++) { if((i + 1) > argc) { global_notice(user, "MSG_MISSING_PARAMS", argv[argc]); return NULL; } if(!irccasecmp(argv[i], "text")) { i++; text = unsplit_string(argv + i, argc - i, NULL); break; } else if (!irccasecmp(argv[i], "sourceless")) { i++; flags |= MESSAGE_OPTION_SOURCELESS; } else if (!irccasecmp(argv[i], "target")) { i++; if(!irccasecmp(argv[i], "all")) { flags |= MESSAGE_RECIPIENT_ALL; } else if(!irccasecmp(argv[i], "authed")) { flags |= MESSAGE_RECIPIENT_AUTHED; } else if(!irccasecmp(argv[i], "users")) { flags |= MESSAGE_RECIPIENT_LUSERS; } else if(!irccasecmp(argv[i], "helpers")) { flags |= MESSAGE_RECIPIENT_HELPERS; } else if(!irccasecmp(argv[i], "opers")) { flags |= MESSAGE_RECIPIENT_OPERS; } else if(!irccasecmp(argv[i], "staff") || !irccasecmp(argv[i], "privileged")) { flags |= MESSAGE_RECIPIENT_STAFF; } else if(!irccasecmp(argv[i], "channels")) { flags |= MESSAGE_RECIPIENT_CHANNELS; } else if(!irccasecmp(argv[i], "rchannels")) { flags |= MESSAGE_RECIPIENT_RCHANNELS; } else if(!irccasecmp(argv[i], "announcement") || !irccasecmp(argv[i], "announce")) { flags |= MESSAGE_RECIPIENT_ANNOUNCE; } else { global_notice(user, "GMSG_INVALID_TARGET", argv[i]); return NULL; } } else if (irccasecmp(argv[i], "duration") == 0) { duration = ParseInterval(argv[++i]); } else if (irccasecmp(argv[i], "from") == 0) { sender = argv[++i]; } else { global_notice(user, "MSG_INVALID_CRITERIA", argv[i]); return NULL; } } if(!flags) { flags = MESSAGE_RECIPIENT_LUSERS; } if(!text) { global_notice(user, "GMSG_MESSAGE_REQUIRED"); return NULL; } return message_add(flags, now, duration, sender, text); }
static void ms_cmd_fsend(sourceinfo_t *si, int parc, char *parv[]) { /* misc structs etc */ user_t *tu; myuser_t *tmu; mowgli_node_t *n; mymemo_t *memo; service_t *memoserv; /* Grab args */ char *target = parv[0]; char *m = parv[1]; /* Arg validation */ if (!target || !m) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "FSEND"); command_fail(si, fault_needmoreparams, "Syntax: FSEND <user> <memo>"); return; } if (!si->smu) { command_fail(si, fault_noprivs, _("You are not logged in.")); return; } /* rate limit it -- jilles */ if (CURRTIME - si->smu->memo_ratelimit_time > MEMO_MAX_TIME) si->smu->memo_ratelimit_num = 0; if (si->smu->memo_ratelimit_num > MEMO_MAX_NUM && !has_priv(si, PRIV_FLOOD)) { command_fail(si, fault_toomany, _("You have used this command too many times; please wait a while and try again.")); return; } /* Check for memo text length -- includes/common.h */ if (strlen(m) >= MEMOLEN) { command_fail(si, fault_badparams, "Please make sure your memo is less than %d characters", MEMOLEN); return; } /* Check to make sure the memo doesn't contain hostile CTCP responses. * realistically, we'll probably want to check the _entire_ message for this... --nenolod */ if (*m == '\001') { command_fail(si, fault_badparams, _("Your memo contains invalid characters.")); return; } memoserv = service_find("memoserv"); if (memoserv == NULL) memoserv = si->service; if (*target != '#' && *target != '!') { /* See if target is valid */ if (!(tmu = myuser_find_ext(target))) { command_fail(si, fault_nosuch_target, "\2%s\2 is not registered.", target); return; } si->smu->memo_ratelimit_num++; si->smu->memo_ratelimit_time = CURRTIME; /* Check to make sure target inbox not full */ if (tmu->memos.count >= me.mdlimit) { command_fail(si, fault_toomany, _("%s's inbox is full"), target); logcommand(si, CMDLOG_SET, "failed SEND to \2%s\2 (target inbox full)", entity(tmu)->name); return; } logcommand(si, CMDLOG_ADMIN, "FSEND: to \2%s\2", entity(tmu)->name); /* Malloc and populate struct */ memo = smalloc(sizeof(mymemo_t)); memo->sent = CURRTIME; memo->status = 0; mowgli_strlcpy(memo->sender,entity(si->smu)->name,NICKLEN); mowgli_strlcpy(memo->text, "[FORCE] ", FMEMOLEN); mowgli_strlcat(memo->text, m, FMEMOLEN); /* Create a linked list node and add to memos */ n = mowgli_node_create(); mowgli_node_add(memo, n, &tmu->memos); tmu->memoct_new++; /* Should we email this? */ if (tmu->flags & MU_EMAILMEMOS) { compat_sendemail(si->su, tmu, EMAIL_MEMO, tmu->email, memo->text); } /* Note: do not disclose other nicks they're logged in with * -- jilles * * Actually, I don't see the point in this at all. If they want this information, * they should use WHOIS. --nenolod */ tu = user_find_named(target); if (tu != NULL && tu->myuser == tmu) command_success_nodata(si, _("%s is currently online, and you may talk directly, by sending a private message."), target); /* Is the user online? If so, tell them about the new memo. */ if (si->su == NULL || !irccasecmp(si->su->nick, entity(si->smu)->name)) myuser_notice(memoserv->nick, tmu, "You have a new memo from %s (%zu).", entity(si->smu)->name, MOWGLI_LIST_LENGTH(&tmu->memos)); else myuser_notice(memoserv->nick, tmu, "You have a new memo from %s (nick: %s) (%zu).", entity(si->smu)->name, si->su->nick, MOWGLI_LIST_LENGTH(&tmu->memos)); myuser_notice(memoserv->nick, tmu, _("To read it, type /%s%s READ %zu"), ircd->uses_rcommand ? "" : "msg ", memoserv->disp, MOWGLI_LIST_LENGTH(&tmu->memos)); /* Tell user memo sent */ command_success_nodata(si, _("The memo has been successfully sent to \2%s\2."), target); } else if (*target == '#') { command_fail(si, fault_nosuch_target, _("Channel memos may not be forced.")); } else { command_fail(si, fault_nosuch_target, _("Group memos may not be forced.")); } return; }