diff options
48 files changed, 353 insertions, 147 deletions
diff --git a/docs/conf/helpop-full.conf.example b/docs/conf/helpop-full.conf.example index a6d3c7cd1..6268ba9ca 100644 --- a/docs/conf/helpop-full.conf.example +++ b/docs/conf/helpop-full.conf.example @@ -361,8 +361,8 @@ Sets your name to the specified name."> <helpop key="coper" value="Oper Commands ------------- -OPERMOTD CHECK CLONES USERIP LINE -ALLTIME MODULES WALLOPS GLOBOPS +OPERMOTD CHECK CLONES USERIP TLINE +ALLTIME WALLOPS GLOBOPS SETHOST SETIDENT CHGHOST CHGIDENT CHGNAME SETIDLE SWHOIS diff --git a/docs/conf/helpop.conf.example b/docs/conf/helpop.conf.example index 5f33b6d88..6d6a81719 100644 --- a/docs/conf/helpop.conf.example +++ b/docs/conf/helpop.conf.example @@ -34,7 +34,7 @@ PRIVMSG NOTICE NICK JOIN PART 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 @@ -49,11 +49,11 @@ OPER"> <helpop key="coper" value="Oper Commands ------------- -OPERMOTD CHECK TAXONOMY CLONES USERIP -TLINE ALLTIME MODULES WALLOPS GLOBOPS +OPERMOTD CHECK CLONES USERIP TLINE +ALLTIME WALLOPS GLOBOPS -SETHOST SETIDENT SETNAME CHGHOST CHGIDENT -CHGNAME SETIDLE SWHOIS +SETHOST SETIDENT CHGHOST CHGIDENT CHGNAME +SETIDLE SWHOIS SANICK NICKLOCK NICKUNLOCK diff --git a/docs/conf/inspircd.conf.example b/docs/conf/inspircd.conf.example index fd7973f39..737e05e5a 100644 --- a/docs/conf/inspircd.conf.example +++ b/docs/conf/inspircd.conf.example @@ -236,7 +236,7 @@ <connect # deny: Will not let people connect if they have specified host/IP. - deny="69.254.*"> + deny="192.0.2.*"> # connect:reason is the message that users will see if they match a deny block <connect deny="3ffe::0/32" reason="The 6bone address space is deprecated"> @@ -253,7 +253,7 @@ parent="main" # allow: What IP addresses/hosts to allow for this block. - allow="196.12.*" + allow="203.0.113.*" # hash: what hash this password is hashed with. requires the module # for selected hash (m_md5.so, m_sha256.so or m_ripemd160.so) be @@ -734,13 +734,15 @@ # no Do not show operspywhois="no" - # runasuser: If this is set, InspIRCd will attempt to setuid - # to run as this user- allows binding of ports under 1024. + # runasuser: If this is set, InspIRCd will attempt to switch + # to run as this user, which allows binding of ports under 1024. + # You should NOT set this unless you are starting as root. # NOT SUPPORTED/NEEDED UNDER WINDOWS. #runasuser="" - # runasgroup: If this is set, InspIRCd will attempt to set group - # to run under this group, which allows binding of ports under 1024 + # runasgroup: If this is set, InspIRCd will attempt to switch + # to run as this group, which allows binding of ports under 1024. + # You should NOT set this unless you are starting as root. # NOT SUPPORTED/NEEDED UNDER WINDOWS. #runasgroup="" @@ -894,7 +896,7 @@ <badip # ipmask: IP range to ban. Wildcards and CIDR can be used. - ipmask="69.69.69.69" + ipmask="192.0.2.69" # reason: Reason to display when user is disconnected. reason="No porn here thanks."> @@ -913,22 +915,22 @@ <badhost # host: ident@hostname to ban. # Wildcards and CIDR (if you specify an IP) can be used. - host="*@hundredz.n.hundredz.o.1337.kiddies.com" + host="*@hundredz.n.hundredz.o.1337.kiddies.example.net" # reason: Reason to display when user is disconnected reason="Too many 1337 kiddiots"> -<badhost host="root@*" reason="Don't irc as root!"> -<badhost host="*@172.32.0.0/16" reason="This subnet is bad."> +<badhost host="root@*" reason="Don't IRC as root!"> +<badhost host="*@198.51.100.0/24" reason="This subnet is bad."> # exception: Hosts that are exempt from [kgz]lines. <exception # host: ident@hostname to exempt. # Wildcards and CIDR (if you specify an IP) can be used. - host="*@ircop.host.com" + host="*@ircop.example.com" # reason: Reason for exception. Only shown in /stats e - reason="Opers hostname"> + reason="Oper's hostname"> #-#-#-#-#-#-#-#-#-#-#- INSANE BAN OPTIONS -#-#-#-#-#-#-#-#-#-#-#-#-#-# # # diff --git a/docs/conf/links.conf.example b/docs/conf/links.conf.example index b196c5621..5e36689f0 100644 --- a/docs/conf/links.conf.example +++ b/docs/conf/links.conf.example @@ -29,7 +29,7 @@ # 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 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 @@ -74,7 +74,7 @@ <link name="hub.penguin.org" ipaddr="penguin.box.com" port="7000" - allowmask="69.58.44.0/24" + allowmask="203.0.113.0/24" timeout="300" ssl="gnutls" bind="1.2.3.4" diff --git a/docs/conf/modules.conf.example b/docs/conf/modules.conf.example index 2ab1adebf..672bcb9d0 100644 --- a/docs/conf/modules.conf.example +++ b/docs/conf/modules.conf.example @@ -842,6 +842,9 @@ # a <bind> tag with type "httpd", and load at least one of the other # m_httpd_* modules to provide pages to display. # +# You can adjust the timeout for HTTP connections below. All HTTP +# connections will be closed after (roughly) this many seconds. +#<httpd timeout="20"> #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# # http ACL module: Provides access control lists for m_httpd dependent @@ -1557,7 +1560,8 @@ #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# # SASL authentication module: Provides support for IRC Authentication -# Layer (aka: atheme SASL) via AUTHENTICATE. +# Layer via AUTHENTICATE. Note: You also need to have m_cap.so loaded +# for SASL to work. #<module name="m_sasl.so"> #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# @@ -1816,6 +1820,8 @@ # SVSHold module: Implements SVSHOLD. Like Q:Lines, but can only be # # added/removed by Services. # #<module name="m_svshold.so"> +# If silent is true no snotices will be generated by SVSHOLD. +#<svshold silent="false"> #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# # SWHOIS module: Allows you to add arbitary lines to user WHOIS. diff --git a/docs/conf/opers.conf.example b/docs/conf/opers.conf.example index b39c73e43..a759622a4 100644 --- a/docs/conf/opers.conf.example +++ b/docs/conf/opers.conf.example @@ -90,7 +90,7 @@ # Multiple options can be separated by spaces and CIDR's are allowed. # You CAN use just * or *@* for this section, but it is not recommended # for security reasons. - host="ident@dialup15.isp.com *@localhost *@server.com *@3ffe::0/16" + host="yourident@dialup15.isp.com *@localhost *@example.com *@2001:db8::/32" # ** ADVANCED ** This option is disabled by default. # fingerprint: When using the m_sslinfo module, you may specify @@ -127,7 +127,7 @@ <oper name="Brain" password="s3cret" - host="ident@dialup15.isp.com *@localhost *@server.com *@3ffe::0/16" + host="yourident@dialup15.isp.com *@localhost *@example.com *@2001:db8::/32" #fingerprint="67cb9dc013248a829bb2171ed11becd4" type="NetAdmin"> @@ -155,7 +155,7 @@ # Multiple options can be separated by spaces and CIDR's are allowed. # You CAN use just * or *@* for this section, but it is not recommended # for security reasons. - host="ident@dialup15.isp.com *@localhost *@server.com *@3ffe::0/16" + host="yourident@dialup15.isp.com *@localhost *@example.com *@2001:db8::/32" # type: What oper type this oline is. See the block above for list # of types. NOTE: This is case-sensitive as well. diff --git a/include/configreader.h b/include/configreader.h index e8c439933..7bc6c1bcb 100644 --- a/include/configreader.h +++ b/include/configreader.h @@ -83,8 +83,7 @@ class CoreExport ConfigTag : public refcountbase inline const std::vector<KeyVal>& getItems() const { return items; } /** Create a new ConfigTag, giving access to the private KeyVal item list */ - static ConfigTag* create(const std::string& Tag, const std::string& file, int line, - std::vector<KeyVal>*&items); + static ConfigTag* create(const std::string& Tag, const std::string& file, int line, std::vector<KeyVal>*& Items); private: ConfigTag(const std::string& Tag, const std::string& file, int line); }; diff --git a/include/inspircd.h b/include/inspircd.h index d69d1b46b..7a8c1fb74 100644 --- a/include/inspircd.h +++ b/include/inspircd.h @@ -132,7 +132,7 @@ inline std::string ConvToStr(const bool in) */ inline std::string ConvToStr(char in) { - return std::string(in,1); + return std::string(1, in); } /** Template function to convert any input type to std::string diff --git a/modulemanager b/modulemanager index 9e4670de8..86f9ca0c4 100755 --- a/modulemanager +++ b/modulemanager @@ -24,14 +24,14 @@ use warnings FATAL => qw(all); 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; @@ -56,15 +56,20 @@ sub parse_url; # retrieve and parse entries from sources.list sub parse_url { - my $src = shift; + chomp(my $src = shift); return if $url_seen{$src}; $url_seen{$src}++; - my $doc = get($src); - die "Could not retrieve $_" unless defined $doc; + my $ua = LWP::UserAgent->new(ssl_opts => { verify_hostname => 0 }); + my $response = $ua->get($src); + + unless ($response->is_success) { + my $err = $response->message; + die "Could not retrieve $src: $err"; + } my $mod; - for (split /\n+/, $doc) { + for (split /\n+/, $response->decoded_content) { s/^\s+//; # ignore whitespace at start next if /^#/; if (/^module (\S+) (\S+) (\S+)/) { @@ -257,7 +262,7 @@ sub resolve_deps { } } -my $action = $#ARGV > 0 ? lc shift @ARGV : 'help'; +my $action = $#ARGV >= 0 ? lc shift @ARGV : 'help'; if ($action eq 'install') { for my $mod (@ARGV) { diff --git a/src/channels.cpp b/src/channels.cpp index 563bc2704..5865f6724 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -654,7 +654,8 @@ const char* Channel::ChanModes(bool showkey) */ void Channel::UserList(User *user) { - if (this->IsModeSet(secretmode) && !this->HasUser(user) && !user->HasPrivPermission("channels/auspex")) + bool has_privs = user->HasPrivPermission("channels/auspex"); + if (this->IsModeSet(secretmode) && !this->HasUser(user) && !has_privs) { user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", this->name.c_str()); return; @@ -679,7 +680,7 @@ void Channel::UserList(User *user) { if (i->first->quitting) continue; - if ((!has_user) && (i->first->IsModeSet(invisiblemode))) + if ((!has_user) && (i->first->IsModeSet(invisiblemode)) && (!has_privs)) { /* * user is +i, and source not on the channel, does not show diff --git a/src/commands/cmd_admin.cpp b/src/commands/cmd_admin.cpp index 3a3eed346..0d6c235f0 100644 --- a/src/commands/cmd_admin.cpp +++ b/src/commands/cmd_admin.cpp @@ -30,7 +30,12 @@ class CommandAdmin : public Command public: /** Constructor for admin. */ - CommandAdmin(Module* parent) : Command(parent,"ADMIN",0,0) { syntax = "[<servername>]"; } + CommandAdmin(Module* parent) : Command(parent,"ADMIN",0,0) + { + Penalty = 2; + syntax = "[<servername>]"; + } + /** Handle command. * @param parameters The parameters to the comamnd * @param pcnt The number of parameters passed to teh command diff --git a/src/commands/cmd_commands.cpp b/src/commands/cmd_commands.cpp index 190c883bd..c45616061 100644 --- a/src/commands/cmd_commands.cpp +++ b/src/commands/cmd_commands.cpp @@ -30,7 +30,11 @@ class CommandCommands : public Command public: /** Constructor for commands. */ - CommandCommands ( Module* parent) : Command(parent,"COMMANDS",0,0) { } + CommandCommands(Module* parent) : Command(parent,"COMMANDS",0,0) + { + Penalty = 3; + } + /** Handle command. * @param parameters The parameters to the comamnd * @param pcnt The number of parameters passed to teh command diff --git a/src/commands/cmd_info.cpp b/src/commands/cmd_info.cpp index b3f146c30..7ee1c4d3b 100644 --- a/src/commands/cmd_info.cpp +++ b/src/commands/cmd_info.cpp @@ -32,7 +32,12 @@ class CommandInfo : public Command public: /** Constructor for info. */ - CommandInfo ( Module* parent) : Command(parent,"INFO") { syntax = "[<servermask>]"; } + CommandInfo(Module* parent) : Command(parent,"INFO") + { + Penalty = 4; + syntax = "[<servername>]"; + } + /** Handle command. * @param parameters The parameters to the comamnd * @param pcnt The number of parameters passed to teh command diff --git a/src/commands/cmd_modules.cpp b/src/commands/cmd_modules.cpp index fe199e7a4..d9fa7d5d5 100644 --- a/src/commands/cmd_modules.cpp +++ b/src/commands/cmd_modules.cpp @@ -31,7 +31,12 @@ class CommandModules : public Command public: /** Constructor for modules. */ - CommandModules ( Module* parent) : Command(parent,"MODULES",0,0) { syntax = "[server]"; } + CommandModules(Module* parent) : Command(parent,"MODULES",0,0) + { + Penalty = 4; + syntax = "[<servername>]"; + } + /** Handle command. * @param parameters The parameters to the comamnd * @param pcnt The number of parameters passed to teh command @@ -74,7 +79,7 @@ CmdResult CommandModules::Handle (const std::vector<std::string>& parameters, Us 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; diff --git a/src/commands/cmd_whois.cpp b/src/commands/cmd_whois.cpp index 7e67676ed..e8a751fa0 100644 --- a/src/commands/cmd_whois.cpp +++ b/src/commands/cmd_whois.cpp @@ -80,7 +80,7 @@ void CommandWhois::SplitChanList(User* source, User* dest, const std::string& cl { std::string line; std::ostringstream prefix; - std::string::size_type start, pos, length; + std::string::size_type start, pos; prefix << dest->nick << " :"; line = prefix.str(); @@ -88,23 +88,13 @@ void CommandWhois::SplitChanList(User* source, User* dest, const std::string& cl for (start = 0; (pos = cl.find(' ', start)) != std::string::npos; start = pos+1) { - length = (pos == std::string::npos) ? cl.length() : pos; - - if (line.length() + namelen + length - start > 510) + if (line.length() + namelen + pos - start > 510) { ServerInstance->SendWhoisLine(source, dest, 319, line); line = prefix.str(); } - if(pos == std::string::npos) - { - line.append(cl.substr(start, length - start)); - break; - } - else - { - line.append(cl.substr(start, length - start + 1)); - } + line.append(cl.substr(start, pos - start + 1)); } if (line.length() != prefix.str().length()) diff --git a/src/configparser.cpp b/src/configparser.cpp index e23d6ec43..92f05edd4 100644 --- a/src/configparser.cpp +++ b/src/configparser.cpp @@ -499,10 +499,10 @@ std::string ConfigTag::getTagLocation() return src_name + ":" + ConvToStr(src_line); } -ConfigTag* ConfigTag::create(const std::string& Tag, const std::string& file, int line, std::vector<KeyVal>*&items) +ConfigTag* ConfigTag::create(const std::string& Tag, const std::string& file, int line, std::vector<KeyVal>*& Items) { ConfigTag* rv = new ConfigTag(Tag, file, line); - items = &rv->items; + Items = &rv->items; return rv; } diff --git a/src/inspircd.cpp b/src/inspircd.cpp index 75e9f3699..fb33f1937 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -161,13 +161,20 @@ void InspIRCd::QuickExit(int status) exit(status); } +// Required for returning the proper value of EXIT_SUCCESS for the parent process +static void VoidSignalHandler(int signalreceived) +{ + exit(0); +} + bool InspIRCd::DaemonSeed() { #ifdef _WIN32 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 = fork(); if (childpid < 0) @@ -570,7 +577,7 @@ InspIRCd::InspIRCd(int argc, char** argv) : if (!g) { - this->Logs->Log("STARTUP", LOG_DEFAULT, "getgrnam() failed (bad user?): %s", strerror(errno)); + this->Logs->Log("STARTUP", LOG_DEFAULT, "getgrnam(%s) failed (wrong group?): %s", SetGroup.c_str(), strerror(errno)); this->QuickExit(0); } @@ -578,7 +585,7 @@ InspIRCd::InspIRCd(int argc, char** argv) : if (ret == -1) { - this->Logs->Log("STARTUP", LOG_DEFAULT, "setgid() failed (bad user?): %s", strerror(errno)); + this->Logs->Log("STARTUP", LOG_DEFAULT, "setgid() failed (wrong group?): %s", strerror(errno)); this->QuickExit(0); } } @@ -593,7 +600,7 @@ InspIRCd::InspIRCd(int argc, char** argv) : if (!u) { - this->Logs->Log("STARTUP", LOG_DEFAULT, "getpwnam() failed (bad user?): %s", strerror(errno)); + this->Logs->Log("STARTUP", LOG_DEFAULT, "getpwnam(%s) failed (wrong user?): %s", SetUser.c_str(), strerror(errno)); this->QuickExit(0); } @@ -601,7 +608,7 @@ InspIRCd::InspIRCd(int argc, char** argv) : if (ret == -1) { - this->Logs->Log("STARTUP", LOG_DEFAULT, "setuid() failed (bad user?): %s", strerror(errno)); + this->Logs->Log("STARTUP", LOG_DEFAULT, "setuid() failed (wrong user?): %s", strerror(errno)); this->QuickExit(0); } } diff --git a/src/mode.cpp b/src/mode.cpp index e0381b683..ad46e602d 100644 --- a/src/mode.cpp +++ b/src/mode.cpp @@ -207,7 +207,12 @@ PrefixMode::PrefixMode(Module* Creator, const std::string& Name, char ModeLetter ModeAction PrefixMode::OnModeChange(User* source, User*, Channel* chan, std::string& parameter, bool adding) { - User* target = ServerInstance->FindNick(parameter); + 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()); @@ -347,9 +352,16 @@ ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, bool 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(); diff --git a/src/modules.cpp b/src/modules.cpp index 5c5e4febc..23aceb3e1 100644 --- a/src/modules.cpp +++ b/src/modules.cpp @@ -388,18 +388,23 @@ void ModuleManager::DoSafeUnload(Module* mod) std::vector<reference<ExtensionItem> > items; ServerInstance->Extensions.BeginUnregister(modfind->second, items); /* Give the module a chance to tidy out all its metadata */ - for (chan_hash::iterator c = ServerInstance->chanlist->begin(); c != ServerInstance->chanlist->end(); c++) + for (chan_hash::iterator c = ServerInstance->chanlist->begin(); c != ServerInstance->chanlist->end(); ) { - mod->OnCleanup(TYPE_CHANNEL,c->second); - c->second->doUnhookExtensions(items); - const UserMembList* users = c->second->GetUsers(); + Channel* chan = c->second; + ++c; + mod->OnCleanup(TYPE_CHANNEL, chan); + chan->doUnhookExtensions(items); + const UserMembList* users = chan->GetUsers(); for(UserMembCIter mi = users->begin(); mi != users->end(); mi++) mi->second->doUnhookExtensions(items); } - for (user_hash::iterator u = ServerInstance->Users->clientlist->begin(); u != ServerInstance->Users->clientlist->end(); u++) + for (user_hash::iterator u = ServerInstance->Users->clientlist->begin(); u != ServerInstance->Users->clientlist->end(); ) { - mod->OnCleanup(TYPE_USER,u->second); - u->second->doUnhookExtensions(items); + User* user = u->second; + // The module may quit the user (e.g. SSL mod unloading) and that will remove it from the container + ++u; + mod->OnCleanup(TYPE_USER, user); + user->doUnhookExtensions(items); } for(char m='A'; m <= 'z'; m++) { 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 diff --git a/src/socket.cpp b/src/socket.cpp index 9ec7544f2..4ebed1ccd 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -262,35 +262,41 @@ bool irc::sockets::sockaddrs::operator==(const irc::sockets::sockaddrs& other) c static void sa2cidr(irc::sockets::cidr_mask& cidr, const irc::sockets::sockaddrs& sa, int range) { const unsigned char* base; + unsigned char target_byte; cidr.type = sa.sa.sa_family; + + memset(cidr.bits, 0, sizeof(cidr.bits)); + if (cidr.type == AF_INET) { + target_byte = sizeof(sa.in4.sin_addr); base = (unsigned char*)&sa.in4.sin_addr; if (range > 32) range = 32; } else if (cidr.type == AF_INET6) { + target_byte = sizeof(sa.in6.sin6_addr); base = (unsigned char*)&sa.in6.sin6_addr; if (range > 128) range = 128; } else { - base = (unsigned char*)""; - range = 0; + cidr.length = 0; + return; } cidr.length = range; unsigned int border = range / 8; unsigned int bitmask = (0xFF00 >> (range & 7)) & 0xFF; - for(unsigned int i=0; i < 16; i++) + for(unsigned int i=0; i < target_byte; i++) { if (i < border) cidr.bits[i] = base[i]; else if (i == border) cidr.bits[i] = base[i] & bitmask; else - cidr.bits[i] = 0; + return; } } diff --git a/src/users.cpp b/src/users.cpp index eff72033d..dab3aad6c 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -761,7 +761,7 @@ const std::string& User::GetIPString() irc::sockets::satoap(client_sa, cachedip, port); /* IP addresses starting with a : on irc are a Bad Thing (tm) */ if (cachedip[0] == ':') - cachedip.insert(0,1,'0'); + cachedip.insert(cachedip.begin(),1,'0'); } return cachedip; |