virtual void OnBuildExemptList(MessageType message_type, Channel* chan, User* sender, char status, CUList &exempt_list, const std::string &text) { int public_silence = (message_type == MSG_PRIVMSG ? SILENCE_CHANNEL : SILENCE_CNOTICE); CUList *ulist; switch (status) { case '@': ulist = chan->GetOppedUsers(); break; case '%': ulist = chan->GetHalfoppedUsers(); break; case '+': ulist = chan->GetVoicedUsers(); break; default: ulist = chan->GetUsers(); break; } for (CUList::iterator i = ulist->begin(); i != ulist->end(); i++) { if (IS_LOCAL(i->first)) { if (MatchPattern(i->first, sender, public_silence) == 1) { exempt_list[i->first] = i->first->nick; } } } }
void UserManager::RemoveCloneCounts(User *user) { if (IS_LOCAL(user)) { clonemap::iterator x = local_clones.find(user->GetCIDRMask()); if (x != local_clones.end()) { x->second--; if (!x->second) { local_clones.erase(x); } } } clonemap::iterator y = global_clones.find(user->GetCIDRMask()); if (y != global_clones.end()) { y->second--; if (!y->second) { global_clones.erase(y); } } }
static bool checkHoplimit(MacInfo_t *info) { if (IS_LOCAL(info)) return true; // only for forwarding if (!info->hoplimit) return true; // hoplimit is optional if (--info->hoplimit) return true; // shold be larger than zero after decrement return false; }
void ModuleSpanningTree::OnUserJoin(userrec* user, chanrec* channel, bool &silent) { // Only do this for local users if (IS_LOCAL(user)) { if (channel->GetUserCounter() == 1) { std::deque<std::string> params; // set up their permissions and the channel TS with FJOIN. // All users are FJOINed now, because a module may specify // new joining permissions for the user. params.push_back(channel->name); params.push_back(ConvToStr(channel->age)); params.push_back(std::string(channel->GetAllPrefixChars(user))+","+std::string(user->nick)); Utils->DoOneToMany(ServerInstance->Config->ServerName,"FJOIN",params); /* First user in, sync the modes for the channel */ params.pop_back(); params.push_back(channel->ChanModes(true)); Utils->DoOneToMany(ServerInstance->Config->ServerName,"FMODE",params); } else { std::deque<std::string> params; params.push_back(channel->name); params.push_back(ConvToStr(channel->age)); Utils->DoOneToMany(user->nick,"JOIN",params); } } }
/** Because Andy insists that services-compatible servers must * implement SVSNICK and SVSJOIN, that's exactly what we do :p */ bool TreeSocket::ForceNick(const std::string &prefix, std::deque<std::string> ¶ms) { if (params.size() < 3) return true; User* u = this->ServerInstance->FindNick(params[0]); if (u) { Utils->DoOneToAllButSender(prefix,"SVSNICK",params,prefix); if (IS_LOCAL(u)) { std::deque<std::string> par; par.push_back(params[1]); if (!u->ForceNickChange(params[1].c_str())) { /* buh. UID them */ if (!u->ForceNickChange(u->uuid.c_str())) { this->ServerInstance->Users->QuitUser(u, "Nickname collision"); return true; } } u->age = atoi(params[2].c_str()); } } return true; }
int ModuleSpanningTree::HandleSquit(const char** parameters, int pcnt, userrec* user) { TreeServer* s = Utils->FindServerMask(parameters[0]); if (s) { if (s == Utils->TreeRoot) { user->WriteServ("NOTICE %s :*** SQUIT: Foolish mortal, you cannot make a server SQUIT itself! (%s matches local server name)",user->nick,parameters[0]); return 1; } TreeSocket* sock = s->GetSocket(); if (sock) { ServerInstance->SNO->WriteToSnoMask('l',"SQUIT: Server \002%s\002 removed from network by %s",parameters[0],user->nick); sock->Squit(s,std::string("Server quit by ") + user->GetFullRealHost()); ServerInstance->SE->DelFd(sock); sock->Close(); } else { if (IS_LOCAL(user)) user->WriteServ("NOTICE %s :*** WARNING: Using SQUIT to split remote servers is deprecated. Please use RSQUIT instead.",user->nick); } } else { user->WriteServ("NOTICE %s :*** SQUIT: The server \002%s\002 does not exist on the network.",user->nick,parameters[0]); } return 1; }
void Snomask::SendMessage(const std::string &message) { if (message != LastMessage) { this->Flush(); LastMessage = message; std::string desc = this->Description; int MOD_RESULT = 0; char mysnomask = MySnomask; ServerInstance->Logs->Log("snomask", DEFAULT, "%s: %s", desc.c_str(), message.c_str()); FOREACH_RESULT(I_OnSendSnotice, OnSendSnotice(mysnomask, desc, message)); LastBlocked = (MOD_RESULT == 1); // 1 blocks the message if (!LastBlocked) { /* Only opers can receive snotices, so we iterate the oper list */ std::list<User*>::iterator i = ServerInstance->Users->all_opers.begin(); while (i != ServerInstance->Users->all_opers.end()) { User* a = *i; if (IS_LOCAL(a) && a->IsModeSet('s') && a->IsNoticeMaskSet(mysnomask) && !a->quitting) { a->WriteServ("NOTICE %s :*** %s: %s", a->nick.c_str(), desc.c_str(), message.c_str()); } i++; } } } Count++; }
void ModuleSpanningTree::OnMode(userrec* user, void* dest, int target_type, const std::string &text) { if ((IS_LOCAL(user)) && (user->registered == REG_ALL)) { std::deque<std::string> params; std::string command; if (target_type == TYPE_USER) { userrec* u = (userrec*)dest; params.push_back(u->nick); params.push_back(text); command = "MODE"; } else { chanrec* c = (chanrec*)dest; params.push_back(c->name); params.push_back(ConvToStr(c->age)); params.push_back(text); command = "FMODE"; } Utils->DoOneToMany(user->nick, command, params); } }
CmdResult Handle (const std::vector<std::string>& parameters, User *user) { User* dest = ServerInstance->FindNick(parameters[0]); if ((dest) && (dest->registered == REG_ALL)) { if (dest->server->IsULine()) { user->WriteNumeric(ERR_NOPRIVILEGES, ":Cannot use an SA command on a u-lined client"); return CMD_FAILURE; } if (IS_LOCAL(user) && !ServerInstance->IsChannel(parameters[1])) { /* we didn't need to check this for each character ;) */ user->WriteNotice("*** Invalid characters in channel name or name too long"); return CMD_FAILURE; } /* For local users, we call Channel::JoinUser which may create a channel and set its TS. * For non-local users, we just return CMD_SUCCESS, knowing this will propagate it where it needs to be * and then that server will handle the command. */ LocalUser* localuser = IS_LOCAL(dest); if (localuser) { Channel* n = Channel::JoinUser(localuser, parameters[1], true); if (n && n->HasUser(dest)) { ServerInstance->SNO->WriteGlobalSno('a', user->nick+" used SAJOIN to make "+dest->nick+" join "+parameters[1]); return CMD_SUCCESS; } else { user->WriteNotice("*** Could not join "+dest->nick+" to "+parameters[1]); return CMD_FAILURE; } } else { return CMD_SUCCESS; } } else { user->WriteNotice("*** No such nickname "+parameters[0]); return CMD_FAILURE; } }
void ModuleSpanningTree::OnUserNotice(userrec* user, void* dest, int target_type, const std::string &text, char status, const CUList &exempt_list) { if (target_type == TYPE_USER) { userrec* d = (userrec*)dest; if ((d->GetFd() < 0) && (IS_LOCAL(user))) { std::deque<std::string> params; params.clear(); params.push_back(d->nick); params.push_back(":"+text); Utils->DoOneToOne(user->nick,"NOTICE",params,d->server); } } else if (target_type == TYPE_CHANNEL) { if (IS_LOCAL(user)) { chanrec *c = (chanrec*)dest; if (c) { std::string cname = c->name; if (status) cname = status + cname; TreeServerList list; Utils->GetListOfServersForChannel(c,list,status,exempt_list); for (TreeServerList::iterator i = list.begin(); i != list.end(); i++) { TreeSocket* Sock = i->second->GetSocket(); if (Sock) Sock->WriteLine(":"+std::string(user->nick)+" NOTICE "+cname+" :"+text); } } } } else if (target_type == TYPE_SERVER) { if (IS_LOCAL(user)) { char* target = (char*)dest; std::deque<std::string> par; par.push_back(target); par.push_back(":"+text); Utils->DoOneToMany(user->nick,"NOTICE",par); } } }
ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding) { if (adding) { if (IS_LOCAL(source)) { if (!ServerInstance->IsChannel(parameter)) { source->WriteNumeric(ERR_NOSUCHCHANNEL, "%s :Invalid channel name", parameter.c_str()); return MODEACTION_DENY; } } if (IS_LOCAL(source) && !source->IsOper()) { Channel* c = ServerInstance->FindChan(parameter); if (!c) { source->WriteNumeric(690, ":Target channel %s must exist to be set as a redirect.",parameter.c_str()); return MODEACTION_DENY; } else if (c->GetPrefixValue(source) < OP_VALUE) { source->WriteNumeric(690, ":You must be opped on %s to set it as a redirect.",parameter.c_str()); return MODEACTION_DENY; } } if (channel->GetModeParameter(this) == parameter) return MODEACTION_DENY; /* * We used to do some checking for circular +L here, but there is no real need for this any more especially as we * now catch +L looping in PreJoin. Remove it, since O(n) logic makes me sad, and we catch it anyway. :) -- w00t */ return MODEACTION_ALLOW; } else { if (channel->IsModeSet(this)) { return MODEACTION_ALLOW; } } return MODEACTION_DENY; }
RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) { if (IS_LOCAL(user)) // This is handled by the OnUserMessage hook to split the LoopCall pieces return ROUTE_LOCALONLY; else return ROUTE_MESSAGE(parameters[0]); }
virtual void OnUserPart(Membership* memb, std::string &partmessage, CUList& excepts) { if (!IS_LOCAL(memb->user)) return; if (memb->chan->GetExtBanStatus(memb->user, 'p') == MOD_RES_DENY) partmessage.clear(); }
// :kenny.chatspike.net 320 Om Epy|AFK :is a Secure Connection virtual void OnWhois(userrec* source, userrec* dest) { // Bugfix, only send this numeric for *our* SSL users if(dest->GetExt("ssl", dummy) || (IS_LOCAL(dest) && isin(dest->GetPort(), listenports))) { source->WriteServ("320 %s %s :is using a secure connection", source->nick, dest->nick); } }
void ModuleSpanningTree::OnPostTopicChange(User* user, Channel* chan, const std::string &topic) { // Drop remote events on the floor. if (!IS_LOCAL(user)) return; CommandFTopic::Builder(user, chan).Broadcast(); }
bool User::ChangeName(const std::string& gecos) { if (!this->fullname.compare(gecos)) return true; if (IS_LOCAL(this)) { ModResult MOD_RESULT; FIRST_MOD_RESULT(OnChangeLocalUserGECOS, MOD_RESULT, (IS_LOCAL(this),gecos)); if (MOD_RESULT == MOD_RES_DENY) return false; FOREACH_MOD(OnChangeName, (this,gecos)); } this->fullname.assign(gecos, 0, ServerInstance->Config->Limits.MaxGecos); return true; }
ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding) { if (adding) { std::string::size_type colon = parameter.find(':'); if (colon == std::string::npos) return MODEACTION_DENY; std::string duration = parameter.substr(colon+1); if ((IS_LOCAL(source)) && ((duration.length() > 10) || (!IsValidDuration(duration)))) return MODEACTION_DENY; unsigned int len = ConvToInt(parameter.substr(0, colon)); int time = InspIRCd::Duration(duration); if (len == 0 || time < 0) return MODEACTION_DENY; if (len > maxlines && IS_LOCAL(source)) return MODEACTION_DENY; if (len > maxlines) len = maxlines; if (parameter == channel->GetModeParameter(this)) return MODEACTION_DENY; HistoryList* history = ext.get(channel); if (history) { // Shrink the list if the new line number limit is lower than the old one if (len < history->lines.size()) history->lines.erase(history->lines.begin(), history->lines.begin() + (history->lines.size() - len)); history->maxlen = len; history->maxtime = time; } else { ext.set(channel, new HistoryList(len, time)); } } else { if (!channel->IsModeSet(this)) return MODEACTION_DENY; ext.unset(channel); } return MODEACTION_ALLOW; }
/** Handle /MODULES */ CmdResult CommandModules::Handle(User* user, const Params& parameters) { // Don't ask remote servers about their modules unless the local user asking is an oper // 2.0 asks anyway, so let's handle that the same way bool for_us = (parameters.empty() || irc::equals(parameters[0], ServerInstance->Config->ServerName)); if ((!for_us) || (!IS_LOCAL(user))) { if (!user->IsOper()) { user->WriteNotice("*** You cannot check what modules other servers have loaded."); return CMD_FAILURE; } // From an oper and not for us, forward if (!for_us) return CMD_SUCCESS; } const ModuleManager::ModuleMap& mods = ServerInstance->Modules.GetModules(); for (ModuleManager::ModuleMap::const_iterator i = mods.begin(); i != mods.end(); ++i) { Module* m = i->second; Version V = m->GetVersion(); if (IS_LOCAL(user) && user->HasPrivPermission("servers/auspex")) { std::string flags("VCO"); size_t pos = 0; for (int mult = 2; mult <= VF_OPTCOMMON; mult *= 2, ++pos) if (!(V.Flags & mult)) flags[pos] = '-'; std::string srcrev = m->ModuleDLLManager->GetVersion(); user->WriteRemoteNumeric(RPL_MODLIST, m->ModuleSourceFile, srcrev.empty() ? "*" : srcrev, flags, V.description); } else { user->WriteRemoteNumeric(RPL_MODLIST, m->ModuleSourceFile, '*', '*', V.description); } } user->WriteRemoteNumeric(RPL_ENDOFMODLIST, "End of MODULES list"); return CMD_SUCCESS; }
bool Matches(User *u) { LocalUser* lu = IS_LOCAL(u); if (lu && lu->exempt) return false; std::string compare = u->nick + "!" + u->ident + "@" + u->host + " " + u->fullname; return regex->Matches(compare); }
virtual void OnPostOper(userrec* user, const std::string &opertype) { if (!IS_LOCAL(user)) return; for(std::vector<std::string>::iterator it = operChans.begin(); it != operChans.end(); it++) if (ServerInstance->IsChannel(it->c_str())) chanrec::JoinUser(ServerInstance, user, it->c_str(), false, "", ServerInstance->Time(true)); }
void ModuleSpanningTree::OnOper(User* user, const std::string &opertype) { if (user->registered != REG_ALL || !IS_LOCAL(user)) return; // Note: The protocol does not allow direct umode +o; // sending OPERTYPE infers +o modechange locally. CommandOpertype::Builder(user).Broadcast(); }
void ModuleSpanningTree::OnCancelAway(userrec* user) { if (IS_LOCAL(user)) { std::deque<std::string> params; params.clear(); Utils->DoOneToMany(user->nick,"AWAY",params); } }
CmdResult Handle (const char** parameters, int pcnt, userrec *user) { userrec* dest = ServerInstance->FindNick(parameters[0]); if (dest) { if (ServerInstance->ULine(dest->server)) { user->WriteServ("990 %s :Cannot use an SA command on a u-lined client",user->nick); return CMD_FAILURE; } if (!ServerInstance->IsChannel(parameters[1])) { /* we didn't need to check this for each character ;) */ user->WriteServ("NOTICE "+std::string(user->nick)+" :*** Invalid characters in channel name"); return CMD_FAILURE; } /* For local users, we send the JoinUser which may create a channel and set its TS. * For non-local users, we just return CMD_SUCCESS, knowing this will propogate it where it needs to be * and then that server will generate the users JOIN or FJOIN instead. */ if (IS_LOCAL(dest)) { chanrec::JoinUser(ServerInstance, dest, parameters[1], true, "", ServerInstance->Time(true)); /* Fix for dotslasher and w00t - if the join didnt succeed, return CMD_FAILURE so that it doesnt propogate */ chanrec* n = ServerInstance->FindChan(parameters[1]); if (n) { if (n->HasUser(dest)) { ServerInstance->WriteOpers("*** "+std::string(user->nick)+" used SAJOIN to make "+std::string(dest->nick)+" join "+parameters[1]); return CMD_SUCCESS; } else { user->WriteServ("NOTICE "+std::string(user->nick)+" :*** Could not join "+std::string(dest->nick)+" to "+parameters[1]+" (User is probably banned, or blocking modes)"); return CMD_FAILURE; } } else { user->WriteServ("NOTICE "+std::string(user->nick)+" :*** Could not join "+std::string(dest->nick)+" to "+parameters[1]); return CMD_FAILURE; } } else { ServerInstance->WriteOpers("*** "+std::string(user->nick)+" sent remote SAJOIN to make "+std::string(dest->nick)+" join "+parameters[1]); return CMD_SUCCESS; } } else { user->WriteServ("NOTICE "+std::string(user->nick)+" :*** No such nickname "+parameters[0]); return CMD_FAILURE; } }
void ModuleSpanningTree::OnWallops(User* user, const std::string &text) { if (IS_LOCAL(user)) { std::deque<std::string> params; params.push_back(":"+text); Utils->DoOneToMany(user->uuid,"WALLOPS",params); } }
void OnChangeIdent(User* user, const std::string& ident) { if (IS_LOCAL(user) && ext.get(user) == NULL) { ServerInstance->Logs->Log("m_identmeta", DEBUG, "Setting ident metadata of %s to %s.", user->nick.c_str(), ident.c_str()); ext.set(user, ident); } }
void cmd_kill::Handle (const char** parameters, int pcnt, userrec *user) { userrec *u = ServerInstance->FindNick(parameters[0]); char killreason[MAXBUF]; int MOD_RESULT = 0; ServerInstance->Log(DEBUG,"kill: %s %s", parameters[0], parameters[1]); if (u) { ServerInstance->Log(DEBUG, "into kill mechanism"); FOREACH_RESULT(I_OnKill, OnKill(user, u, parameters[1])); if (MOD_RESULT) { ServerInstance->Log(DEBUG, "A module prevented the kill with result %d", MOD_RESULT); return; } if (!IS_LOCAL(u)) { // remote kill ServerInstance->WriteOpers("*** Remote kill by %s: %s!%s@%s (%s)", user->nick, u->nick, u->ident, u->host, parameters[1]); snprintf(killreason, MAXQUIT,"[%s] Killed (%s (%s))", ServerInstance->Config->ServerName, user->nick, parameters[1]); u->WriteCommonExcept("QUIT :%s", killreason); FOREACH_MOD(I_OnRemoteKill, OnRemoteKill(user, u, killreason)); user_hash::iterator iter = ServerInstance->clientlist.find(u->nick); if (iter != ServerInstance->clientlist.end()) { ServerInstance->Log(DEBUG,"deleting user hash value %d", iter->second); ServerInstance->clientlist.erase(iter); } if (u->registered == REG_ALL) { u->PurgeEmptyChannels(); } DELETE(u); } else { // local kill ServerInstance->Log(DEFAULT,"LOCAL KILL: %s :%s!%s!%s (%s)", u->nick, ServerInstance->Config->ServerName, user->dhost, user->nick, parameters[1]); user->WriteTo(u, "KILL %s :%s!%s!%s (%s)", u->nick, ServerInstance->Config->ServerName, user->dhost, user->nick, parameters[1]); ServerInstance->WriteOpers("*** Local Kill by %s: %s!%s@%s (%s)", user->nick, u->nick, u->ident, u->host, parameters[1]); snprintf(killreason,MAXQUIT,"Killed (%s (%s))", user->nick, parameters[1]); userrec::QuitUser(ServerInstance, u, killreason); } } else { user->WriteServ( "401 %s %s :No such nick/channel", user->nick, parameters[0]); } }
virtual void OnPostConnect(User* user) { if (!IS_LOCAL(user)) return; for(std::vector<std::string>::iterator it = Joinchans.begin(); it != Joinchans.end(); it++) if (ServerInstance->IsChannel(it->c_str(), ServerInstance->Config->Limits.ChanMax)) Channel::JoinUser(ServerInstance, user, it->c_str(), false, "", false, ServerInstance->Time()); }
static void BuildExcept(Membership* memb, CUList& excepts) { const UserMembList* users = memb->chan->GetUsers(); for(UserMembCIter i = users->begin(); i != users->end(); i++) { if (IS_LOCAL(i->first) && i->first->HasPrivPermission("invisible/see")) excepts.insert(i->first); } }
void ModuleSpanningTree::OnSetAway(userrec* user) { if (IS_LOCAL(user)) { std::deque<std::string> params; params.push_back(":"+std::string(user->awaymsg)); Utils->DoOneToMany(user->nick,"AWAY",params); } }
// note: the protocol does not allow direct umode +o except // via NICK with 8 params. sending OPERTYPE infers +o modechange // locally. void ModuleSpanningTree::OnOper(User* user, const std::string &opertype) { if (IS_LOCAL(user)) { std::deque<std::string> params; params.push_back(opertype); Utils->DoOneToMany(user->uuid,"OPERTYPE",params); } }