]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Merge tag 'v2.0.25' into master.
authorPeter Powell <petpow@saberuk.com>
Sun, 12 Nov 2017 17:33:21 +0000 (17:33 +0000)
committerPeter Powell <petpow@saberuk.com>
Sun, 12 Nov 2017 17:33:21 +0000 (17:33 +0000)
14 files changed:
1  2 
docs/conf/inspircd.conf.example
docs/conf/links.conf.example
docs/conf/modules.conf.example
docs/conf/modules/charybdis.conf.example
docs/conf/modules/unrealircd.conf.example
include/command_parse.h
modulemanager
src/coremods/core_oper/cmd_restart.cpp
src/modules/extra/m_mysql.cpp
src/modules/m_cap.cpp
src/modules/m_shun.cpp
src/modules/m_spanningtree/main.h
src/modules/m_timedbans.cpp
src/users.cpp

index b9fa6d3a91e3215c461b60b7d49bdf699acbf5cc,8ec6616bd5dd82d68afb8819286f5a5c4d2cd2a9..61d1a8c122194e5d5380eafddf550ace06cb06f2
  # Logging is covered with the <log> tag, which you may use to change
  # the behaviour of the logging of the IRCd.
  #
- # In InspIRCd as of 1.2, logging is pluggable and very extensible.
- # Different files can log the same thing, different 'types' of log can
- # go to different places, and modules can even extend the log tag
- # to do what they want.
- #
  # An example log tag would be:
 -#  <log method="file" type="OPER" level="default" target="logs/opers.log">
 +#  <log method="file" type="OPER" level="default" target="opers.log">
  # which would log all information on /oper (failed and successful) to
  # a file called opers.log.
  #
index f3c0807f81a29412da7f7f64768e74b1fde929e5,ba18c5325205ff46150a2f80709f74e1c46f060d..e11c4fe32a9ed2875d888d786235be4162aa0d71
@@@ -48,9 -46,9 +48,9 @@@
        ssl="gnutls"
  
        # fingerprint: If defined, this option will force servers to be
 -      # authenticated using SSL Fingerprints. See https://wiki.inspircd.org/SSL
 -      # for more information. This will require an SSL link for both inbound
 -      # and outbound connections.
 +      # authenticated using SSL certificate fingerprints. See
-       # http://wiki.inspircd.org/SSL for more information. This will
++      # https://wiki.inspircd.org/SSL for more information. This will
 +      # require an SSL link for both inbound and outbound connections.
        #fingerprint=""
  
        # bind: Local IP address to bind to.
index 5382eb354ca9bc4377389eb2250c3cd1a189ecba,b672367f967e93bc85906f093e55361ad548a251..cf79dafce3b538f5fd8d9a667e5bfaa7b6cb7739
@@@ -10,7 -10,7 +10,7 @@@
  #                                                                     #
  #  By default, ALL modules are commented out. You must uncomment them #
  #  or add lines to your config to load modules. Please refer to       #
- #  http://wiki.inspircd.org/Modules for a list of modules and         #
 -#  https://wiki.inspircd.org/2.0/Modules for a list of modules and    #
++#  https://wiki.inspircd.org/3.0/Modules for a list of modules and    #
  #  each modules link for any additional conf tags they require.       #
  #                                                                     #
  #    ____                _   _____ _     _       ____  _ _   _        #
  #
  #-#-#-#-#-#-#-#-#-#-#-  CENSOR  CONFIGURATION  -#-#-#-#-#-#-#-#-#-#-#-#
  #                                                                     #
 -# Optional - If you specify to use the m_censor module, then you must #
 +# Optional - If you specify to use the censor module, then you must   #
  # specify some censor tags. See also:                                 #
- # http://wiki.inspircd.org/Modules/censor                             #
 -# https://wiki.inspircd.org/Modules/2.0/censor                        #
++# https://wiki.inspircd.org/Modules/3.0/censor                        #
  #
 -#<include file="conf/examples/censor.conf.example">
 +#<include file="examples/censor.conf.example">
  
  #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
 -# CGI:IRC module: Adds support for automatic host changing in CGI:IRC
 -# (http://cgiirc.sourceforge.net).
 -#<module name="m_cgiirc.so">
 +# CGI:IRC module: Enables forwarding the real IP address of a user from
 +# a gateway to the IRC server.
 +#<module name="cgiirc">
  #
  #-#-#-#-#-#-#-#-#-#-#-# CGIIRC  CONFIGURATION #-#-#-#-#-#-#-#-#-#-#-#-#
  #
  #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
  # DNS blacklist module: Provides support for looking up IPs on one or #
  # more blacklists.                                                    #
 -#<module name="m_dnsbl.so">                                           #
 +#<module name="dnsbl">                                                #
  #                                                                     #
 -# For configuration options please see the wiki page for m_dnsbl at   #
 -# https://wiki.inspircd.org/Modules/2.0/dnsbl                         #
 +# For configuration options please see the wiki page for dnsbl at     #
- # http://wiki.inspircd.org/Modules/dnsbl                              #
++# https://wiki.inspircd.org/Modules/3.0/dnsbl                         #
  
  #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
  # Exempt channel operators module: Provides support for allowing      #
  #
  #-#-#-#-#-#-#-#-#-#-#-  HOSTCHANGE  CONFIGURATION  -#-#-#-#-#-#-#-#-#-#
  #                                                                     #
- # See http://wiki.inspircd.org/Modules/hostchange for help.           #
 -# See https://wiki.inspircd.org/Modules/2.0/hostchange for help.      #
++# See https://wiki.inspircd.org/Modules/3.0/hostchange for help.      #
  #                                                                     #
  #<host suffix="invalid.org" separator="." prefix="">
  #<hostchange mask="*@42.theanswer.example.org" action="addnick">
  #
  # Further information on these extensions can be found at the IRCv3
  # working group website:
- # http://ircv3.org/extensions/
+ # http://ircv3.net/irc/
  #
 -#<module name="m_ircv3.so">
 +#<module name="ircv3">
  # The following block can be used to control which extensions are
 -# enabled. Note that extended-join can be incompatible with m_delayjoin
 +# enabled. Note that extended-join can be incompatible with delayjoin
  # and host cycling.
  #<ircv3 accountnotify="on" awaynotify="on" extendedjoin="on">
  
  #
  #-#-#-#-#-#-#-#-#-#-#-#- SQL CONFIGURATION   -#-#-#-#-#-#-#-#-#-#-#-#-#
  #                                                                     #
 -# m_mysql.so is more complex than described here, see the wiki for    #
 -# more: https://wiki.inspircd.org/Modules/2.0/mysql                   #
 +# mysql is more complex than described here, see the wiki for more    #
- # info: http://wiki.inspircd.org/Modules/mysql                        #
++# info: https://wiki.inspircd.org/Modules/3.0/mysql                   #
  #
  #<database module="mysql" name="mydb" user="myuser" pass="mypass" host="localhost" id="my_database2">
  
  #
  #-#-#-#-#-#-#-#-#-#-#-#- SQL CONFIGURATION   -#-#-#-#-#-#-#-#-#-#-#-#-#
  #                                                                     #
- # pgsql is more complex than described here, see the wiki for    #
- # more: http://wiki.inspircd.org/Modules/pgsql                        #
 -# m_pgsql.so is more complex than described here, see the wiki for    #
 -# more: https://wiki.inspircd.org/Modules/2.0/pgsql                   #
++# pgsql is more complex than described here, see the wiki for         #
++# more: https://wiki.inspircd.org/Modules/3.0/pgsql                   #
  #
  #<database module="pgsql" name="mydb" user="myuser" pass="mypass" host="localhost" id="my_database" ssl="no">
  
  
  #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
  # SASL authentication module: Provides support for IRC Authentication
 -# Layer via AUTHENTICATE. Note: You also need to have m_cap.so loaded
 +# Layer via AUTHENTICATE. Note: You also need to have cap loaded
  # for SASL to work.
 -#<module name="m_sasl.so">
 +#<module name="sasl">
+ # Define the following to your services server name to improve security
+ # by ensuring the SASL messages are only sent to the services server
+ # and not to all connected servers. This prevents a rogue server from
 -# capturing SASL messages.
++# capturing SASL messages and disables the SASL cap when services is
++# down.
+ #<sasl target="services.mynetwork.com">
  
  #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
  # Secure list module: Prevent /LIST in the first minute of connection,
  #
  #-#-#-#-#-#-#-#-#-#-#-  GNUTLS CONFIGURATION   -#-#-#-#-#-#-#-#-#-#-#-#
  #                                                                     #
 -# m_ssl_gnutls.so is too complex to describe here, see the wiki:      #
 -# https://wiki.inspircd.org/Modules/2.0/ssl_gnutls                    #
 +# ssl_gnutls is too complex to describe here, see the wiki:           #
- # http://wiki.inspircd.org/Modules/ssl_gnutls                         #
++# https://wiki.inspircd.org/Modules/3.0/ssl_gnutls                    #
  
  #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
  # SSL info module: Allows users to retrieve information about other
  #
  #-#-#-#-#-#-#-#-#-#-#- OPENSSL CONFIGURATION   -#-#-#-#-#-#-#-#-#-#-#-#
  #                                                                     #
 -# m_ssl_openssl.so is too complex to describe here, see the wiki:     #
 -# https://wiki.inspircd.org/Modules/2.0/ssl_openssl                   #
 +# ssl_openssl is too complex to describe here, see the wiki:          #
- # http://wiki.inspircd.org/Modules/ssl_openssl                        #
++# https://wiki.inspircd.org/Modules/3.0/ssl_openssl                   #
  
  #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
 -# Strip color module: Adds channel mode +S that strips mIRC color
 -# codes from all messages sent to the channel.
 -#<module name="m_stripcolor.so">
 +# Strip color module: Adds channel mode +S that strips color codes and
 +# all control codes except CTCP from all messages sent to the channel.
 +#<module name="stripcolor">
  
  #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
  # Silence module: Adds support for the /SILENCE command, which allows
  #
  #-#-#-#-#-#-#-#-#-#-#-#- SQL CONFIGURATION   -#-#-#-#-#-#-#-#-#-#-#-#-#
  #                                                                     #
 -# m_sqlite.so is more complex than described here, see the wiki for   #
 -# more: https://wiki.inspircd.org/Modules/2.0/sqlite3                 #
 +# sqlite is more complex than described here, see the wiki for more   #
- # info: http://wiki.inspircd.org/Modules/sqlite3                      #
++# info: https://wiki.inspircd.org/Modules/3.0/sqlite3                 #
  #
  #<database module="sqlite" hostname="/full/path/to/database.db" id="anytext">
  
  #
  #-#-#-#-#-#-#-#-#-#-#- SQLAUTH CONFIGURATION   -#-#-#-#-#-#-#-#-#-#-#-#
  #                                                                     #
 -# m_sqlauth.so is too complex to describe here, see the wiki:         #
 -# https://wiki.inspircd.org/Modules/2.0/sqlauth                       #
 +# sqlauth is too complex to describe here, see the wiki:              #
- # http://wiki.inspircd.org/Modules/sqlauth                            #
++# https://wiki.inspircd.org/Modules/3.0/sqlauth                       #
  
  #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
  # SQL oper module: Allows you to store oper credentials in an SQL table
  # dbid       - Database ID to use (see SQL modules).                  #
  # hash       - Hashing provider to use for password hashing.          #
  #                                                                     #
- # See also: http://wiki.inspircd.org/Modules/sqloper                  #
 -# See also: https://wiki.inspircd.org/Modules/2.0/sqloper             #
++# See also: https://wiki.inspircd.org/Modules/3.0/sqloper             #
  #                                                                     #
 -#<sqloper dbid="1" hash="md5">
 +#<sqloper dbid="1" hash="bcrypt">
 +
 +#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
 +# StartTLS module: Implements STARTTLS, which allows clients          #
 +# connected to non SSL enabled ports to enable SSL, if a proper SSL   #
 +# module is loaded (either ssl_gnutls or ssl_openssl).                #
 +#<module name="starttls">
  
  #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
  # SVSHold module: Implements SVSHOLD. Like Q:Lines, but can only be   #
index 6f8171b41111ecda3528f565e2de17a81b8a0730,91260c7d3133979923736996ce05c3d7d02d789a..97436c54891a0e2bebe1267bdbc55ca3c0275519
  #
  #-#-#-#-#-#-#-#-#-#-#-# CGIIRC  CONFIGURATION #-#-#-#-#-#-#-#-#-#-#-#-#
  #
 -# Optional - If you specify to use m_cgiirc, then you must specify one
 +# Optional - If you specify to use cgiirc, then you must specify one
  # or more cgihost tags which indicate authorised CGI:IRC servers which
  # will be connecting to your network, and an optional cgiirc tag.
- # For more information see: http://wiki.inspircd.org/Modules/cgiirc
 -# For more information see: https://wiki.inspircd.org/Modules/2.0/cgiirc
++# For more information see: https://wiki.inspircd.org/Modules/3.0/cgiirc
  #
  # Set to yes if you want to notice opers when CGI clients connect
  # <cgiirc opernotice="no">
  #
  #-#-#-#-#-#-#-#-#-#-#-  GNUTLS CONFIGURATION   -#-#-#-#-#-#-#-#-#-#-#-#
  #                                                                     #
 -# m_ssl_gnutls.so is too complex to describe here, see the wiki:      #
 -# https://wiki.inspircd.org/Modules/2.0/ssl_gnutls                    #
 +# ssl_gnutls is too complex to describe here, see the wiki:           #
- # http://wiki.inspircd.org/Modules/ssl_gnutls                         #
++# https://wiki.inspircd.org/Modules/3.0/ssl_gnutls                    #
  
  #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
  # SSL Info module: Allows users to retrieve information about other
  #
  #-#-#-#-#-#-#-#-#-#-#- OPENSSL CONFIGURATION   -#-#-#-#-#-#-#-#-#-#-#-#
  #                                                                     #
 -# m_ssl_openssl.so is too complex to describe here, see the wiki:     #
 -# https://wiki.inspircd.org/Modules/2.0/ssl_openssl                   #
 +# ssl_openssl is too complex to describe here, see the wiki:          #
- # http://wiki.inspircd.org/Modules/ssl_openssl                        #
++# https://wiki.inspircd.org/Modules/3.0/ssl_openssl                   #
  
 -<module name="m_stripcolor.so">
 -<module name="m_svshold.so">
 -<module name="m_tline.so">
 -<module name="m_uhnames.so">
 -<module name="m_watch.so">
 +<module name="stripcolor">
 +<module name="svshold">
 +<module name="tline">
 +<module name="uhnames">
 +<module name="watch">
  <watch maxentries="32">
 -<module name="m_xline_db.so">
 +<module name="xline_db">
  
 -<module name="m_spanningtree.so">
 +<module name="spanningtree">
index 45a0ac3d6d4033aa172d170dc91af1d9bbe1b259,65d71339455709cf2ca2b430798282b11ea3312c..8ebdd2c1f6db5f137efef6db23bf7bd5580562df
  #
  #-#-#-#-#-#-#-#-#-#-#-# CGIIRC  CONFIGURATION #-#-#-#-#-#-#-#-#-#-#-#-#
  #
 -# Optional - If you specify to use m_cgiirc, then you must specify one
 +# Optional - If you specify to use cgiirc, then you must specify one
  # or more cgihost tags which indicate authorised CGI:IRC servers which
  # will be connecting to your network, and an optional cgiirc tag.
- # For more information see: http://wiki.inspircd.org/Modules/cgiirc
 -# For more information see: https://wiki.inspircd.org/Modules/2.0/cgiirc
++# For more information see: https://wiki.inspircd.org/Modules/3.0/cgiirc
  #
  # Set to yes if you want to notice opers when CGI clients connect
  # <cgiirc opernotice="no">
  #                                                                     #
  #<opermotd file="oper.motd" onoper="yes">
  
 -<module name="m_override.so">
 +<module name="override">
  #-#-#-#-#-#-#-#-#-#-#   OVERRIDE CONFIGURATION   -#-#-#-#-#-#-#-#-#-#-#
  #                                                                     #
 -# m_override.so is too complex to describe here, see the wiki:        #
 -# https://wiki.inspircd.org/Modules/2.0/override                      #
 +# The override module is too complex to describe here, see the wiki:  #
- # http://wiki.inspircd.org/Modules/override                           #
++# https://wiki.inspircd.org/Modules/3.0/override                      #
  
 -<module name="m_operlevels.so">
 -<module name="m_opermodes.so">
 -<module name="m_password_hash.so">
 -<module name="m_muteban.so">
 +<module name="operlevels">
 +<module name="opermodes">
 +<module name="password_hash">
 +<module name="muteban">
  
 -<module name="m_redirect.so">
 -<module name="m_regex_glob.so">
 +<module name="redirect">
 +<module name="regex_glob">
  
  #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
  # Regular expression provider for PCRE (Perl-Compatible Regular
  #
  #-#-#-#-#-#-#-#-#-#-#-  GNUTLS CONFIGURATION   -#-#-#-#-#-#-#-#-#-#-#-#
  #                                                                     #
 -# m_ssl_gnutls.so is too complex to describe here, see the wiki:      #
 -# https://wiki.inspircd.org/Modules/2.0/ssl_gnutls                    #
 +# ssl_gnutls is too complex to describe here, see the wiki:           #
- # http://wiki.inspircd.org/Modules/ssl_gnutls                         #
++# https://wiki.inspircd.org/Modules/3.0/ssl_gnutls                    #
  
 -<module name="m_sslinfo.so">
 +<module name="sslinfo">
  
  #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
  # OpenSSL SSL module: Adds support for SSL connections using OpenSSL,
  #
  #-#-#-#-#-#-#-#-#-#-#- OPENSSL CONFIGURATION   -#-#-#-#-#-#-#-#-#-#-#-#
  #                                                                     #
 -# m_ssl_openssl.so is too complex to describe here, see the wiki:     #
 -# https://wiki.inspircd.org/Modules/2.0/ssl_openssl                   #
 -
 -<module name="m_stripcolor.so">
 -<module name="m_svshold.so">
 -<module name="m_swhois.so">
 -<module name="m_tline.so">
 -<module name="m_uhnames.so">
 -<module name="m_userip.so">
 -<module name="m_watch.so">
 +# ssl_openssl is too complex to describe here, see the wiki:          #
- # http://wiki.inspircd.org/Modules/ssl_openssl                        #
++# https://wiki.inspircd.org/Modules/3.0/ssl_openssl                   #
 +
 +<module name="stripcolor">
 +<module name="svshold">
 +<module name="swhois">
 +<module name="tline">
 +<module name="uhnames">
 +<module name="userip">
 +<module name="watch">
  <watch maxentries="32">
  
 -<module name="m_spanningtree.so">
 +<module name="spanningtree">
index c3d67af23906c447f45fa704eb862416d02083da,f9e3a740c3012bc3e955f2b6da841600707cdde7..ec5ebba485ad1f02c82f15f559c96ff54d603024
   */
  class CoreExport CommandParser
  {
 - private:
 -      /** Process a parameter string into a list of items
 -       * @param command_p The output list of items
 -       * @param parameters The input string
 -       * @return The number of parameters parsed into command_p
 -       */
 -      int ProcessParameters(std::vector<std::string>& command_p, char* parameters);
 + public:
-       typedef TR1NS::unordered_map<std::string, Command*> CommandMap;
++      typedef TR1NS::unordered_map<std::string, Command*, irc::insensitive, irc::StrHashComp> CommandMap;
  
 + private:
        /** Process a command from a user.
         * @param user The user to parse the command for
         * @param cmd The command string to process
diff --cc modulemanager
Simple merge
index f76fd098dcef860a3634e748f496627f22a1c77c,0000000000000000000000000000000000000000..6c19329c30aac78f1e4e8c78f0f79ded3fa379d0
mode 100644,000000..100644
--- /dev/null
@@@ -1,64 -1,0 +1,64 @@@
-               /* XXX: This hack sets FD_CLOEXEC on all possible file descriptors, so they're closed if the execv() below succeeds.
 +/*
 + * InspIRCd -- Internet Relay Chat Daemon
 + *
 + *   Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
 + *   Copyright (C) 2007 Robin Burchell <robin+git@viroteck.net>
 + *
 + * This file is part of InspIRCd.  InspIRCd is free software: you can
 + * redistribute it and/or modify it under the terms of the GNU General Public
 + * License as published by the Free Software Foundation, version 2.
 + *
 + * This program is distributed in the hope that it will be useful, but WITHOUT
 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 + * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 + * details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 + */
 +
 +
 +#include "inspircd.h"
 +#include "core_oper.h"
 +
 +CommandRestart::CommandRestart(Module* parent)
 +      : Command(parent, "RESTART", 1, 1)
 +{
 +      flags_needed = 'o';
 +      syntax = "<server>";
 +}
 +
 +CmdResult CommandRestart::Handle (const std::vector<std::string>& parameters, User *user)
 +{
 +      ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Restart: %s", user->nick.c_str());
 +      if (DieRestart::CheckPass(user, parameters[0], "restartpass"))
 +      {
 +              ServerInstance->SNO->WriteGlobalSno('a', "RESTART command from %s, restarting server.", user->GetFullRealHost().c_str());
 +
 +              DieRestart::SendError("Server restarting.");
 +
 +#ifndef _WIN32
-               execv(ServerInstance->Config->cmdline.argv[0], ServerInstance->Config->cmdline.argv);
++              /* XXX: This hack sets FD_CLOEXEC on all possible file descriptors, so they're closed if the execvp() below succeeds.
 +               * Certainly, this is not a nice way to do things and it's slow when the fd limit is high.
 +               *
 +               * A better solution would be to set the close-on-exec flag for each fd we create (or create them with O_CLOEXEC),
 +               * however there is no guarantee that third party libs will do the same.
 +               */
 +              for (int i = getdtablesize(); --i > 2;)
 +              {
 +                      int flags = fcntl(i, F_GETFD);
 +                      if (flags != -1)
 +                              fcntl(i, F_SETFD, flags | FD_CLOEXEC);
 +              }
 +#endif
 +
++              execvp(ServerInstance->Config->cmdline.argv[0], ServerInstance->Config->cmdline.argv);
 +              ServerInstance->SNO->WriteGlobalSno('a', "Failed RESTART - could not execute '%s' (%s)",
 +                      ServerInstance->Config->cmdline.argv[0], strerror(errno));
 +      }
 +      else
 +      {
 +              ServerInstance->SNO->WriteGlobalSno('a', "Failed RESTART Command from %s.", user->GetFullRealHost().c_str());
 +      }
 +      return CMD_FAILURE;
 +}
Simple merge
index 868294fe4d6fb436a2a3189231e7bfc70bae026f,ae9e824f448c61ab2b94dfe20f29c47572c2a5e0..86de15d9559f0dbebddfac1a78d4a73ddc776632
@@@ -285,146 -128,40 +285,146 @@@ class Cap::ManagerImpl : public Cap::Ma
        }
  };
  
 -class ModuleCAP : public Module
 +Cap::ExtItem::ExtItem(Module* mod)
 +      : LocalIntExt("caps", ExtensionItem::EXT_USER, mod)
  {
 -      CommandCAP cmd;
 +}
 +
 +std::string Cap::ExtItem::serialize(SerializeFormat format, const Extensible* container, void* item) const
 +{
 +      std::string ret;
 +      // XXX: Cast away the const because IS_LOCAL() doesn't handle it
 +      LocalUser* user = IS_LOCAL(const_cast<User*>(static_cast<const User*>(container)));
 +      if ((format == FORMAT_NETWORK) || (!user))
 +              return ret;
 +
 +      // List requested caps
 +      managerimpl->HandleList(ret, user, false, false);
 +
 +      // Serialize cap protocol version. If building a human-readable string append a new token, otherwise append only a single character indicating the version.
 +      Protocol protocol = managerimpl->GetProtocol(user);
 +      if (format == FORMAT_USER)
 +              ret.append("capversion=3.");
 +      else if (!ret.empty())
 +              ret.erase(ret.length()-1);
 +
 +      if (protocol == CAP_302)
 +              ret.push_back('2');
 +      else
 +              ret.push_back('1');
 +
 +      return ret;
 +}
 +
 +void Cap::ExtItem::unserialize(SerializeFormat format, Extensible* container, const std::string& value)
 +{
 +      if (format == FORMAT_NETWORK)
 +              return;
 +
 +      LocalUser* user = IS_LOCAL(static_cast<User*>(container));
 +      if (!user)
 +              return; // Can't happen
 +
 +      // Process the cap protocol version which is a single character at the end of the serialized string
 +      const char verchar = *value.rbegin();
 +      if (verchar == '2')
 +              managerimpl->Set302Protocol(user);
 +
 +      // Remove the version indicator from the string passed to HandleReq
 +      std::string caplist(value, 0, value.size()-1);
 +      managerimpl->HandleReq(user, caplist);
 +}
 +
 +class CommandCap : public SplitCommand
 +{
 +      Events::ModuleEventProvider evprov;
 +      Cap::ManagerImpl manager;
 +
 +      static void DisplayResult(LocalUser* user, std::string& result)
 +      {
 +              if (*result.rbegin() == ' ')
 +                      result.erase(result.end()-1);
 +              user->WriteCommand("CAP", result);
 +      }
 +
   public:
 -      ModuleCAP()
 -              : cmd(this)
 +      LocalIntExt holdext;
 +
 +      CommandCap(Module* mod)
 +              : SplitCommand(mod, "CAP", 1)
 +              , evprov(mod, "event/cap")
 +              , manager(mod, evprov)
 +              , holdext("cap_hold", ExtensionItem::EXT_USER, mod)
        {
 +              works_before_reg = true;
        }
  
 -      void init()
 +      CmdResult HandleLocal(const std::vector<std::string>& parameters, LocalUser* user) CXX11_OVERRIDE
        {
 -              ServerInstance->Modules->AddService(cmd);
 -              ServerInstance->Modules->AddService(cmd.reghold);
 +              if (user->registered != REG_ALL)
 +                      holdext.set(user, 1);
 +
 +              std::string subcommand(parameters[0].length(), ' ');
 +              std::transform(parameters[0].begin(), parameters[0].end(), subcommand.begin(), ::toupper);
 +
 +              if (subcommand == "REQ")
 +              {
 +                      if (parameters.size() < 2)
 +                              return CMD_FAILURE;
 +
 +                      std::string result = (manager.HandleReq(user, parameters[1]) ? "ACK :" : "NAK :");
 +                      result.append(parameters[1]);
 +                      user->WriteCommand("CAP", result);
 +              }
 +              else if (subcommand == "END")
 +              {
 +                      holdext.unset(user);
 +              }
 +              else if ((subcommand == "LS") || (subcommand == "LIST"))
 +              {
 +                      const bool is_ls = (subcommand.length() == 2);
 +                      if ((is_ls) && (parameters.size() > 1) && (parameters[1] == "302"))
 +                              manager.Set302Protocol(user);
  
 -              Implementation eventlist[] = { I_OnCheckReady };
 -              ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
 +                      std::string result = subcommand + " :";
 +                      // Show values only if supports v3.2 and doing LS
 +                      manager.HandleList(result, user, is_ls, ((is_ls) && (manager.GetProtocol(user) != Cap::CAP_LEGACY)));
 +                      DisplayResult(user, result);
 +              }
 +              else if ((subcommand == "CLEAR") && (manager.GetProtocol(user) == Cap::CAP_LEGACY))
 +              {
 +                      std::string result = "ACK :";
 +                      manager.HandleClear(user, result);
 +                      DisplayResult(user, result);
 +              }
 +              else
 +              {
-                       user->WriteNumeric(ERR_INVALIDCAPSUBCOMMAND, subcommand, "Invalid CAP subcommand");
++                      user->WriteNumeric(ERR_INVALIDCAPSUBCOMMAND, subcommand.empty() ? "*" : subcommand, "Invalid CAP subcommand");
 +                      return CMD_FAILURE;
 +              }
 +
 +              return CMD_SUCCESS;
        }
 +};
  
 -      ModResult OnCheckReady(LocalUser* user)
 -      {
 -              /* Users in CAP state get held until CAP END */
 -              if (cmd.reghold.get(user))
 -                      return MOD_RES_DENY;
 +class ModuleCap : public Module
 +{
 +      CommandCap cmd;
  
 -              return MOD_RES_PASSTHRU;
 + public:
 +      ModuleCap()
 +              : cmd(this)
 +      {
        }
  
 -      ~ModuleCAP()
 +      ModResult OnCheckReady(LocalUser* user) CXX11_OVERRIDE
        {
 +              return (cmd.holdext.get(user) ? MOD_RES_DENY : MOD_RES_PASSTHRU);
        }
  
 -      Version GetVersion()
 +      Version GetVersion() CXX11_OVERRIDE
        {
 -              return Version("Client CAP extension support", VF_VENDOR);
 +              return Version("Provides support for CAP capability negotiation", VF_VENDOR);
        }
  };
  
index 417d67b69fd1df260358c8e50417d814b3091719,3147d5476f40eda1f19775a88654b27b777a1831..66cc7fd58dc488e2a4585d57d76ffa9675bc1ac0
@@@ -106,13 -114,17 +106,17 @@@ class CommandShun : public Comman
  
                if (parameters.size() == 1)
                {
-                       if (ServerInstance->XLines->DelLine(target.c_str(), "SHUN", user))
+                       if (ServerInstance->XLines->DelLine(parameters[0].c_str(), "SHUN", user))
                        {
-                               ServerInstance->SNO->WriteToSnoMask('x',"%s removed SHUN on %s",user->nick.c_str(),target.c_str());
+                               ServerInstance->SNO->WriteToSnoMask('x', "%s removed SHUN on %s", user->nick.c_str(), parameters[0].c_str());
+                       }
+                       else if (ServerInstance->XLines->DelLine(target.c_str(), "SHUN", user))
+                       {
 -                              ServerInstance->SNO->WriteToSnoMask('x',"%s removed SHUN on %s",user->nick.c_str(),target.c_str());
++                              ServerInstance->SNO->WriteToSnoMask('x',"%s removed SHUN on %s", user->nick.c_str(), target.c_str());
                        }
                        else
                        {
-                               user->WriteNotice("*** Shun " + target + " not found in list, try /stats H.");
 -                              user->WriteServ("NOTICE %s :*** Shun %s not found in list, try /stats H.", user->nick.c_str(), parameters[0].c_str());
++                              user->WriteNotice("*** Shun " + parameters[0] + " not found in list, try /stats H.");
                                return CMD_FAILURE;
                        }
                }
Simple merge
index 9890800e4c524f4222080cedc30474e85c0455af,bbbc518bdd1b7a7947464c43b83a8942ea2c7d2f..8c1454d7ed2a0fba80809aefa3b39e8a5357288b
@@@ -117,11 -117,13 +117,13 @@@ class CommandTban : public Comman
                T.chan = channel;
                TimedBanList.push_back(T);
  
+               const std::string addban = user->nick + " added a timed ban on " + mask + " lasting for " + ConvToStr(duration) + " seconds.";
                // If halfop is loaded, send notice to halfops and above, otherwise send to ops and above
 -              ModeHandler* mh = ServerInstance->Modes->FindMode('h', MODETYPE_CHANNEL);
 +              PrefixMode* mh = ServerInstance->Modes->FindPrefixMode('h');
                char pfxchar = (mh && mh->name == "halfop") ? mh->GetPrefix() : '@';
  
-               channel->WriteAllExcept(ServerInstance->FakeClient, true, pfxchar, tmp, "NOTICE %s :%s added a timed ban on %s lasting for %ld seconds.", channel->name.c_str(), user->nick.c_str(), mask.c_str(), duration);
+               channel->WriteAllExcept(ServerInstance->FakeClient, true, pfxchar, tmp, "NOTICE %s :%s", channel->name.c_str(), addban.c_str());
+               ServerInstance->PI->SendChannelNotice(channel, pfxchar, addban);
                return CMD_SUCCESS;
        }
  
@@@ -203,17 -198,26 +205,21 @@@ class ModuleTimedBans : public Modul
  
                for (timedbans::iterator i = expired.begin(); i != expired.end(); i++)
                {
 -                      std::string chan = i->channel;
                        std::string mask = i->mask;
 -                      Channel* cr = ServerInstance->FindChan(chan);
 -                      if (cr)
 +                      Channel* cr = i->chan;
                        {
 -                              std::vector<std::string> setban;
 -                              setban.push_back(chan);
 -                              setban.push_back("-b");
 -                              setban.push_back(mask);
 -
                                CUList empty;
-                               std::string expiry = "*** Timed ban on " + cr->name + " expired.";
-                               cr->WriteAllExcept(ServerInstance->FakeClient, true, '@', empty, "NOTICE %s :%s", cr->name.c_str(), expiry.c_str());
-                               ServerInstance->PI->SendChannelNotice(cr, '@', expiry);
 -                              const std::string expiry = "*** Timed ban on " + chan + " expired.";
++                              const std::string expiry = "*** Timed ban on " + cr->name + " expired.";
+                               // If halfop is loaded, send notice to halfops and above, otherwise send to ops and above
 -                              ModeHandler* mh = ServerInstance->Modes->FindMode('h', MODETYPE_CHANNEL);
++                              PrefixMode* mh = ServerInstance->Modes->FindPrefixMode('h');
+                               char pfxchar = (mh && mh->name == "halfop") ? mh->GetPrefix() : '@';
+                               cr->WriteAllExcept(ServerInstance->FakeClient, true, pfxchar, empty, "NOTICE %s :%s", cr->name.c_str(), expiry.c_str());
+                               ServerInstance->PI->SendChannelNotice(cr, pfxchar, expiry);
  
 -                              ServerInstance->SendGlobalMode(setban, ServerInstance->FakeClient);
 +                              Modes::ChangeList setban;
 +                              setban.push_remove(ServerInstance->Modes->FindMode('b', MODETYPE_CHANNEL), mask);
 +                              ServerInstance->Modes->Process(ServerInstance->FakeClient, cr, NULL, setban);
                        }
                }
        }
diff --cc src/users.cpp
Simple merge