diff options
Diffstat (limited to 'src/modules')
27 files changed, 219 insertions, 65 deletions
diff --git a/src/modules/m_alias.cpp b/src/modules/m_alias.cpp index 065b9184e..b3b5f2c76 100644 --- a/src/modules/m_alias.cpp +++ b/src/modules/m_alias.cpp @@ -310,11 +310,11 @@ class ModuleAlias : public Module for (unsigned int i = 0; i < newline.length(); i++) { char c = newline[i]; - if (c == '$') + if ((c == '$') && (i + 1 < newline.length())) { if (isdigit(newline[i+1])) { - int len = (newline[i+2] == '-') ? 3 : 2; + int len = ((i + 2 < newline.length()) && (newline[i+2] == '-')) ? 3 : 2; std::string var = newline.substr(i, len); result.append(GetVar(var, original_line)); i += len - 1; diff --git a/src/modules/m_callerid.cpp b/src/modules/m_callerid.cpp index 3dc932958..6f2c67300 100644 --- a/src/modules/m_callerid.cpp +++ b/src/modules/m_callerid.cpp @@ -158,13 +158,18 @@ class CommandAccept : public Command */ typedef std::pair<User*, bool> ACCEPTAction; - static ACCEPTAction GetTargetAndAction(std::string& tok) + static ACCEPTAction GetTargetAndAction(std::string& tok, User* cmdfrom = NULL) { bool remove = (tok[0] == '-'); if ((remove) || (tok[0] == '+')) tok.erase(tok.begin()); - User* target = ServerInstance->FindNick(tok); + 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; @@ -216,7 +221,7 @@ public: } std::string tok = parameters[0]; - ACCEPTAction action = GetTargetAndAction(tok); + ACCEPTAction action = GetTargetAndAction(tok, user); if (!action.first) { user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", tok.c_str()); @@ -248,7 +253,7 @@ public: // 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; diff --git a/src/modules/m_channames.cpp b/src/modules/m_channames.cpp index 8b050df2b..f6d78037d 100644 --- a/src/modules/m_channames.cpp +++ b/src/modules/m_channames.cpp @@ -106,6 +106,12 @@ class ModuleChannelNames : public Module ConfigTag* tag = ServerInstance->Config->ConfValue("channames"); std::string denyToken = tag->getString("denyrange"); std::string allowToken = tag->getString("allowrange"); + + if (!denyToken.compare(0, 2, "0-")) + denyToken[0] = '1'; + if (!allowToken.compare(0, 2, "0-")) + allowToken[0] = '1'; + allowedmap.set(); irc::portparser denyrange(denyToken, false); diff --git a/src/modules/m_dccallow.cpp b/src/modules/m_dccallow.cpp index 487e4a7ed..7332402ba 100644 --- a/src/modules/m_dccallow.cpp +++ b/src/modules/m_dccallow.cpp @@ -225,6 +225,10 @@ class CommandDccallow : public Command 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) diff --git a/src/modules/m_dnsbl.cpp b/src/modules/m_dnsbl.cpp index 10419de51..6ee1c317b 100644 --- a/src/modules/m_dnsbl.cpp +++ b/src/modules/m_dnsbl.cpp @@ -142,7 +142,10 @@ class DNSBLResolver : public DNS::Request ServerInstance->XLines->ApplyLines(); } else + { delete kl; + return; + } break; } case DNSBLConfEntry::I_GLINE: @@ -157,7 +160,10 @@ class DNSBLResolver : public DNS::Request ServerInstance->XLines->ApplyLines(); } else + { delete gl; + return; + } break; } case DNSBLConfEntry::I_ZLINE: @@ -172,7 +178,10 @@ class DNSBLResolver : public DNS::Request ServerInstance->XLines->ApplyLines(); } else + { delete zl; + return; + } break; } case DNSBLConfEntry::I_UNKNOWN: diff --git a/src/modules/m_helpop.cpp b/src/modules/m_helpop.cpp index 64bdc2400..2fe958a71 100644 --- a/src/modules/m_helpop.cpp +++ b/src/modules/m_helpop.cpp @@ -96,7 +96,6 @@ class CommandHelpop : public Command class ModuleHelpop : public Module { - std::string h_file; CommandHelpop cmd; Helpop ho; @@ -108,7 +107,7 @@ class ModuleHelpop : public Module void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE { - helpop_map.clear(); + HelpopMap help; ConfigTagList tags = ServerInstance->Config->ConfTags("helpop"); for(ConfigIter i = tags.first; i != tags.second; ++i) @@ -123,20 +122,21 @@ class ModuleHelpop : public Module throw ModuleException("m_helpop: The key 'index' is reserved for internal purposes. Please remove it."); } - helpop_map[key] = value; + help[key] = value; } - if (helpop_map.find("start") == helpop_map.end()) + if (help.find("start") == help.end()) { // error! throw ModuleException("m_helpop: Helpop file is missing important entry 'start'. Please check the example conf."); } - else if (helpop_map.find("nohelp") == helpop_map.end()) + else if (help.find("nohelp") == help.end()) { // error! throw ModuleException("m_helpop: Helpop file is missing important entry 'nohelp'. Please check the example conf."); } + helpop_map.swap(help); } void OnWhois(User* src, User* dst) CXX11_OVERRIDE diff --git a/src/modules/m_httpd.cpp b/src/modules/m_httpd.cpp index 5a71f8018..735551dff 100644 --- a/src/modules/m_httpd.cpp +++ b/src/modules/m_httpd.cpp @@ -30,6 +30,7 @@ class ModuleHttpServer; static ModuleHttpServer* HttpModule; static bool claimed; +static std::set<HttpServerSocket*> sockets; /** HTTP socket states */ @@ -56,8 +57,11 @@ class HttpServerSocket : public BufferedSocket std::string http_version; public: + const time_t createtime; + HttpServerSocket(int newfd, const std::string& IP, ListenSocket* via, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server) : BufferedSocket(newfd), ip(IP), postsize(0) + , createtime(ServerInstance->Time()) { InternalState = HTTP_SERVE_WAIT_REQUEST; @@ -66,6 +70,11 @@ class HttpServerSocket : public BufferedSocket GetIOHook()->OnStreamSocketAccept(this, client, server); } + ~HttpServerSocket() + { + sockets.erase(this); + } + void OnError(BufferedSocketError) CXX11_OVERRIDE { ServerInstance->GlobalCulls.AddItem(this); @@ -347,6 +356,7 @@ class ModuleHttpServer : public Module { std::vector<HttpServerSocket *> httpsocks; HTTPdAPIImpl APIImpl; + unsigned int timeoutsec; public: ModuleHttpServer() @@ -359,6 +369,12 @@ class ModuleHttpServer : public Module HttpModule = this; } + void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE + { + ConfigTag* tag = ServerInstance->Config->ConfValue("httpd"); + timeoutsec = tag->getInt("timeout"); + } + ModResult OnAcceptConnection(int nfd, ListenSocket* from, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server) CXX11_OVERRIDE { if (from->bind_tag->getString("type") != "httpd") @@ -366,17 +382,39 @@ class ModuleHttpServer : public Module int port; std::string incomingip; irc::sockets::satoap(*client, incomingip, port); - new HttpServerSocket(nfd, incomingip, from, client, server); + sockets.insert(new HttpServerSocket(nfd, incomingip, from, client, server)); return MOD_RES_ALLOW; } - ~ModuleHttpServer() + 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() 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(); } Version GetVersion() CXX11_OVERRIDE diff --git a/src/modules/m_httpd_stats.cpp b/src/modules/m_httpd_stats.cpp index 346fe41f5..11809e893 100644 --- a/src/modules/m_httpd_stats.cpp +++ b/src/modules/m_httpd_stats.cpp @@ -52,7 +52,7 @@ class ModuleHttpStats : public Module ret += it->second; ret += ';'; } - else if (*x == 0x9 || *x == 0xA || *x == 0xD || *x >= 0x20) + else if (*x == 0x09 || *x == 0x0A || *x == 0x0D || ((*x >= 0x20) && (*x <= 0x7e))) { // The XML specification defines the following characters as valid inside an XML document: // Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] diff --git a/src/modules/m_ident.cpp b/src/modules/m_ident.cpp index c73e26b16..1f57fc3e1 100644 --- a/src/modules/m_ident.cpp +++ b/src/modules/m_ident.cpp @@ -336,7 +336,7 @@ class ModuleIdent : public Module /* 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->WriteNotice("*** Could not find your ident, using " + user->ident + " instead."); } else diff --git a/src/modules/m_joinflood.cpp b/src/modules/m_joinflood.cpp index 81ad7e169..edce2b22c 100644 --- a/src/modules/m_joinflood.cpp +++ b/src/modules/m_joinflood.cpp @@ -124,12 +124,8 @@ class JoinFlood : public ModeHandler 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; } @@ -168,7 +164,7 @@ class ModuleJoinFlood : public Module joinfloodsettings *f = jf.ext.get(memb->chan); /* But all others are OK */ - if (f) + if ((f) && (!f->islocked())) { f->addjoin(); if (f->shouldlock()) diff --git a/src/modules/m_mlock.cpp b/src/modules/m_mlock.cpp index 43eadf63e..22faa2119 100644 --- a/src/modules/m_mlock.cpp +++ b/src/modules/m_mlock.cpp @@ -31,12 +31,7 @@ public: return Version("Implements the ability to have server-side MLOCK enforcement.", VF_VENDOR); } - void Prioritize() - { - ServerInstance->Modules->SetPriority(this, I_OnPreMode, PRIORITY_FIRST); - } - - ModResult OnPreMode(User* source, User* dest, Channel* channel, const std::vector<std::string>& parameters) CXX11_OVERRIDE + ModResult OnRawMode(User* source, Channel* channel, const char mode, const std::string& parameter, bool adding, int pcnt) { if (!channel) return MOD_RES_PASSTHRU; @@ -48,11 +43,11 @@ public: if (!mlock_str) return MOD_RES_PASSTHRU; - std::string::size_type p = parameters[1].find_first_of(*mlock_str); + std::string::size_type p = mlock_str->find(mode); if (p != std::string::npos) { source->WriteNumeric(742, "%s %c %s :MODE cannot be set due to channel having an active MLOCK restriction policy", - channel->name.c_str(), parameters[1][p], mlock_str->c_str()); + channel->name.c_str(), mode, mlock_str->c_str()); return MOD_RES_DENY; } diff --git a/src/modules/m_override.cpp b/src/modules/m_override.cpp index ce9ea17e2..346d38b9f 100644 --- a/src/modules/m_override.cpp +++ b/src/modules/m_override.cpp @@ -35,6 +35,20 @@ class ModuleOverride : public Module 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") @@ -110,7 +124,10 @@ class ModuleOverride : public Module unsigned int mode = channel->GetPrefixValue(source); - if (mode < HALFOP_VALUE && CanOverride(source, "MODE")) + if (!IsOverride(mode, parameters[1])) + return MOD_RES_PASSTHRU; + + if (CanOverride(source, "MODE")) { std::string msg = source->nick+" overriding modes:"; for(unsigned int i=0; i < parameters.size(); i++) diff --git a/src/modules/m_permchannels.cpp b/src/modules/m_permchannels.cpp index a0b3284e3..61080b2dd 100644 --- a/src/modules/m_permchannels.cpp +++ b/src/modules/m_permchannels.cpp @@ -165,10 +165,12 @@ class ModulePermanentChannels : public Module { PermChannel p; bool dirty; + bool loaded; bool save_listmodes; public: - ModulePermanentChannels() : p(this), dirty(false) + ModulePermanentChannels() + : p(this), dirty(false), loaded(false) { } @@ -301,8 +303,6 @@ public: // to be able to set the modes they provide (e.g.: m_stripcolor is inited after us) // Prioritize() is called after all module initialization is complete, consequently // all modes are available now - - static bool loaded = false; if (loaded) return; diff --git a/src/modules/m_remove.cpp b/src/modules/m_remove.cpp index 4dcd5aaa1..ed9b6ce25 100644 --- a/src/modules/m_remove.cpp +++ b/src/modules/m_remove.cpp @@ -60,7 +60,10 @@ class RemoveBase : public Command const std::string& username = parameters[neworder ? 1 : 0]; /* Look up the user we're meant to be removing from the channel */ - target = ServerInstance->FindNick(username); + if (IS_LOCAL(user)) + target = ServerInstance->FindNickOnly(username); + else + target = ServerInstance->FindNick(username); /* And the channel we're meant to be removing them from */ channel = ServerInstance->FindChan(channame); diff --git a/src/modules/m_ripemd160.cpp b/src/modules/m_ripemd160.cpp index 41331543a..261cd1e27 100644 --- a/src/modules/m_ripemd160.cpp +++ b/src/modules/m_ripemd160.cpp @@ -149,6 +149,9 @@ typedef uint32_t dword; class RIProv : public HashProvider { + /** Final hash value + */ + byte hashcode[RMDsize/8]; void MDinit(dword *MDbuf, unsigned int* key) { @@ -403,7 +406,6 @@ class RIProv : public HashProvider byte *RMD(byte *message, dword length, unsigned int* key) { 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 */ diff --git a/src/modules/m_sajoin.cpp b/src/modules/m_sajoin.cpp index eda58ef96..0748c013b 100644 --- a/src/modules/m_sajoin.cpp +++ b/src/modules/m_sajoin.cpp @@ -60,7 +60,7 @@ class CommandSajoin : public Command 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]); + ServerInstance->SNO->WriteGlobalSno('a', user->nick+" used SAJOIN to make "+dest->nick+" join "+parameters[1]); return CMD_SUCCESS; } else @@ -71,7 +71,6 @@ class CommandSajoin : public Command } else { - ServerInstance->SNO->WriteToSnoMask('a', user->nick+" sent remote SAJOIN to make "+dest->nick+" join "+parameters[1]); return CMD_SUCCESS; } } diff --git a/src/modules/m_sasl.cpp b/src/modules/m_sasl.cpp index 1d67f0c02..796d343ea 100644 --- a/src/modules/m_sasl.cpp +++ b/src/modules/m_sasl.cpp @@ -91,20 +91,23 @@ class SaslAuthenticator { case SASL_INIT: this->agent = msg[0]; - this->user->Write("AUTHENTICATE %s", msg[3].c_str()); this->state = SASL_COMM; - break; + /* fall through */ case SASL_COMM: if (msg[0] != this->agent) return this->state; - if (msg[2] != "D") + if (msg[2] == "C") this->user->Write("AUTHENTICATE %s", msg[3].c_str()); - else + else if (msg[2] == "D") { this->state = SASL_DONE; this->result = this->GetSaslResult(msg[3]); } + 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: diff --git a/src/modules/m_services_account.cpp b/src/modules/m_services_account.cpp index 5f288424c..8ab9c9a3b 100644 --- a/src/modules/m_services_account.cpp +++ b/src/modules/m_services_account.cpp @@ -102,6 +102,24 @@ class AChannel_M : public SimpleChannelModeHandler AChannel_M(Module* Creator) : SimpleChannelModeHandler(Creator, "regmoderated", 'M') { } }; +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; + + StringExtItem* stringext = static_cast<StringExtItem*>(wiext); + std::string* addr = stringext->get(user); + if (!addr) + return false; + + out = addr; + return true; +} + class AccountExtItemImpl : public AccountExtItem { public: @@ -121,8 +139,19 @@ class AccountExtItemImpl : public AccountExtItem { // 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); + } + } + + 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(); } @@ -142,6 +171,7 @@ class ModuleServicesAccount : public Module 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) @@ -219,8 +249,7 @@ class ModuleServicesAccount : public Module 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] == ':')) @@ -240,9 +269,9 @@ class ModuleServicesAccount : public Module /* If we made it this far we know the user isn't registered so just deny if it matches */ - checking = true; + checking_ban = true; bool result = chan->CheckBan(user, mask.substr(2)); - checking = false; + checking_ban = false; if (result) return MOD_RES_DENY; diff --git a/src/modules/m_showwhois.cpp b/src/modules/m_showwhois.cpp index 7a3b2d352..783f7d3fe 100644 --- a/src/modules/m_showwhois.cpp +++ b/src/modules/m_showwhois.cpp @@ -42,7 +42,7 @@ class SeeWhois : public SimpleUserModeHandler class WhoisNoticeCmd : public Command { public: - WhoisNoticeCmd(Module* Creator) : Command(Creator,"WHOISNOTICE", 1) + WhoisNoticeCmd(Module* Creator) : Command(Creator,"WHOISNOTICE", 2) { flags_needed = FLAG_SERVERONLY; } diff --git a/src/modules/m_silence.cpp b/src/modules/m_silence.cpp index fe7418621..3a213c6e7 100644 --- a/src/modules/m_silence.cpp +++ b/src/modules/m_silence.cpp @@ -85,7 +85,7 @@ class CommandSVSSilence : public Command if (IS_LOCAL(u)) { - ServerInstance->Parser->CallHandler("SILENCE", std::vector<std::string>(++parameters.begin(), parameters.end()), u); + ServerInstance->Parser->CallHandler("SILENCE", std::vector<std::string>(parameters.begin() + 1, parameters.end()), u); } return CMD_SUCCESS; @@ -301,7 +301,7 @@ class ModuleSilence : public Module 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; } diff --git a/src/modules/m_spanningtree/main.cpp b/src/modules/m_spanningtree/main.cpp index 9a7cddec3..671e10269 100644 --- a/src/modules/m_spanningtree/main.cpp +++ b/src/modules/m_spanningtree/main.cpp @@ -38,6 +38,7 @@ ModuleSpanningTree::ModuleSpanningTree() : rconnect(this), rsquit(this), map(this) , commands(NULL), DNS(this, "DNS") + , KeepNickTS(false) { } @@ -246,7 +247,7 @@ void ModuleSpanningTree::ConnectServer(Link* x, Autoconnect* y) { bool ipvalid = true; - if (InspIRCd::Match(ServerInstance->Config->ServerName, assign(x->Name))) + if (InspIRCd::Match(ServerInstance->Config->ServerName, assign(x->Name), rfc_case_insensitive_map)) { ServerInstance->SNO->WriteToSnoMask('l', "CONNECT: Not connecting to myself."); return; @@ -377,9 +378,9 @@ ModResult ModuleSpanningTree::HandleConnect(const std::vector<std::string>& para for (std::vector<reference<Link> >::iterator i = Utils->LinkBlocks.begin(); i < Utils->LinkBlocks.end(); i++) { Link* x = *i; - if (InspIRCd::Match(x->Name.c_str(),parameters[0])) + if (InspIRCd::Match(x->Name.c_str(),parameters[0], rfc_case_insensitive_map)) { - if (InspIRCd::Match(ServerInstance->Config->ServerName, assign(x->Name))) + if (InspIRCd::Match(ServerInstance->Config->ServerName, assign(x->Name), rfc_case_insensitive_map)) { RemoteMessage(user, "*** CONNECT: Server \002%s\002 is ME, not connecting.",x->Name.c_str()); return MOD_RES_DENY; @@ -529,7 +530,7 @@ void ModuleSpanningTree::OnChangeName(User* user, const std::string &gecos) if (user->registered != REG_ALL || !IS_LOCAL(user)) return; - CmdBuilder(user, "FNAME").push(gecos).Broadcast(); + CmdBuilder(user, "FNAME").push_last(gecos).Broadcast(); } void ModuleSpanningTree::OnChangeIdent(User* user, const std::string &ident) @@ -587,11 +588,12 @@ void ModuleSpanningTree::OnUserPostNick(User* user, const std::string &oldnick) /** IMPORTANT: We don't update the TS if the oldnick is just a case change of the newnick! */ - if (irc::string(user->nick.c_str()) != assign(oldnick)) + if ((irc::string(user->nick.c_str()) != assign(oldnick)) && (!this->KeepNickTS)) user->age = ServerInstance->Time(); params.push_back(ConvToStr(user->age)); params.Broadcast(); + this->KeepNickTS = false; } else if (!loopCall && user->nick == user->uuid) { diff --git a/src/modules/m_spanningtree/main.h b/src/modules/m_spanningtree/main.h index 513e86a2f..12667aebf 100644 --- a/src/modules/m_spanningtree/main.h +++ b/src/modules/m_spanningtree/main.h @@ -77,6 +77,11 @@ class ModuleSpanningTree : public Module */ bool SplitInProgress; + /** If true OnUserPostNick() won't update the nick TS before sending the NICK, + * used when handling SVSNICK. + */ + bool KeepNickTS; + /** Constructor */ ModuleSpanningTree(); diff --git a/src/modules/m_spanningtree/svsnick.cpp b/src/modules/m_spanningtree/svsnick.cpp index a504afbd7..b3480eb55 100644 --- a/src/modules/m_spanningtree/svsnick.cpp +++ b/src/modules/m_spanningtree/svsnick.cpp @@ -20,6 +20,7 @@ #include "inspircd.h" +#include "main.h" #include "commands.h" CmdResult CommandSVSNick::Handle(User* user, std::vector<std::string>& parameters) @@ -32,17 +33,28 @@ CmdResult CommandSVSNick::Handle(User* user, std::vector<std::string>& parameter if (isdigit(nick[0])) nick = u->uuid; + // 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)) { ServerInstance->Users->QuitUser(u, "Nickname collision"); - return CMD_SUCCESS; } } - u->age = ConvToInt(parameters[2]); + st->KeepNickTS = false; } return CMD_SUCCESS; diff --git a/src/modules/m_spanningtree/utils.cpp b/src/modules/m_spanningtree/utils.cpp index fd51fb6b4..de96b073d 100644 --- a/src/modules/m_spanningtree/utils.cpp +++ b/src/modules/m_spanningtree/utils.cpp @@ -363,7 +363,7 @@ Link* SpanningTreeUtilities::FindLink(const std::string& name) for (std::vector<reference<Link> >::iterator i = LinkBlocks.begin(); i != LinkBlocks.end(); ++i) { Link* x = *i; - if (InspIRCd::Match(x->Name.c_str(), name.c_str())) + if (InspIRCd::Match(x->Name.c_str(), name.c_str(), rfc_case_insensitive_map)) { return x; } diff --git a/src/modules/m_svshold.cpp b/src/modules/m_svshold.cpp index b1b454e63..c821f63bb 100644 --- a/src/modules/m_svshold.cpp +++ b/src/modules/m_svshold.cpp @@ -23,6 +23,11 @@ #include "inspircd.h" #include "xline.h" +namespace +{ + bool silent; +} + /** Holds a SVSHold item */ class SVSHold : public XLine @@ -48,6 +53,15 @@ public: return InspIRCd::Match(s, nickname); } + void DisplayExpiry() + { + if (!silent) + { + 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; @@ -99,7 +113,8 @@ class CommandSvshold : public Command { if (ServerInstance->XLines->DelLine(parameters[0].c_str(), "SVSHOLD", user)) { - ServerInstance->SNO->WriteToSnoMask('x',"%s removed SVSHOLD on %s",user->nick.c_str(),parameters[0].c_str()); + if (!silent) + ServerInstance->SNO->WriteToSnoMask('x',"%s removed SVSHOLD on %s",user->nick.c_str(),parameters[0].c_str()); } else { @@ -116,6 +131,9 @@ class CommandSvshold : public Command if (ServerInstance->XLines->AddLine(r, user)) { + if (silent) + return CMD_SUCCESS; + if (!duration) { ServerInstance->SNO->WriteGlobalSno('x', "%s added permanent SVSHOLD for %s: %s", user->nick.c_str(), parameters[0].c_str(), parameters[2].c_str()); @@ -159,6 +177,12 @@ class ModuleSVSHold : public Module ServerInstance->XLines->RegisterFactory(&s); } + void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE + { + ConfigTag* tag = ServerInstance->Config->ConfValue("svshold"); + silent = tag->getBool("silent"); + } + ModResult OnStats(char symbol, User* user, string_list &out) CXX11_OVERRIDE { if(symbol != 'S') diff --git a/src/modules/m_uninvite.cpp b/src/modules/m_uninvite.cpp index 6eaeb285f..97ad841f1 100644 --- a/src/modules/m_uninvite.cpp +++ b/src/modules/m_uninvite.cpp @@ -35,7 +35,12 @@ class CommandUninvite : public Command CmdResult Handle (const std::vector<std::string> ¶meters, User *user) { - User* u = ServerInstance->FindNick(parameters[0]); + User* u; + if (IS_LOCAL(user)) + u = ServerInstance->FindNickOnly(parameters[0]); + else + u = ServerInstance->FindNick(parameters[0]); + Channel* c = ServerInstance->FindChan(parameters[1]); if ((!c) || (!u) || (u->registered != REG_ALL)) diff --git a/src/modules/m_userip.cpp b/src/modules/m_userip.cpp index f4e67d6bf..96505a047 100644 --- a/src/modules/m_userip.cpp +++ b/src/modules/m_userip.cpp @@ -40,7 +40,7 @@ class CommandUserip : public Command for (int i = 0; i < (int)parameters.size(); i++) { - User *u = ServerInstance->FindNick(parameters[i]); + User *u = ServerInstance->FindNickOnly(parameters[i]); if ((u) && (u->registered == REG_ALL)) { // Anyone may query their own IP |