CYCLE KNOCK MODE DEVOICE TOPIC
KICK FPART REMOVE TBAN INVITE
UNINVITE AWAY DCCALLOW SILENCE ACCEPT
- MKPASSWD VHOST TITLE
+ MKPASSWD VHOST TITLE SETNAME
WHOIS WHOWAS ISON USERHOST WATCH
-LIST NAMES WHO MOTD RULES
+LIST NAMES WHO MOTD
ADMIN MAP LINKS LUSERS TIME
STATS VERSION INFO MODULES COMMANDS
SSLINFO
# allowmask: Range of IP addresses to allow for this link.
# Can be a CIDR (see example).
- allowmask="69.58.44.0/24 127.0.0.0/8"
- allowmask="203.0.113.0/24"
++ allowmask="203.0.113.0/24 127.0.0.0/8 2001:db8::/32"
# timeout: If defined, this option defines how long the server
# will wait to consider the connect attempt failed and try the
use strict;
use warnings FATAL => qw(all);
-use make::configure;
+use make::utilities;
- if (!module_installed("LWP::Simple"))
- {
- die "Your system is missing the LWP::Simple Perl module!";
- }
+ BEGIN {
+ unless (module_installed("LWP::Simple")) {
+ die "Your system is missing the LWP::Simple Perl module!";
+ }
+ unless (module_installed("Crypt::SSLeay") || module_installed("IO::Socket::SSL")) {
+ die "Your system is missing the Crypt::SSLeay or IO::Socket::SSL Perl modules!";
+ }
+
- if (!module_installed("Crypt::SSLeay") && !module_installed("IO::Socket::SSL"))
- {
- die "Your system is missing the Crypt::SSLeay or IO::Socket::SSL Perl modules!";
}
+use File::Basename;
use LWP::Simple;
-our @modlist;
-
my %installed;
# $installed{name} = $version
*/
void Channel::UserList(User *user)
{
- if (this->IsModeSet(secretmode) && !this->HasUser(user) && !user->HasPrivPermission("channels/auspex"))
- char list[MAXBUF];
- size_t dlen, curlen;
-
- if (!IS_LOCAL(user))
- return;
-
+ bool has_privs = user->HasPrivPermission("channels/auspex");
-
- if (this->IsModeSet('s') && !this->HasUser(user) && !has_privs)
++ if (this->IsModeSet(secretmode) && !this->HasUser(user) && !has_privs)
{
- user->WriteNumeric(ERR_NOSUCHNICK, "%s %s :No such nick/channel",user->nick.c_str(), this->name.c_str());
+ user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", this->name.c_str());
return;
}
{
if (i->first->quitting)
continue;
- if ((!has_user) && (i->first->IsModeSet(invisiblemode)))
- if ((!has_user) && (i->first->IsModeSet('i')) && (!has_privs))
++ if ((!has_user) && (i->first->IsModeSet(invisiblemode)) && (!has_privs))
{
/*
* user is +i, and source not on the channel, does not show
*/
CmdResult CommandModules::Handle (const std::vector<std::string>& parameters, User *user)
{
- if (parameters.size() >= 1 && parameters[0] != ServerInstance->Config->ServerName)
- return CMD_SUCCESS;
+ // 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() || 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;
+ }
- std::vector<std::string> module_names = ServerInstance->Modules->GetAllModuleNames(0);
+ const ModuleManager::ModuleMap& mods = ServerInstance->Modules->GetModules();
- for (unsigned int i = 0; i < module_names.size(); i++)
+ for (ModuleManager::ModuleMap::const_iterator i = mods.begin(); i != mods.end(); ++i)
{
- Module* m = ServerInstance->Modules->Find(module_names[i]);
+ Module* m = i->second;
Version V = m->GetVersion();
- if (user->HasPrivPermission("servers/auspex"))
+ if (IS_LOCAL(user) && user->HasPrivPermission("servers/auspex"))
{
std::string flags("SvcC");
int pos = 0;
* @param user The user issuing the command
* @return A value from CmdResult to indicate command success or failure.
*/
- CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+ CmdResult HandleLocal(const std::vector<std::string>& parameters, LocalUser* user);
+ CmdResult HandleRemote(const std::vector<std::string>& parameters, RemoteUser* target);
};
- std::string::size_type start, pos, length;
+std::string CommandWhois::ChannelList(User* source, User* dest, bool spy)
+{
+ std::string list;
+
+ for (UCListIter i = dest->chans.begin(); i != dest->chans.end(); i++)
+ {
+ Channel* c = *i;
+ /* If the target is the sender, neither +p nor +s is set, or
+ * the channel contains the user, it is not a spy channel
+ */
+ if (spy != (source == dest || !(c->IsModeSet(privatemode) || c->IsModeSet(secretmode)) || c->HasUser(source)))
+ list.append(c->GetPrefixChar(dest)).append(c->name).append(" ");
+ }
+
+ return list;
+}
+
+void CommandWhois::SplitChanList(User* source, User* dest, const std::string& cl)
+{
+ std::string line;
+ std::ostringstream prefix;
- length = (pos == std::string::npos) ? cl.length() : pos;
-
- if (line.length() + namelen + length - start > 510)
++ std::string::size_type start, pos;
+
+ prefix << dest->nick << " :";
+ line = prefix.str();
+ int namelen = ServerInstance->Config->ServerName.length() + 6;
+
+ for (start = 0; (pos = cl.find(' ', start)) != std::string::npos; start = pos+1)
+ {
- if(pos == std::string::npos)
- {
- line.append(cl.substr(start, length - start));
- break;
- }
- else
- {
- line.append(cl.substr(start, length - start + 1));
- }
++ if (line.length() + namelen + pos - start > 510)
+ {
+ ServerInstance->SendWhoisLine(source, dest, 319, line);
+ line = prefix.str();
+ }
+
++ line.append(cl.substr(start, pos - start + 1));
+ }
+
+ if (line.length() != prefix.str().length())
+ {
+ ServerInstance->SendWhoisLine(source, dest, 319, line);
+ }
+}
+
+void CommandWhois::DoWhois(User* user, User* dest, unsigned long signon, unsigned long idle)
+{
+ ServerInstance->SendWhoisLine(user, dest, 311, "%s %s %s * :%s", dest->nick.c_str(), dest->ident.c_str(), dest->dhost.c_str(), dest->fullname.c_str());
+ if (user == dest || user->HasPrivPermission("users/auspex"))
+ {
+ ServerInstance->SendWhoisLine(user, dest, 378, "%s :is connecting from %s@%s %s", dest->nick.c_str(), dest->ident.c_str(), dest->host.c_str(), dest->GetIPString().c_str());
+ }
+
+ std::string cl = ChannelList(user, dest, false);
+ const ServerConfig::OperSpyWhoisState state = user->HasPrivPermission("users/auspex") ? ServerInstance->Config->OperSpyWhois : ServerConfig::SPYWHOIS_NONE;
+
+ if (state == ServerConfig::SPYWHOIS_SINGLEMSG)
+ cl.append(ChannelList(user, dest, true));
+
+ SplitChanList(user, dest, cl);
+
+ if (state == ServerConfig::SPYWHOIS_SPLITMSG)
+ {
+ std::string scl = ChannelList(user, dest, true);
+ if (scl.length())
+ {
+ ServerInstance->SendWhoisLine(user, dest, 336, "%s :is on private/secret channels:", dest->nick.c_str());
+ SplitChanList(user, dest, scl);
+ }
+ }
+ if (user != dest && !ServerInstance->Config->HideWhoisServer.empty() && !user->HasPrivPermission("servers/auspex"))
+ {
+ ServerInstance->SendWhoisLine(user, dest, 312, "%s %s :%s", dest->nick.c_str(), ServerInstance->Config->HideWhoisServer.c_str(), ServerInstance->Config->Network.c_str());
+ }
+ else
+ {
+ ServerInstance->SendWhoisLine(user, dest, 312, "%s %s :%s", dest->nick.c_str(), dest->server->GetName().c_str(), dest->server->GetDesc().c_str());
+ }
+
+ if (dest->IsAway())
+ {
+ ServerInstance->SendWhoisLine(user, dest, 301, "%s :%s", dest->nick.c_str(), dest->awaymsg.c_str());
+ }
+
+ if (dest->IsOper())
+ {
+ if (ServerInstance->Config->GenericOper)
+ ServerInstance->SendWhoisLine(user, dest, 313, "%s :is an IRC operator", dest->nick.c_str());
+ else
+ ServerInstance->SendWhoisLine(user, dest, 313, "%s :is %s %s on %s", dest->nick.c_str(), (strchr("AEIOUaeiou",dest->oper->name[0]) ? "an" : "a"),dest->oper->name.c_str(), ServerInstance->Config->Network.c_str());
+ }
+
+ if (user == dest || user->HasPrivPermission("users/auspex"))
+ {
+ if (dest->IsModeSet(snomaskmode))
+ {
+ ServerInstance->SendWhoisLine(user, dest, 379, "%s :is using modes +%s %s", dest->nick.c_str(), dest->FormatModes(), snomaskmode->GetUserParameter(dest).c_str());
+ }
+ else
+ {
+ ServerInstance->SendWhoisLine(user, dest, 379, "%s :is using modes +%s", dest->nick.c_str(), dest->FormatModes());
+ }
+ }
+
+ FOREACH_MOD(OnWhois, (user,dest));
+
+ /*
+ * We only send these if we've been provided them. That is, if hidewhois is turned off, and user is local, or
+ * if remote whois is queried, too. This is to keep the user hidden, and also since you can't reliably tell remote time. -- w00t
+ */
+ if ((idle) || (signon))
+ {
+ ServerInstance->SendWhoisLine(user, dest, 317, "%s %lu %lu :seconds idle, signon time", dest->nick.c_str(), idle, signon);
+ }
+
+ ServerInstance->SendWhoisLine(user, dest, 318, "%s :End of /WHOIS list.", dest->nick.c_str());
+}
-CmdResult CommandWhois::Handle (const std::vector<std::string>& parameters, User *user)
+CmdResult CommandWhois::HandleRemote(const std::vector<std::string>& parameters, RemoteUser* target)
+{
+ if (parameters.size() < 2)
+ return CMD_FAILURE;
+
+ User* user = ServerInstance->FindUUID(parameters[0]);
+ if (!user)
+ return CMD_FAILURE;
+
+ unsigned long idle = ConvToInt(parameters.back());
+ DoWhois(user, target, target->signon, idle);
+
+ return CMD_SUCCESS;
+}
+
+CmdResult CommandWhois::HandleLocal(const std::vector<std::string>& parameters, LocalUser* user)
{
User *dest;
int userindex = 0;
std::cout << "InspIRCd Process ID: " << con_green << GetCurrentProcessId() << con_reset << std::endl;
return true;
#else
- signal(SIGTERM, InspIRCd::QuickExit);
+ // Do not use QuickExit here: It will exit with status SIGTERM which would break e.g. daemon scripts
+ signal(SIGTERM, VoidSignalHandler);
- int childpid;
- if ((childpid = fork ()) < 0)
+ int childpid = fork();
+ if (childpid < 0)
return false;
else if (childpid > 0)
{
if (!g)
{
- this->Logs->Log("STARTUP", LOG_DEFAULT, "getgrnam() failed (bad user?): %s", strerror(errno));
- this->Logs->Log("SETGUID", DEFAULT, "getgrnam(%s) failed (wrong group?): %s", SetGroup.c_str(), strerror(errno));
++ this->Logs->Log("STARTUP", LOG_DEFAULT, "getgrnam(%s) failed (wrong group?): %s", SetGroup.c_str(), strerror(errno));
this->QuickExit(0);
}
if (ret == -1)
{
- this->Logs->Log("STARTUP", LOG_DEFAULT, "setgid() failed (bad user?): %s", strerror(errno));
- this->Logs->Log("SETGUID", DEFAULT, "setgid() failed (wrong group?): %s", strerror(errno));
++ this->Logs->Log("STARTUP", LOG_DEFAULT, "setgid() failed (wrong group?): %s", strerror(errno));
this->QuickExit(0);
}
}
if (!u)
{
- this->Logs->Log("STARTUP", LOG_DEFAULT, "getpwnam() failed (bad user?): %s", strerror(errno));
- this->Logs->Log("SETGUID", DEFAULT, "getpwnam(%s) failed (wrong user?): %s", SetUser.c_str(), strerror(errno));
++ this->Logs->Log("STARTUP", LOG_DEFAULT, "getpwnam(%s) failed (wrong user?): %s", SetUser.c_str(), strerror(errno));
this->QuickExit(0);
}
if (ret == -1)
{
- this->Logs->Log("STARTUP", LOG_DEFAULT, "setuid() failed (bad user?): %s", strerror(errno));
- this->Logs->Log("SETGUID", DEFAULT, "setuid() failed (wrong user?): %s", strerror(errno));
++ this->Logs->Log("STARTUP", LOG_DEFAULT, "setuid() failed (wrong user?): %s", strerror(errno));
this->QuickExit(0);
}
}
}
}
- User* target = ServerInstance->FindNick(parameter);
+PrefixMode::PrefixMode(Module* Creator, const std::string& Name, char ModeLetter)
+ : ModeHandler(Creator, Name, ModeLetter, PARAM_ALWAYS, MODETYPE_CHANNEL, MC_PREFIX)
+ , prefix(0), prefixrank(0)
+{
+ list = true;
+ m_paramtype = TR_NICK;
+}
+
+ModeAction PrefixMode::OnModeChange(User* source, User*, Channel* chan, std::string& parameter, bool adding)
+{
++ User* target;
++ if (IS_LOCAL(source))
++ target = ServerInstance->FindNickOnly(parameter);
++ else
++ target = ServerInstance->FindNick(parameter);
++
+ if (!target)
+ {
+ source->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", parameter.c_str());
+ return MODEACTION_DENY;
+ }
+
+ Membership* memb = chan->GetUser(target);
+ if (!memb)
+ return MODEACTION_DENY;
+
+ parameter = target->nick;
+ return (memb->SetPrefix(this, adding) ? MODEACTION_ALLOW : MODEACTION_DENY);
+}
+
ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, bool adding, const unsigned char modechar,
std::string ¶meter, bool SkipACL)
{
return MODEACTION_ALLOW;
}
-void ModeParser::Process(const std::vector<std::string>& parameters, User *user, bool merge)
+void ModeParser::Process(const std::vector<std::string>& parameters, User* user, ModeProcessFlag flags)
{
- std::string target = parameters[0];
+ const std::string& target = parameters[0];
Channel* targetchannel = ServerInstance->FindChan(target);
- User* targetuser = ServerInstance->FindNick(target);
+ User* targetuser = NULL;
+ if (!targetchannel)
+ {
+ if (IS_LOCAL(user))
+ targetuser = ServerInstance->FindNickOnly(target);
+ else
+ targetuser = ServerInstance->FindNick(target);
+ }
ModeType type = targetchannel ? MODETYPE_CHANNEL : MODETYPE_USER;
LastParse.clear();
class CommandAccept : public Command
{
- static ACCEPTAction GetTargetAndAction(std::string& tok)
+ /** Pair: first is the target, second is true to add, false to remove
+ */
+ typedef std::pair<User*, bool> ACCEPTAction;
+
- User* target = ServerInstance->FindNick(tok);
++ static ACCEPTAction GetTargetAndAction(std::string& tok, User* cmdfrom = NULL)
+ {
+ bool remove = (tok[0] == '-');
+ if ((remove) || (tok[0] == '+'))
+ tok.erase(tok.begin());
+
++ User* target;
++ if (!cmdfrom || !IS_LOCAL(cmdfrom))
++ target = ServerInstance->FindNick(tok);
++ else
++ target = ServerInstance->FindNickOnly(tok);
++
+ if ((!target) || (target->registered != REG_ALL) || (target->quitting) || (IS_SERVER(target)))
+ target = NULL;
+
+ return std::make_pair(target, !remove);
+ }
+
public:
CallerIDExtInfo extInfo;
unsigned int maxaccepts;
/* Even if callerid mode is not set, we let them manage their ACCEPT list so that if they go +g they can
* have a list already setup. */
- const std::string& tok = parameters[0];
-
- if (tok == "*")
+ if (parameters[0] == "*")
{
- if (IS_LOCAL(user))
- ListAccept(user);
+ ListAccept(user);
return CMD_SUCCESS;
}
- else if (tok[0] == '-')
- {
- User* whotoremove;
- if (IS_LOCAL(user))
- whotoremove = ServerInstance->FindNickOnly(tok.substr(1));
- else
- whotoremove = ServerInstance->FindNick(tok.substr(1));
- if (whotoremove)
- return (RemoveAccept(user, whotoremove) ? CMD_SUCCESS : CMD_FAILURE);
- else
- return CMD_FAILURE;
- }
- else
+ std::string tok = parameters[0];
- ACCEPTAction action = GetTargetAndAction(tok);
++ ACCEPTAction action = GetTargetAndAction(tok, user);
+ if (!action.first)
{
- const std::string target = (tok[0] == '+' ? tok.substr(1) : tok);
- User* whotoadd;
- if (IS_LOCAL(user))
- whotoadd = ServerInstance->FindNickOnly(target);
- else
- whotoadd = ServerInstance->FindNick(target);
-
- if ((whotoadd) && (whotoadd->registered == REG_ALL) && (!whotoadd->quitting) && (!IS_SERVER(whotoadd)))
- return (AddAccept(user, whotoadd) ? CMD_SUCCESS : CMD_FAILURE);
- else
- {
- user->WriteNumeric(401, "%s %s :No such nick/channel", user->nick.c_str(), tok.c_str());
- return CMD_FAILURE;
- }
+ user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", tok.c_str());
+ return CMD_FAILURE;
}
+
+ if ((!IS_LOCAL(user)) && (!IS_LOCAL(action.first)))
+ // Neither source nor target is local, forward the command to the server of target
+ return CMD_SUCCESS;
+
+ // The second item in the pair is true if the first char is a '+' (or nothing), false if it's a '-'
+ if (action.second)
+ return (AddAccept(user, action.first) ? CMD_SUCCESS : CMD_FAILURE);
+ else
+ return (RemoveAccept(user, action.first) ? CMD_SUCCESS : CMD_FAILURE);
}
RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters)
{
- return ROUTE_BROADCAST;
+ // There is a list in parameters[0] in two cases:
+ // Either when the source is remote, this happens because 2.0 servers send comma seperated uuid lists,
+ // we don't split those but broadcast them, as before.
+ //
+ // Or if the source is local then LoopCall() runs OnPostCommand() after each entry in the list,
+ // meaning the linking module has sent an ACCEPT already for each entry in the list to the
+ // appropiate server and the ACCEPT with the list of nicks (this) doesn't need to be sent anywhere.
+ if ((!IS_LOCAL(user)) && (parameters[0].find(',') != std::string::npos))
+ return ROUTE_BROADCAST;
+
+ // Find the target
+ std::string targetstring = parameters[0];
- ACCEPTAction action = GetTargetAndAction(targetstring);
++ ACCEPTAction action = GetTargetAndAction(targetstring, user);
+ if (!action.first)
+ // Target is a "*" or source is local and the target is a list of nicks
+ return ROUTE_LOCALONLY;
+
+ // Route to the server of the target
+ return ROUTE_UNICAST(action.first->server);
}
void ListAccept(User* user)
void DisplayHelp(User* user)
{
- user->WriteNumeric(998, "%s :DCCALLOW [<+|->nick [time]] [list] [help]", user->nick.c_str());
- user->WriteNumeric(998, "%s :You may allow DCCs from specific users by specifying a", user->nick.c_str());
- user->WriteNumeric(998, "%s :DCC allow for the user you want to receive DCCs from.", user->nick.c_str());
- user->WriteNumeric(998, "%s :For example, to allow the user Brain to send you inspircd.exe", user->nick.c_str());
- user->WriteNumeric(998, "%s :you would type:", user->nick.c_str());
- user->WriteNumeric(998, "%s :/DCCALLOW +Brain", user->nick.c_str());
- user->WriteNumeric(998, "%s :Brain would then be able to send you files. They would have to", user->nick.c_str());
- user->WriteNumeric(998, "%s :resend the file again if the server gave them an error message", user->nick.c_str());
- user->WriteNumeric(998, "%s :before you added them to your DCCALLOW list.", user->nick.c_str());
- user->WriteNumeric(998, "%s :DCCALLOW entries will be temporary by default, if you want to add", user->nick.c_str());
- user->WriteNumeric(998, "%s :them to your DCCALLOW list until you leave IRC, type:", user->nick.c_str());
- user->WriteNumeric(998, "%s :/DCCALLOW +Brain 0", user->nick.c_str());
- user->WriteNumeric(998, "%s :To remove the user from your DCCALLOW list, type:", user->nick.c_str());
- user->WriteNumeric(998, "%s :/DCCALLOW -Brain", user->nick.c_str());
- user->WriteNumeric(998, "%s :To see the users in your DCCALLOW list, type:", user->nick.c_str());
- user->WriteNumeric(998, "%s :/DCCALLOW LIST", user->nick.c_str());
- user->WriteNumeric(998, "%s :NOTE: If the user leaves IRC or changes their nickname", user->nick.c_str());
- user->WriteNumeric(998, "%s : they will be removed from your DCCALLOW list.", user->nick.c_str());
- user->WriteNumeric(998, "%s : your DCCALLOW list will be deleted when you leave IRC.", user->nick.c_str());
- user->WriteNumeric(999, "%s :End of DCCALLOW HELP", user->nick.c_str());
+ user->WriteNumeric(998, ":DCCALLOW [<+|->nick [time]] [list] [help]");
+ user->WriteNumeric(998, ":You may allow DCCs from specific users by specifying a");
+ user->WriteNumeric(998, ":DCC allow for the user you want to receive DCCs from.");
+ user->WriteNumeric(998, ":For example, to allow the user Brain to send you inspircd.exe");
+ user->WriteNumeric(998, ":you would type:");
+ user->WriteNumeric(998, ":/DCCALLOW +Brain");
+ user->WriteNumeric(998, ":Brain would then be able to send you files. They would have to");
+ user->WriteNumeric(998, ":resend the file again if the server gave them an error message");
+ user->WriteNumeric(998, ":before you added them to your DCCALLOW list.");
+ user->WriteNumeric(998, ":DCCALLOW entries will be temporary by default, if you want to add");
+ user->WriteNumeric(998, ":them to your DCCALLOW list until you leave IRC, type:");
+ user->WriteNumeric(998, ":/DCCALLOW +Brain 0");
+ user->WriteNumeric(998, ":To remove the user from your DCCALLOW list, type:");
+ user->WriteNumeric(998, ":/DCCALLOW -Brain");
+ user->WriteNumeric(998, ":To see the users in your DCCALLOW list, type:");
+ user->WriteNumeric(998, ":/DCCALLOW LIST");
+ user->WriteNumeric(998, ":NOTE: If the user leaves IRC or changes their nickname");
+ user->WriteNumeric(998, ": they will be removed from your DCCALLOW list.");
+ user->WriteNumeric(998, ": your DCCALLOW list will be deleted when you leave IRC.");
+ user->WriteNumeric(999, ":End of DCCALLOW HELP");
+
+ LocalUser* localuser = IS_LOCAL(user);
+ if (localuser)
+ localuser->CommandFloodPenalty += 4000;
}
void DisplayDCCAllowList(User* user)
{
/* Check the user still exists */
LocalUser* them = (LocalUser*)ServerInstance->FindUUID(theiruid);
- if (them)
+ if (!them)
+ return;
+
+ const DNS::ResourceRecord &ans_record = r->answers[0];
+
+ int i = countExt.get(them);
+ if (i)
+ countExt.set(them, i - 1);
+
+ // Now we calculate the bitmask: 256*(256*(256*a+b)+c)+d
+
+ unsigned int bitmask = 0, record = 0;
+ bool match = false;
+ in_addr resultip;
+
+ inet_aton(ans_record.rdata.c_str(), &resultip);
+
+ switch (ConfEntry->type)
{
- int i = countExt.get(them);
- if (i)
- countExt.set(them, i - 1);
- // Now we calculate the bitmask: 256*(256*(256*a+b)+c)+d
- if(result.length())
+ case DNSBLConfEntry::A_BITMASK:
+ bitmask = resultip.s_addr >> 24; /* Last octet (network byte order) */
+ bitmask &= ConfEntry->bitmask;
+ match = (bitmask != 0);
+ break;
+ case DNSBLConfEntry::A_RECORD:
+ record = resultip.s_addr >> 24; /* Last octet */
+ match = (ConfEntry->records[record] == 1);
+ break;
+ }
+
+ if (match)
+ {
+ std::string reason = ConfEntry->reason;
+ std::string::size_type x = reason.find("%ip%");
+ while (x != std::string::npos)
{
- unsigned int bitmask = 0, record = 0;
- bool match = false;
- in_addr resultip;
+ reason.erase(x, 4);
+ reason.insert(x, them->GetIPString());
+ x = reason.find("%ip%");
+ }
- inet_aton(result.c_str(), &resultip);
+ ConfEntry->stats_hits++;
- switch (ConfEntry->type)
+ switch (ConfEntry->banaction)
+ {
+ case DNSBLConfEntry::I_KILL:
{
- case DNSBLConfEntry::A_BITMASK:
- bitmask = resultip.s_addr >> 24; /* Last octet (network byte order) */
- bitmask &= ConfEntry->bitmask;
- match = (bitmask != 0);
- break;
- case DNSBLConfEntry::A_RECORD:
- record = resultip.s_addr >> 24; /* Last octet */
- match = (ConfEntry->records[record] == 1);
+ ServerInstance->Users->QuitUser(them, "Killed (" + reason + ")");
break;
}
-
- if (match)
+ case DNSBLConfEntry::I_MARK:
{
- std::string reason = ConfEntry->reason;
- std::string::size_type x = reason.find("%ip%");
- while (x != std::string::npos)
+ if (!ConfEntry->ident.empty())
{
- reason.erase(x, 4);
- reason.insert(x, them->GetIPString());
- x = reason.find("%ip%");
+ them->WriteNumeric(304, ":Your ident has been set to " + ConfEntry->ident + " because you matched " + reason);
+ them->ChangeIdent(ConfEntry->ident);
}
- ConfEntry->stats_hits++;
-
- switch (ConfEntry->banaction)
+ if (!ConfEntry->host.empty())
{
- case DNSBLConfEntry::I_KILL:
- {
- ServerInstance->Users->QuitUser(them, "Killed (" + reason + ")");
- break;
- }
- case DNSBLConfEntry::I_MARK:
- {
- if (!ConfEntry->ident.empty())
- {
- them->WriteServ("304 " + them->nick + " :Your ident has been set to " + ConfEntry->ident + " because you matched " + reason);
- them->ChangeIdent(ConfEntry->ident.c_str());
- }
-
- if (!ConfEntry->host.empty())
- {
- them->WriteServ("304 " + them->nick + " :Your host has been set to " + ConfEntry->host + " because you matched " + reason);
- them->ChangeDisplayedHost(ConfEntry->host.c_str());
- }
-
- nameExt.set(them, ConfEntry->name);
- break;
- }
- case DNSBLConfEntry::I_KLINE:
- {
- KLine* kl = new KLine(ServerInstance->Time(), ConfEntry->duration, ServerInstance->Config->ServerName.c_str(), reason.c_str(),
- "*", them->GetIPString());
- if (ServerInstance->XLines->AddLine(kl,NULL))
- {
- std::string timestr = ServerInstance->TimeString(kl->expiry);
- ServerInstance->SNO->WriteGlobalSno('x',"K:line added due to DNSBL match on *@%s to expire on %s: %s",
- them->GetIPString(), timestr.c_str(), reason.c_str());
- ServerInstance->XLines->ApplyLines();
- }
- else
- {
- delete kl;
- return;
- }
- break;
- }
- case DNSBLConfEntry::I_GLINE:
- {
- GLine* gl = new GLine(ServerInstance->Time(), ConfEntry->duration, ServerInstance->Config->ServerName.c_str(), reason.c_str(),
- "*", them->GetIPString());
- if (ServerInstance->XLines->AddLine(gl,NULL))
- {
- std::string timestr = ServerInstance->TimeString(gl->expiry);
- ServerInstance->SNO->WriteGlobalSno('x',"G:line added due to DNSBL match on *@%s to expire on %s: %s",
- them->GetIPString(), timestr.c_str(), reason.c_str());
- ServerInstance->XLines->ApplyLines();
- }
- else
- {
- delete gl;
- return;
- }
- break;
- }
- case DNSBLConfEntry::I_ZLINE:
- {
- ZLine* zl = new ZLine(ServerInstance->Time(), ConfEntry->duration, ServerInstance->Config->ServerName.c_str(), reason.c_str(),
- them->GetIPString());
- if (ServerInstance->XLines->AddLine(zl,NULL))
- {
- std::string timestr = ServerInstance->TimeString(zl->expiry);
- ServerInstance->SNO->WriteGlobalSno('x',"Z:line added due to DNSBL match on *@%s to expire on %s: %s",
- them->GetIPString(), timestr.c_str(), reason.c_str());
- ServerInstance->XLines->ApplyLines();
- }
- else
- {
- delete zl;
- return;
- }
- break;
- }
- case DNSBLConfEntry::I_UNKNOWN:
- {
- break;
- }
- break;
+ them->WriteNumeric(304, ":Your host has been set to " + ConfEntry->host + " because you matched " + reason);
+ them->ChangeDisplayedHost(ConfEntry->host);
}
- ServerInstance->SNO->WriteGlobalSno('a', "Connecting user %s%s detected as being on a DNS blacklist (%s) with result %d", them->nick.empty() ? "<unknown>" : "", them->GetFullRealHost().c_str(), ConfEntry->domain.c_str(), (ConfEntry->type==DNSBLConfEntry::A_BITMASK) ? bitmask : record);
+ nameExt.set(them, ConfEntry->name);
+ break;
+ }
+ case DNSBLConfEntry::I_KLINE:
+ {
+ KLine* kl = new KLine(ServerInstance->Time(), ConfEntry->duration, ServerInstance->Config->ServerName.c_str(), reason.c_str(),
+ "*", them->GetIPString());
+ if (ServerInstance->XLines->AddLine(kl,NULL))
+ {
+ std::string timestr = InspIRCd::TimeString(kl->expiry);
+ ServerInstance->SNO->WriteGlobalSno('x',"K:line added due to DNSBL match on *@%s to expire on %s: %s",
+ them->GetIPString().c_str(), timestr.c_str(), reason.c_str());
+ ServerInstance->XLines->ApplyLines();
+ }
+ else
++ {
+ delete kl;
++ return;
++ }
+ break;
+ }
+ case DNSBLConfEntry::I_GLINE:
+ {
+ GLine* gl = new GLine(ServerInstance->Time(), ConfEntry->duration, ServerInstance->Config->ServerName.c_str(), reason.c_str(),
+ "*", them->GetIPString());
+ if (ServerInstance->XLines->AddLine(gl,NULL))
+ {
+ std::string timestr = InspIRCd::TimeString(gl->expiry);
+ ServerInstance->SNO->WriteGlobalSno('x',"G:line added due to DNSBL match on *@%s to expire on %s: %s",
+ them->GetIPString().c_str(), timestr.c_str(), reason.c_str());
+ ServerInstance->XLines->ApplyLines();
+ }
+ else
++ {
+ delete gl;
++ return;
++ }
+ break;
+ }
+ case DNSBLConfEntry::I_ZLINE:
+ {
+ ZLine* zl = new ZLine(ServerInstance->Time(), ConfEntry->duration, ServerInstance->Config->ServerName.c_str(), reason.c_str(),
+ them->GetIPString());
+ if (ServerInstance->XLines->AddLine(zl,NULL))
+ {
+ std::string timestr = InspIRCd::TimeString(zl->expiry);
+ ServerInstance->SNO->WriteGlobalSno('x',"Z:line added due to DNSBL match on *@%s to expire on %s: %s",
+ them->GetIPString().c_str(), timestr.c_str(), reason.c_str());
+ ServerInstance->XLines->ApplyLines();
+ }
+ else
++ {
+ delete zl;
++ return;
++ }
+ break;
}
- else
- ConfEntry->stats_misses++;
+ case DNSBLConfEntry::I_UNKNOWN:
+ default:
+ break;
}
- else
- ConfEntry->stats_misses++;
+
+ ServerInstance->SNO->WriteGlobalSno('a', "Connecting user %s%s detected as being on a DNS blacklist (%s) with result %d", them->nick.empty() ? "<unknown>" : "", them->GetFullRealHost().c_str(), ConfEntry->domain.c_str(), (ConfEntry->type==DNSBLConfEntry::A_BITMASK) ? bitmask : record);
}
+ else
+ ConfEntry->stats_misses++;
}
- virtual void OnError(ResolverError e, const std::string &errormessage)
+ void OnError(const DNS::Query *q) CXX11_OVERRIDE
{
LocalUser* them = (LocalUser*)ServerInstance->FindUUID(theiruid);
- if (them)
- {
- int i = countExt.get(them);
- if (i)
- countExt.set(them, i - 1);
- }
- }
+ if (!them)
+ return;
- virtual ~DNSBLResolver()
- {
+ int i = countExt.get(them);
+ if (i)
+ countExt.set(them, i - 1);
+
+ if (q->error == DNS::ERROR_NO_RECORDS || q->error == DNS::ERROR_DOMAIN_NOT_FOUND)
+ ConfEntry->stats_misses++;
}
};
class ModuleHelpop : public Module
{
- std::string h_file;
- private:
CommandHelpop cmd;
Helpop ho;
{
}
- void init()
+ void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
{
- helpop_map.clear();
- ReadConfig();
- ServerInstance->Modules->AddService(ho);
- ServerInstance->Modules->AddService(cmd);
- Implementation eventlist[] = { I_OnRehash, I_OnWhois };
- ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
- }
-
- void ReadConfig()
- {
- std::map<irc::string, std::string> help;
++ HelpopMap help;
ConfigTagList tags = ServerInstance->Config->ConfTags("helpop");
for(ConfigIter i = tags.first; i != tags.second; ++i)
throw ModuleException("m_helpop: Helpop file is missing important entry 'nohelp'. Please check the example conf.");
}
+ helpop_map.swap(help);
}
- void OnRehash(User* user)
- {
- ReadConfig();
- }
-
- void OnWhois(User* src, User* dst)
+ void OnWhois(User* src, User* dst) CXX11_OVERRIDE
{
- if (dst->IsModeSet('h'))
+ if (dst->IsModeSet(ho))
{
- ServerInstance->SendWhoisLine(src, dst, 310, src->nick+" "+dst->nick+" :is available for help.");
+ ServerInstance->SendWhoisLine(src, dst, 310, dst->nick+" :is available for help.");
}
}
GetIOHook()->OnStreamSocketAccept(this, client, server);
}
- virtual void OnError(BufferedSocketError)
+ ~HttpServerSocket()
+ {
+ sockets.erase(this);
+ }
+
+ void OnError(BufferedSocketError) CXX11_OVERRIDE
{
ServerInstance->GlobalCulls.AddItem(this);
}
}
};
+class HTTPdAPIImpl : public HTTPdAPIBase
+{
+ public:
+ HTTPdAPIImpl(Module* parent)
+ : HTTPdAPIBase(parent)
+ {
+ }
+
+ void SendResponse(HTTPDocumentResponse& resp) CXX11_OVERRIDE
+ {
+ claimed = true;
+ resp.src.sock->Page(resp.document, resp.responsecode, &resp.headers);
+ }
+};
+
class ModuleHttpServer : public Module
{
+ std::vector<HttpServerSocket *> httpsocks;
+ HTTPdAPIImpl APIImpl;
+ unsigned int timeoutsec;
public:
+ ModuleHttpServer()
+ : APIImpl(this)
+ {
+ }
- void init()
+ void init() CXX11_OVERRIDE
{
HttpModule = this;
- Implementation eventlist[] = { I_OnAcceptConnection, I_OnBackgroundTimer, I_OnRehash };
- ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
- OnRehash(NULL);
}
- void OnRehash(User* user)
++ void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
+ {
+ ConfigTag* tag = ServerInstance->Config->ConfValue("httpd");
+ timeoutsec = tag->getInt("timeout");
+ }
+
- void OnRequest(Request& request)
- {
- if (strcmp(request.id, "HTTP-DOC") != 0)
- return;
- HTTPDocumentResponse& resp = static_cast<HTTPDocumentResponse&>(request);
- claimed = true;
- resp.src.sock->Page(resp.document, resp.responsecode, &resp.headers);
- }
-
- ModResult OnAcceptConnection(int nfd, ListenSocket* from, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server)
+ ModResult OnAcceptConnection(int nfd, ListenSocket* from, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server) CXX11_OVERRIDE
{
if (from->bind_tag->getString("type") != "httpd")
return MOD_RES_PASSTHRU;
return MOD_RES_ALLOW;
}
- ~ModuleHttpServer()
- void OnBackgroundTimer(time_t curtime)
++ void OnBackgroundTimer(time_t curtime) CXX11_OVERRIDE
+ {
+ if (!timeoutsec)
+ return;
+
+ time_t oldest_allowed = curtime - timeoutsec;
+ for (std::set<HttpServerSocket*>::const_iterator i = sockets.begin(); i != sockets.end(); )
+ {
+ HttpServerSocket* sock = *i;
+ ++i;
+ if (sock->createtime < oldest_allowed)
+ {
+ sock->cull();
+ delete sock;
+ }
+ }
+ }
+
- CullResult cull()
++ CullResult cull() CXX11_OVERRIDE
{
- for (size_t i = 0; i < httpsocks.size(); i++)
+ std::set<HttpServerSocket*> local;
+ local.swap(sockets);
+ for (std::set<HttpServerSocket*>::const_iterator i = local.begin(); i != local.end(); ++i)
{
- httpsocks[i]->cull();
- delete httpsocks[i];
+ HttpServerSocket* sock = *i;
+ sock->cull();
+ delete sock;
}
+ return Module::cull();
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides HTTP serving facilities to modules", VF_VENDOR);
}
/* wooo, got a result (it will be good, or bad) */
if (isock->result.empty())
{
- user->ident.insert(0, 1, '~');
+ user->ident.insert(user->ident.begin(), 1, '~');
- user->WriteServ("NOTICE Auth :*** Could not find your ident, using %s instead.", user->ident.c_str());
+ user->WriteNotice("*** Could not find your ident, using " + user->ident + " instead.");
}
else
{
}
else
{
- if (channel->IsModeSet('j'))
- {
- ext.unset(channel);
- channel->SetModeParam('j', "");
- return MODEACTION_ALLOW;
- }
+ if (!channel->IsModeSet(this))
+ return MODEACTION_DENY;
+
- joinfloodsettings* f = ext.get(channel);
- if (f)
- {
- ext.unset(channel);
- return MODEACTION_ALLOW;
- }
++ ext.unset(channel);
++ return MODEACTION_ALLOW;
}
return MODEACTION_DENY;
}
{
bool RequireKey;
bool NoisyOverride;
+ ChanModeReference topiclock;
+ ChanModeReference inviteonly;
+ ChanModeReference key;
+ ChanModeReference limit;
+ static bool IsOverride(unsigned int userlevel, const std::string& modeline)
+ {
+ for (std::string::const_iterator i = modeline.begin(); i != modeline.end(); ++i)
+ {
+ ModeHandler* mh = ServerInstance->Modes->FindMode(*i, MODETYPE_CHANNEL);
+ if (!mh)
+ continue;
+
+ if (mh->GetLevelRequired() > userlevel)
+ return true;
+ }
+ return false;
+ }
+
public:
+ ModuleOverride()
+ : topiclock(this, "topiclock")
+ , inviteonly(this, "inviteonly")
+ , key(this, "key")
+ , limit(this, "limit")
+ {
+ }
- void init()
+ void init() CXX11_OVERRIDE
{
- // read our config options (main config file)
- OnRehash(NULL);
ServerInstance->SNO->EnableSnomask('v', "OVERRIDE");
- Implementation eventlist[] = { I_OnRehash, I_OnPreMode, I_On005Numeric, I_OnUserPreJoin, I_OnUserPreKick, I_OnPreTopicChange };
- ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- void OnRehash(User* user)
+ void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
{
- // re-read our config options on a rehash
+ // re-read our config options
ConfigTag* tag = ServerInstance->Config->ConfValue("override");
NoisyOverride = tag->getBool("noisy");
RequireKey = tag->getBool("requirekey");
byte *RMD(byte *message, dword length, unsigned int* key)
{
- ServerInstance->Logs->Log("m_ripemd160", DEBUG, "RMD: '%s' length=%u", (const char*)message, length);
dword MDbuf[RMDsize/32]; /* contains (A, B, C, D(E)) */
- static byte hashcode[RMDsize/8]; /* for final hash-value */
dword X[16]; /* current 16-word chunk */
unsigned int i; /* counter */
dword nbytes; /* # of bytes not yet processed */
return CMD_FAILURE;
}
- /* For local users, we send the JoinUser which may create a channel and set its TS.
+ /* 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 generate the users JOIN or FJOIN instead.
+ * and then that server will handle the command.
*/
- if (IS_LOCAL(dest))
+ LocalUser* localuser = IS_LOCAL(dest);
+ if (localuser)
{
- Channel::JoinUser(dest, parameters[1].c_str(), true, "", false, ServerInstance->Time());
- /* Fix for dotslasher and w00t - if the join didnt succeed, return CMD_FAILURE so that it doesnt propagate */
- Channel* n = ServerInstance->FindChan(parameters[1]);
- if (n)
+ Channel* n = Channel::JoinUser(localuser, parameters[1], true);
+ if (n && n->HasUser(dest))
{
- ServerInstance->SNO->WriteToSnoMask('a', user->nick+" used SAJOIN to make "+dest->nick+" join "+parameters[1]);
- if (n->HasUser(dest))
- {
- ServerInstance->SNO->WriteGlobalSno('a', user->nick+" used SAJOIN to make "+dest->nick+" join "+parameters[1]);
- return CMD_SUCCESS;
- }
- else
- {
- user->WriteServ("NOTICE "+user->nick+" :*** Could not join "+dest->nick+" to "+parameters[1]+" (User is probably banned, or blocking modes)");
- return CMD_FAILURE;
- }
++ ServerInstance->SNO->WriteGlobalSno('a', user->nick+" used SAJOIN to make "+dest->nick+" join "+parameters[1]);
+ return CMD_SUCCESS;
}
else
{
this->state = SASL_DONE;
this->result = this->GetSaslResult(msg[3]);
}
- ServerInstance->Logs->Log("m_sasl", DEFAULT, "Services sent an unknown SASL message \"%s\" \"%s\"", msg[2].c_str(), msg[3].c_str());
+ else if (msg[2] == "M")
+ this->user->WriteNumeric(908, "%s %s :are available SASL mechanisms", this->user->nick.c_str(), msg[3].c_str());
+ else
++ ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Services sent an unknown SASL message \"%s\" \"%s\"", msg[2].c_str(), msg[3].c_str());
break;
case SASL_DONE:
AChannel_M(Module* Creator) : SimpleChannelModeHandler(Creator, "regmoderated", 'M') { }
};
-class ModuleServicesAccount : public Module
++static bool ReadCGIIRCExt(const char* extname, User* user, const std::string*& out)
+ {
- AChannel_R m1;
- AChannel_M m2;
- AUser_R m3;
- Channel_r m4;
- User_r m5;
- AccountExtItem accountname;
- bool checking_ban;
++ ExtensionItem* wiext = ServerInstance->Extensions.GetItem(extname);
++ if (!wiext)
++ return false;
+
- static bool ReadCGIIRCExt(const char* extname, User* user, const std::string*& out)
- {
- ExtensionItem* wiext = ServerInstance->Extensions.GetItem(extname);
- if (!wiext)
- return false;
-
- if (wiext->creator->ModuleSourceFile != "m_cgiirc.so")
- return false;
++ if (wiext->creator->ModuleSourceFile != "m_cgiirc.so")
++ return false;
+
- StringExtItem* stringext = static_cast<StringExtItem*>(wiext);
- std::string* addr = stringext->get(user);
- if (!addr)
- return false;
++ StringExtItem* stringext = static_cast<StringExtItem*>(wiext);
++ std::string* addr = stringext->get(user);
++ if (!addr)
++ return false;
+
- out = addr;
- return true;
- }
++ out = addr;
++ return true;
++}
+
+class AccountExtItemImpl : public AccountExtItem
+{
public:
- ModuleServicesAccount() : m1(this), m2(this), m3(this), m4(this), m5(this),
- accountname("accountname", this), checking_ban(false)
+ AccountExtItemImpl(Module* mod)
+ : AccountExtItem("accountname", mod)
{
}
- void init()
+ void unserialize(SerializeFormat format, Extensible* container, const std::string& value)
{
- ServiceProvider* providerlist[] = { &m1, &m2, &m3, &m4, &m5, &accountname };
- ServerInstance->Modules->AddServices(providerlist, sizeof(providerlist)/sizeof(ServiceProvider*));
- Implementation eventlist[] = { I_OnWhois, I_OnUserPreMessage, I_OnUserPreNotice, I_OnUserPreJoin, I_OnCheckBan,
- I_OnDecodeMetaData, I_On005Numeric, I_OnUserPostNick, I_OnSetConnectClass };
+ User* user = dynamic_cast<User*>(container);
+ if (!user)
+ return;
+
+ StringExtItem::unserialize(format, container, value);
+ if (!value.empty())
+ {
+ // Logged in
+ if (IS_LOCAL(user))
- user->WriteNumeric(900, "%s %s :You are now logged in as %s",
- user->GetFullHost().c_str(), value.c_str(), value.c_str());
++ {
++ const std::string* host = &user->dhost;
++ if (user->registered != REG_ALL)
++ {
++ if (!ReadCGIIRCExt("cgiirc_webirc_hostname", user, host))
++ {
++ ReadCGIIRCExt("cgiirc_webirc_ip", user, host);
++ }
++ }
+
- ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
++ user->WriteNumeric(900, "%s!%s@%s %s :You are now logged in as %s",
++ user->nick.c_str(), user->ident.c_str(), host->c_str(), value.c_str(), value.c_str());
++ }
+
+ AccountEvent(creator, user, value).Send();
+ }
+ else
+ {
+ // Logged out
+ AccountEvent(creator, user, "").Send();
+ }
}
+};
- void On005Numeric(std::string &t)
+class ModuleServicesAccount : public Module
+{
+ AChannel_R m1;
+ AChannel_M m2;
+ AUser_R m3;
+ Channel_r m4;
+ User_r m5;
+ AccountExtItemImpl accountname;
++ bool checking_ban;
+ public:
+ ModuleServicesAccount() : m1(this), m2(this), m3(this), m4(this), m5(this),
+ accountname(this)
+ {
+ }
+
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- ServerInstance->AddExtBanChar('R');
- ServerInstance->AddExtBanChar('U');
+ tokens["EXTBAN"].push_back('R');
+ tokens["EXTBAN"].push_back('U');
}
/* <- :twisted.oscnet.org 330 w00t2 w00t2 w00t :is logged in as */
return MOD_RES_PASSTHRU;
}
- ModResult OnCheckBan(User* user, Channel* chan, const std::string& mask)
+ ModResult OnCheckBan(User* user, Channel* chan, const std::string& mask) CXX11_OVERRIDE
{
- static bool checking = false;
- if (checking)
+ if (checking_ban)
return MOD_RES_PASSTHRU;
if ((mask.length() > 2) && (mask[1] == ':'))
{
}
- void init()
- {
- OnRehash(NULL);
- ServerInstance->Modules->AddService(cmdsilence);
- ServerInstance->Modules->AddService(cmdsvssilence);
- ServerInstance->Modules->AddService(cmdsilence.ext);
-
- Implementation eventlist[] = { I_OnRehash, I_On005Numeric, I_OnUserPreNotice, I_OnUserPreMessage, I_OnUserPreInvite };
- ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
- }
-
- void OnRehash(User* user)
+ void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
{
- maxsilence = ServerInstance->Config->ConfValue("showwhois")->getInt("maxentries", 32);
+ maxsilence = ServerInstance->Config->ConfValue("silence")->getInt("maxentries", 32);
if (!maxsilence)
maxsilence = 32;
}
#include "protocolinterface.h"
ModuleSpanningTree::ModuleSpanningTree()
- : KeepNickTS(false)
+ : rconnect(this), rsquit(this), map(this)
+ , commands(NULL), DNS(this, "DNS")
++ , KeepNickTS(false)
{
- Utils = new SpanningTreeUtilities(this);
- commands = new SpanningTreeCommands(this);
- RefreshTimer = NULL;
}
SpanningTreeCommands::SpanningTreeCommands(ModuleSpanningTree* module)
if (user->registered != REG_ALL || !IS_LOCAL(user))
return;
- CmdBuilder(user, "FNAME").push(gecos).Broadcast();
- parameterlist params;
- params.push_back(":" + gecos);
- Utils->DoOneToMany(user->uuid,"FNAME",params);
++ CmdBuilder(user, "FNAME").push_last(gecos).Broadcast();
}
void ModuleSpanningTree::OnChangeIdent(User* user, const std::string &ident)
user->age = ServerInstance->Time();
params.push_back(ConvToStr(user->age));
- Utils->DoOneToMany(user->uuid,"NICK",params);
+ params.Broadcast();
+ this->KeepNickTS = false;
}
else if (!loopCall && user->nick == user->uuid)
{
*/
bool loopCall;
+ /** True if users are quitting due to a netsplit
+ */
+ bool SplitInProgress;
+
+ /** If true OnUserPostNick() won't update the nick TS before sending the NICK,
+ * used when handling SVSNICK.
+ */
+ bool KeepNickTS;
+
/** Constructor
*/
ModuleSpanningTree();
#include "inspircd.h"
-#include "utils.h"
+ #include "main.h"
#include "commands.h"
-CmdResult CommandSVSNick::Handle(const std::vector<std::string>& parameters, User *user)
+CmdResult CommandSVSNick::Handle(User* user, std::vector<std::string>& parameters)
{
User* u = ServerInstance->FindNick(parameters[0]);
if (isdigit(nick[0]))
nick = u->uuid;
- if (!u->ForceNickChange(nick.c_str()))
+ // Don't update the TS if the nick is exactly the same
+ if (u->nick == nick)
+ return CMD_FAILURE;
+
+ time_t NickTS = ConvToInt(parameters[2]);
+ if (NickTS <= 0)
+ return CMD_FAILURE;
+
+ ModuleSpanningTree* st = (ModuleSpanningTree*)(Module*)creator;
+ st->KeepNickTS = true;
+ u->age = NickTS;
+
+ if (!u->ForceNickChange(nick))
{
/* buh. UID them */
- if (!u->ForceNickChange(u->uuid.c_str()))
+ if (!u->ForceNickChange(u->uuid))
{
ServerInstance->Users->QuitUser(u, "Nickname collision");
- return CMD_SUCCESS;
}
}
#include "inspircd.h"
#include "xline.h"
-/* $ModDesc: Implements SVSHOLD. Like Q:Lines, but can only be added/removed by Services. */
-
+ namespace
+ {
+ bool silent;
+ }
+
/** Holds a SVSHold item
*/
class SVSHold : public XLine
bool Matches(const std::string &s)
{
- if (nickname == s)
- return true;
- return false;
+ return InspIRCd::Match(s, nickname);
}
- ServerInstance->SNO->WriteToSnoMask('x',"Removing expired SVSHOLD %s (set by %s %ld seconds ago)",
- this->nickname.c_str(), this->source.c_str(), (long int)(ServerInstance->Time() - this->set_time));
+ void DisplayExpiry()
+ {
+ if (!silent)
+ {
- const char* Displayable()
++ ServerInstance->SNO->WriteToSnoMask('x', "Removing expired SVSHOLD %s (set by %s %ld seconds ago)",
++ nickname.c_str(), source.c_str(), (long)(ServerInstance->Time() - set_time));
+ }
+ }
+
+ const std::string& Displayable()
{
- return nickname.c_str();
+ return nickname;
}
};
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->XLines->RegisterFactory(&s);
- ServerInstance->Modules->AddService(cmd);
- Implementation eventlist[] = { I_OnUserPreNick, I_OnStats, I_OnRehash };
- ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
- OnRehash(NULL);
}
- void OnRehash(User* user)
++ void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
+ {
+ ConfigTag* tag = ServerInstance->Config->ConfValue("svshold");
+ silent = tag->getBool("silent");
+ }
+
- virtual ModResult OnStats(char symbol, User* user, string_list &out)
+ ModResult OnStats(char symbol, User* user, string_list &out) CXX11_OVERRIDE
{
if(symbol != 'S')
return MOD_RES_PASSTHRU;
{
irc::sockets::satoap(client_sa, cachedip, port);
/* IP addresses starting with a : on irc are a Bad Thing (tm) */
- if (cachedip.c_str()[0] == ':')
+ if (cachedip[0] == ':')
- cachedip.insert(0,1,'0');
+ cachedip.insert(cachedip.begin(),1,'0');
}
- return cachedip.c_str();
+ return cachedip;
}
irc::sockets::cidr_mask User::GetCIDRMask()