static std::string BuildModeList(ModeType type) { std::vector<std::string> modes; for(char c='A'; c <= 'z'; c++) { ModeHandler* mh = ServerInstance->Modes->FindMode(c, type); if (mh) { std::string mdesc = mh->name; mdesc.push_back('='); if (mh->GetPrefix()) mdesc.push_back(mh->GetPrefix()); if (mh->GetModeChar()) mdesc.push_back(mh->GetModeChar()); modes.push_back(mdesc); } } sort(modes.begin(), modes.end()); irc::stringjoiner line(" ", modes, 0, modes.size() - 1); return line.GetJoined(); }
/** Handle /INVITE */ CmdResult CommandInvite::Handle (const std::vector<std::string>& parameters, User *user) { ModResult MOD_RESULT; if (parameters.size() == 2 || parameters.size() == 3) { User* u; if (IS_LOCAL(user)) u = ServerInstance->FindNickOnly(parameters[0]); else u = ServerInstance->FindNick(parameters[0]); Channel* c = ServerInstance->FindChan(parameters[1]); time_t timeout = 0; if (parameters.size() == 3) { if (IS_LOCAL(user)) timeout = ServerInstance->Time() + InspIRCd::Duration(parameters[1]); else timeout = ConvToInt(parameters[2]); } if ((!c) || (!u) || (u->registered != REG_ALL)) { user->WriteNumeric(ERR_NOSUCHNICK, "%s %s :No such nick/channel",user->nick.c_str(), c ? parameters[0].c_str() : parameters[1].c_str()); return CMD_FAILURE; } if ((IS_LOCAL(user)) && (!c->HasUser(user))) { user->WriteNumeric(ERR_NOTONCHANNEL, "%s %s :You're not on that channel!",user->nick.c_str(), c->name.c_str()); return CMD_FAILURE; } if (c->HasUser(u)) { user->WriteNumeric(ERR_USERONCHANNEL, "%s %s %s :is already on channel",user->nick.c_str(),u->nick.c_str(),c->name.c_str()); return CMD_FAILURE; } FIRST_MOD_RESULT(OnUserPreInvite, MOD_RESULT, (user,u,c,timeout)); if (MOD_RESULT == MOD_RES_DENY) { return CMD_FAILURE; } else if (MOD_RESULT == MOD_RES_PASSTHRU) { if (IS_LOCAL(user)) { unsigned int rank = c->GetPrefixValue(user); if (rank < HALFOP_VALUE) { // Check whether halfop mode is available and phrase error message accordingly ModeHandler* mh = ServerInstance->Modes->FindMode('h', MODETYPE_CHANNEL); user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :You must be a channel %soperator", user->nick.c_str(), c->name.c_str(), (mh && mh->name == "halfop" ? "half-" : "")); return CMD_FAILURE; } } } if (IS_LOCAL(u)) { Invitation::Create(c, IS_LOCAL(u), timeout); u->WriteFrom(user,"INVITE %s :%s",u->nick.c_str(),c->name.c_str()); } if (IS_LOCAL(user)) user->WriteNumeric(RPL_INVITING, "%s %s %s",user->nick.c_str(),u->nick.c_str(),c->name.c_str()); if (ServerInstance->Config->AnnounceInvites != ServerConfig::INVITE_ANNOUNCE_NONE) { char prefix; switch (ServerInstance->Config->AnnounceInvites) { case ServerConfig::INVITE_ANNOUNCE_OPS: { prefix = '@'; break; } case ServerConfig::INVITE_ANNOUNCE_DYNAMIC: { PrefixMode* mh = ServerInstance->Modes->FindPrefixMode('h'); prefix = (mh && mh->name == "halfop" ? mh->GetPrefix() : '@'); break; } default: { prefix = 0; break; } } c->WriteAllExceptSender(user, true, prefix, "NOTICE %s :*** %s invited %s into the channel", c->name.c_str(), user->nick.c_str(), u->nick.c_str()); } FOREACH_MOD(OnUserInvite, (user,u,c,timeout)); } else if (IS_LOCAL(user)) { // pinched from ircu - invite with not enough parameters shows channels // youve been invited to but haven't joined yet. InviteList& il = IS_LOCAL(user)->GetInviteList(); for (InviteList::const_iterator i = il.begin(); i != il.end(); ++i) { user->WriteNumeric(RPL_INVITELIST, "%s :%s",user->nick.c_str(), (*i)->chan->name.c_str()); } user->WriteNumeric(RPL_ENDOFINVITELIST, "%s :End of INVITE list",user->nick.c_str()); } return CMD_SUCCESS; }
CmdResult Handle(const std::vector<std::string> ¶meters, User *user) { ModeHandler* mh; Channel* chan = ServerInstance->FindChan(parameters[0]); char modeletter = parameters[1][0]; if (chan == NULL) { user->WriteNotice("The channel " + parameters[0] + " does not exist."); return CMD_FAILURE; } mh = ServerInstance->Modes->FindMode(modeletter, MODETYPE_CHANNEL); if (mh == NULL || parameters[1].size() > 1) { user->WriteNotice(parameters[1] + " is not a valid channel mode."); return CMD_FAILURE; } if (chan->GetPrefixValue(user) < mh->GetLevelRequired()) { user->WriteNotice("You do not have access to unset " + ConvToStr(modeletter) + " on " + chan->name + "."); return CMD_FAILURE; } unsigned int prefixrank; char prefixchar; std::string pattern = parameters.size() > 2 ? parameters[2] : "*"; ListModeBase* lm; ListModeBase::ModeList* ml; irc::modestacker modestack(false); if (!mh->IsListMode()) { if (chan->IsModeSet(mh)) modestack.Push(modeletter); } else if (((prefixrank = mh->GetPrefixRank()) && (prefixchar = mh->GetPrefix()))) { // As user prefix modes don't have a GetList() method, let's iterate through the channel's users. for (UserMembIter it = chan->userlist.begin(); it != chan->userlist.end(); ++it) { if (!InspIRCd::Match(it->first->nick, pattern)) continue; if (((strchr(chan->GetAllPrefixChars(user), prefixchar)) != NULL) && !(it->first == user && prefixrank > VOICE_VALUE)) modestack.Push(modeletter, it->first->nick); } } else if (((lm = dynamic_cast<ListModeBase*>(mh)) != NULL) && ((ml = lm->GetList(chan)) != NULL)) { for (ListModeBase::ModeList::iterator it = ml->begin(); it != ml->end(); ++it) { if (!InspIRCd::Match(it->mask, pattern)) continue; modestack.Push(modeletter, it->mask); } } else { user->WriteNotice("Could not remove channel mode " + ConvToStr(modeletter)); return CMD_FAILURE; } parameterlist stackresult; stackresult.push_back(chan->name); while (modestack.GetStackedLine(stackresult)) { ServerInstance->Modes->Process(stackresult, user); stackresult.erase(stackresult.begin() + 1, stackresult.end()); } return CMD_SUCCESS; }