diff options
94 files changed, 763 insertions, 547 deletions
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..6fdf33bba --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,40 @@ +<!-- +--------------------------------------------------- +GENERAL SUPPORT INFORMATION +--------------------------------------------------- + +The GitHub issue tracker is for bug reports and feature requests. +General support can be found at the following locations: + +IRC: +irc.inspircd.org #inspircd + +Example configs: +2.0 - https://github.com/inspircd/inspircd/tree/insp20/docs/conf +3.0 (alpha) - https://github.com/inspircd/inspircd/tree/master/docs/conf + +Wiki: +https://wiki.inspircd.org/ +--> + +**Description** + +<!-- +Briefly describe the problem you are having in a few paragraphs. +--> + +**Steps to reproduce the issue:** +1. +2. +3. + +**Describe the results you received:** + + +**Describe the results you expected:** + + +**Additional information you deem important (e.g. issue happens only occasionally):** + +**Output of `./bin/inspircd --version`:** + diff --git a/.gitignore b/.gitignore index 3aea64f53..e9d91b29b 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,7 @@ !.git* /.configure -/BSDmakefile +/Makefile /GNUmakefile /build /docs/doxygen @@ -3,6 +3,7 @@ # # InspIRCd -- Internet Relay Chat Daemon # +# Copyright (C) 2012-2017 Peter Powell <petpow@saberuk.com> # Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org> # Copyright (C) 2007, 2009 Dennis Friis <peavey@inspircd.org> # Copyright (C) 2003, 2006-2008 Craig Edwards <craigedwards@brainbox.cc> @@ -129,9 +130,9 @@ our $interactive = !( my %version = get_version $opt_distribution_label; print_format "<|BOLD Configuring InspIRCd $version{FULL} on $^O.|>\n"; -our %config; +my %config; if ($interactive) { - %config = read_configure_cache(); + %config = read_config_file(CONFIGURE_CACHE_FILE); run_test CONFIGURE_CACHE_FILE, %config; if (!defined $config{VERSION}) { $config{VERSION} = CONFIGURE_CACHE_VERSION; @@ -158,41 +159,22 @@ my %compiler = get_compiler_info($config{CXX}); $config{HAS_CLOCK_GETTIME} = run_test 'clock_gettime()', test_file($config{CXX}, 'clock_gettime.cpp', $^O eq 'darwin' ? undef : '-lrt'); $config{HAS_EVENTFD} = run_test 'eventfd()', test_file($config{CXX}, 'eventfd.cpp'); -if ($config{HAS_EPOLL} = run_test 'epoll', test_header($config{CXX}, 'sys/epoll.h')) { - $config{SOCKETENGINE} //= 'epoll'; -} - -if ($config{HAS_KQUEUE} = run_test 'kqueue', test_file($config{CXX}, 'kqueue.cpp')) { - $config{SOCKETENGINE} //= 'kqueue'; -} - -if ($config{HAS_PORTS} = run_test 'Solaris IOCP', test_header($config{CXX}, 'port.h')) { - $config{SOCKETENGINE} //= 'ports'; -} - -if ($config{HAS_POLL} = run_test 'poll', test_header($config{CXX}, 'poll.h')) { - $config{SOCKETENGINE} //= 'poll'; -} - -# Select is available on all platforms -$config{HAS_SELECT} = 1; -$config{SOCKETENGINE} //= 'select'; +my @socketengines; +push @socketengines, 'epoll' if run_test 'epoll', test_header $config{CXX}, 'sys/epoll.h'; +push @socketengines, 'kqueue' if run_test 'kqueue', test_file $config{CXX}, 'kqueue.cpp'; +push @socketengines, 'ports' if run_test 'Solaris IOCP', test_header $config{CXX}, 'port.h'; +push @socketengines, 'poll' if run_test 'poll', test_header $config{CXX}, 'poll.h'; +push @socketengines, 'select'; if (defined $opt_socketengine) { - my $cfgkey = 'HAS_' . uc $opt_socketengine; - if ($config{$cfgkey} && -f "src/socketengines/socketengine_$opt_socketengine.cpp") { - $config{SOCKETENGINE} = $opt_socketengine; - } else { - print "Unable to use a socket engine which is not supported on this platform ($opt_socketengine)!\n"; - print "Available socket engines are:"; - foreach (<src/socketengines/socketengine_*.cpp>) { - s/src\/socketengines\/socketengine_(\w+)\.cpp/$1/; - print " $1" if $config{'HAS_' . uc $1}; - } - print "\n"; - exit 1; + unless (grep { $_ eq $opt_socketengine } @socketengines) { + my $reason = -f "src/socketengines/socketengine_$opt_socketengine.cpp" ? 'is not available on this platform' : 'does not exist'; + print_error "The socket engine you requested ($opt_socketengine) $reason!", + 'Available socket engines are:', + map { " * $_" } @socketengines; } } +$config{SOCKETENGINE} = $opt_socketengine // $socketengines[0]; if (defined $opt_system) { $config{BASE_DIR} = $opt_prefix // '/var/lib/inspircd'; @@ -239,6 +221,15 @@ $config{UID} = $user[2]; # Clear the screen. system 'tput', 'clear' if $interactive; +# Warn the user about clock drifting when running on OpenVZ. +if (-e '/proc/user_beancounters' || -e '/proc/vz/vzaquota') { + print_warning <<'EOW'; +You are building InspIRCd inside of an an OpenVZ container. If you +plan to use InspIRCd in this container then you should make sure that NTP is +configured on the Hardware Node. Failure to do so may result in clock drifting! +EOW +} + # Check that the user actually wants this version. if ($version{LABEL} ne 'release') { print_warning <<'EOW'; diff --git a/docs/Doxyfile b/docs/Doxyfile index 807020af5..f4e526bc7 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -1,6 +1,6 @@ DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = InspIRCd -PROJECT_NUMBER = 2.0 +PROJECT_NUMBER = 3.0 PROJECT_BRIEF = PROJECT_LOGO = OUTPUT_DIRECTORY = docs/doxygen diff --git a/docs/conf/modules.conf.example b/docs/conf/modules.conf.example index 835e31795..93e26059c 100644 --- a/docs/conf/modules.conf.example +++ b/docs/conf/modules.conf.example @@ -1059,7 +1059,8 @@ # allowpattern="Guest* Bot*" # # killreason="Access denied" # # verbose="yes" # -# host="$uid.$ou.inspircd.org"> # +# host="$uid.$ou.inspircd.org" # +# useusername="no"> # # # # <ldapwhitelist cidr="10.42.0.0/16"> # # # @@ -1076,6 +1077,10 @@ # regardless of if they have an account, for example guest and bot # # users. # # # +# The useusername setting chooses whether the user's username or # +# nickname is used when locating a user account, if a username isn't # +# provided in PASS. # +# # # Killreason indicates the QUIT reason to give to users if they fail # # to authenticate. # # # @@ -1434,7 +1439,6 @@ #<include file="permchannels.conf"> # # You may also create channels on startup by using the <permchannels> block. -# Don't forget to set them +P in the modes, or they won't stay permanent. #<permchannels channel="#opers" modes="isP" topic="Opers only."> #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# @@ -1683,13 +1687,12 @@ # #-#-#-#-#-#-#-#-#-# SECURELIST CONFIGURATION -#-#-#-#-#-#-#-#-#-#-#-#-# # # -# Securelist can be harmful to some IRC search engines such as # -# netsplit.de and searchirc.com. To prevent securelist blocking these # -# sites from listing, define exception tags as shown below: # -#<securehost exception="*@*.searchirc.org"> +# Securelist can be harmful to some IRC search engines. To prevent # +# securelist blocking these sites from listing, define exception tags # +# as shown below: # #<securehost exception="*@*.netsplit.de"> -#<securehost exception="*@echo940.server4you.de"> #<securehost exception="*@*.ircdriven.com"> +#<securehost exception="*@*.irc-source.com"> # # # Define the following variable to change how long a user must wait # # before issuing a LIST. If not defined, defaults to 60 seconds. # @@ -1827,7 +1830,8 @@ # SSL channel mode module: Adds support for SSL-only channels via # channel mode +z and the 'z' extban which matches SSL client # certificate fingerprints. -# Does not do anything useful without a working SSL module (see below). +# Does not do anything useful without a working SSL module and the +# sslinfo module (see below). #<module name="sslmodes"> #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# diff --git a/docs/conf/services/atheme.conf.example b/docs/conf/services/atheme.conf.example index dae1dfce2..037087998 100644 --- a/docs/conf/services/atheme.conf.example +++ b/docs/conf/services/atheme.conf.example @@ -11,7 +11,7 @@ <alias text="GLOBAL" replace="PRIVMSG $requirement :$2-" requires="Global" uline="yes" operonly="yes"> <alias text="GROUPSERV" replace="PRIVMSG $requirement :$2-" requires="GroupServ" uline="yes"> <alias text="HELPSERV" replace="PRIVMSG $requirement :$2-" requires="HelpServ" uline="yes"> -<alias text="INFOSERV" replace="PRIVMSG $requirement :$2-" requires="GroupServ" uline="yes"> +<alias text="INFOSERV" replace="PRIVMSG $requirement :$2-" requires="InfoServ" uline="yes"> <alias text="PROXYSCAN" replace="PRIVMSG $requirement :$2-" requires="Proxyscan" uline="yes" operonly="yes"> <alias text="RPGSERV" replace="PRIVMSG $requirement :$2-" requires="RPGServ" uline="yes"> diff --git a/include/base.h b/include/base.h index c378afc1c..d8781f796 100644 --- a/include/base.h +++ b/include/base.h @@ -202,7 +202,7 @@ class CoreExport CoreException : public std::exception * Actually no, it does nothing. Never mind. * @throws Nothing! */ - virtual ~CoreException() throw() {}; + virtual ~CoreException() throw() {} /** Returns the reason for the exception. * @return Human readable description of the error */ diff --git a/include/builtinmodes.h b/include/builtinmodes.h index a77734ae3..bfb46823f 100644 --- a/include/builtinmodes.h +++ b/include/builtinmodes.h @@ -97,8 +97,8 @@ class ModeUserServerNoticeMask : public ModeHandler public: ModeUserServerNoticeMask(); - ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding); - void OnParameterMissing(User* user, User* dest, Channel* channel); + ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding) CXX11_OVERRIDE; + void OnParameterMissing(User* user, User* dest, Channel* channel) CXX11_OVERRIDE; /** Create a displayable mode string of the snomasks set on a given user * @param user The user whose notice masks to format diff --git a/include/configparser.h b/include/configparser.h index 02619e759..c9790c59f 100644 --- a/include/configparser.h +++ b/include/configparser.h @@ -41,7 +41,7 @@ enum ParseFlags struct ParseStack { std::vector<std::string> reading; - insp::flat_map<std::string, std::string> vars; + insp::flat_map<std::string, std::string, irc::insensitive_swo> vars; ConfigDataHash& output; ConfigFileCache& FilesOutput; std::stringstream& errstr; diff --git a/include/configreader.h b/include/configreader.h index 005d4a37d..4d70d8510 100644 --- a/include/configreader.h +++ b/include/configreader.h @@ -35,7 +35,7 @@ /** Structure representing a single \<tag> in config */ class CoreExport ConfigTag : public refcountbase { - std::vector<KeyVal> items; + ConfigItems items; public: const std::string tag; const std::string src_name; @@ -80,10 +80,10 @@ class CoreExport ConfigTag : public refcountbase std::string getTagLocation(); - inline const std::vector<KeyVal>& getItems() const { return items; } + inline const ConfigItems& 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); + /** Create a new ConfigTag, giving access to the private ConfigItems item list */ + static ConfigTag* create(const std::string& Tag, const std::string& file, int line, ConfigItems*& Items); private: ConfigTag(const std::string& Tag, const std::string& file, int line); }; diff --git a/include/extensible.h b/include/extensible.h index 07756fb59..1da45cee6 100644 --- a/include/extensible.h +++ b/include/extensible.h @@ -111,7 +111,7 @@ class CoreExport Extensible : public classbase inline const ExtensibleStore& GetExtList() const { return extensions; } Extensible(); - virtual CullResult cull(); + virtual CullResult cull() CXX11_OVERRIDE; virtual ~Extensible(); void doUnhookExtensions(const std::vector<reference<ExtensionItem> >& toRemove); diff --git a/include/inspsocket.h b/include/inspsocket.h index 751374fdf..95f29ff11 100644 --- a/include/inspsocket.h +++ b/include/inspsocket.h @@ -312,7 +312,7 @@ class CoreExport StreamSocket : public EventHandler */ virtual void Close(); /** This ensures that close is called prior to destructor */ - virtual CullResult cull(); + virtual CullResult cull() CXX11_OVERRIDE; /** Get the IOHook of a module attached to this socket * @param mod Module whose IOHook to return @@ -372,7 +372,7 @@ class CoreExport BufferedSocket : public StreamSocket /** When there is data waiting to be read on a socket, the OnDataReady() * method is called. */ - virtual void OnDataReady() = 0; + virtual void OnDataReady() CXX11_OVERRIDE = 0; /** * When an outbound connection fails, and the attempt times out, you diff --git a/include/listmode.h b/include/listmode.h index 94af1d524..f49c5b3c8 100644 --- a/include/listmode.h +++ b/include/listmode.h @@ -63,6 +63,9 @@ class CoreExport ListModeBase : public ModeHandler */ typedef std::vector<ListLimit> limitlist; + /** The default maximum list size. */ + static const unsigned int DEFAULT_LIST_SIZE = 64; + /** Finds the limit of modes that can be placed on the given channel name according to the config * @param channame The channel name to find the limit for * @return The maximum number of modes of this type that we allow to be set on the given channel name @@ -123,6 +126,10 @@ class CoreExport ListModeBase : public ModeHandler */ unsigned int GetLimit(Channel* channel); + /** Gets the lower list limit for this listmode. + */ + unsigned int GetLowerLimit(); + /** Retrieves the list of all modes set on the given channel * @param channel Channel to get the list from * @return A list with all modes of this type set on the given channel, can be NULL diff --git a/include/mode.h b/include/mode.h index 956b86050..2e9ed22f3 100644 --- a/include/mode.h +++ b/include/mode.h @@ -166,7 +166,7 @@ class CoreExport ModeHandler : public ServiceProvider * @param mclass The object type of this mode handler, one of ModeHandler::Class */ ModeHandler(Module* me, const std::string& name, char modeletter, ParamSpec params, ModeType type, Class mclass = MC_OTHER); - virtual CullResult cull(); + virtual CullResult cull() CXX11_OVERRIDE; virtual ~ModeHandler(); /** Register this object in the ModeParser diff --git a/include/modules.h b/include/modules.h index 5deed943a..d9d05a396 100644 --- a/include/modules.h +++ b/include/modules.h @@ -276,7 +276,7 @@ class CoreExport Module : public classbase, public usecountbase /** Clean up prior to destruction * If you override, you must call this AFTER your module's cleanup */ - virtual CullResult cull(); + virtual CullResult cull() CXX11_OVERRIDE; /** Default destructor. * destroys a module class diff --git a/include/modules/dns.h b/include/modules/dns.h index 5f2836761..61abd7144 100644 --- a/include/modules/dns.h +++ b/include/modules/dns.h @@ -33,6 +33,8 @@ namespace DNS QUERY_CNAME = 5, /* Reverse DNS lookup */ QUERY_PTR = 12, + /* TXT */ + QUERY_TXT = 16, /* IPv6 AAAA lookup */ QUERY_AAAA = 28 }; diff --git a/include/numerics.h b/include/numerics.h index 0d5537278..e1d225d31 100644 --- a/include/numerics.h +++ b/include/numerics.h @@ -46,11 +46,13 @@ enum RPL_SERVERVERSION = 4, // 2812, not 1459 RPL_ISUPPORT = 5, // not RFC, extremely common though (defined as RPL_BOUNCE in 2812, widely ignored) - RPL_MAP = 6, // unrealircd - RPL_ENDMAP = 7, // unrealircd RPL_SNOMASKIS = 8, // unrealircd RPL_REDIR = 10, + RPL_MAP = 15, // ircu + RPL_ENDMAP = 17, // ircu + RPL_MAPUSERS = 18, // insp-specific + RPL_YOURUUID = 42, // taken from ircnet RPL_UMODEIS = 221, @@ -70,8 +72,6 @@ enum RPL_LOCALUSERS = 265, RPL_GLOBALUSERS = 266, - RPL_MAPUSERS = 270, // insp-specific - RPL_AWAY = 301, RPL_USERHOST = 302, RPL_ISON = 303, diff --git a/include/socketengine.h b/include/socketengine.h index c0026bfc6..b00643952 100644 --- a/include/socketengine.h +++ b/include/socketengine.h @@ -244,11 +244,19 @@ class CoreExport SocketEngine */ Statistics() : lastempty(0), TotalEvents(0), ReadEvents(0), WriteEvents(0), ErrorEvents(0) { } - /** Increase the counters for bytes sent/received in this second. - * @param len_in Bytes received, 0 if updating number of bytes written. - * @param len_out Bytes sent, 0 if updating number of bytes read. + /** Update counters for network data received. + * This should be called after every read-type syscall. + * @param len_in Number of bytes received, or -1 for error, as typically + * returned by a read-style syscall. */ - void Update(size_t len_in, size_t len_out); + void UpdateReadCounters(int len_in); + + /** Update counters for network data sent. + * This should be called after every write-type syscall. + * @param len_out Number of bytes sent, or -1 for error, as typically + * returned by a read-style syscall. + */ + void UpdateWriteCounters(int len_out); /** Get data transfer statistics. * @param kbitspersec_in Filled with incoming traffic in this second in kbit/s. diff --git a/include/typedefs.h b/include/typedefs.h index 879ef0627..873382999 100644 --- a/include/typedefs.h +++ b/include/typedefs.h @@ -66,13 +66,13 @@ typedef std::vector<Membership*> IncludeChanList; */ typedef std::vector<std::string> file_cache; -/** A configuration key and value pair +/** A mapping of configuration keys to their assigned values. */ -typedef std::pair<std::string, std::string> KeyVal; +typedef insp::flat_map<std::string, std::string, irc::insensitive_swo> ConfigItems; /** The entire configuration */ -typedef std::multimap<std::string, reference<ConfigTag> > ConfigDataHash; +typedef std::multimap<std::string, reference<ConfigTag>, irc::insensitive_swo> ConfigDataHash; /** Iterator of ConfigDataHash */ typedef ConfigDataHash::const_iterator ConfigIter; diff --git a/include/users.h b/include/users.h index 4939feb1e..4c8df549d 100644 --- a/include/users.h +++ b/include/users.h @@ -717,7 +717,7 @@ class CoreExport User : public Extensible /** Default destructor */ virtual ~User(); - virtual CullResult cull(); + virtual CullResult cull() CXX11_OVERRIDE; }; class CoreExport UserIOHandler : public StreamSocket @@ -742,7 +742,7 @@ class CoreExport LocalUser : public User, public insp::intrusive_list_node<Local { public: LocalUser(int fd, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server); - CullResult cull(); + CullResult cull() CXX11_OVERRIDE; UserIOHandler eh; @@ -836,12 +836,12 @@ class CoreExport LocalUser : public User, public insp::intrusive_list_node<Local */ void SetClass(const std::string &explicit_name = ""); - bool SetClientIP(const char* sip, bool recheck_eline = true); + bool SetClientIP(const char* sip, bool recheck_eline = true) CXX11_OVERRIDE; - void SetClientIP(const irc::sockets::sockaddrs& sa, bool recheck_eline = true); + void SetClientIP(const irc::sockets::sockaddrs& sa, bool recheck_eline = true) CXX11_OVERRIDE; - void Write(const std::string& text); - void Write(const char*, ...) CUSTOM_PRINTF(2, 3); + void Write(const std::string& text) CXX11_OVERRIDE; + void Write(const char*, ...) CXX11_OVERRIDE CUSTOM_PRINTF(2, 3); /** Send a NOTICE message from the local server to the user. * The message will be sent even if the user is connected to a remote server. @@ -855,7 +855,7 @@ class CoreExport LocalUser : public User, public insp::intrusive_list_node<Local * @param command A command (should be all CAPS) * @return True if this user can execute the command */ - bool HasPermission(const std::string &command); + bool HasPermission(const std::string &command) CXX11_OVERRIDE; /** Returns true if a user has a given permission. * This is used to check whether or not users may perform certain actions which admins may not wish to give to @@ -865,7 +865,7 @@ class CoreExport LocalUser : public User, public insp::intrusive_list_node<Local * @param noisy If set to true, the user is notified that they do not have the specified permission where applicable. If false, no notification is sent. * @return True if this user has the permission in question. */ - bool HasPrivPermission(const std::string &privstr, bool noisy = false); + bool HasPrivPermission(const std::string &privstr, bool noisy = false) CXX11_OVERRIDE; /** Returns true or false if a user can set a privileged user or channel mode. * This is done by looking up their oper type from User::oper, then referencing @@ -873,7 +873,7 @@ class CoreExport LocalUser : public User, public insp::intrusive_list_node<Local * @param mh Mode to check * @return True if the user can set or unset this mode. */ - bool HasModePermission(const ModeHandler* mh) const; + bool HasModePermission(const ModeHandler* mh) const CXX11_OVERRIDE; /** Change nick to uuid, unset REG_NICK and send a nickname overruled numeric. * This is called when another user (either local or remote) needs the nick of this user and this user @@ -904,9 +904,9 @@ class CoreExport FakeUser : public User nick = sname; } - virtual CullResult cull(); - virtual const std::string& GetFullHost(); - virtual const std::string& GetFullRealHost(); + virtual CullResult cull() CXX11_OVERRIDE; + virtual const std::string& GetFullHost() CXX11_OVERRIDE; + virtual const std::string& GetFullRealHost() CXX11_OVERRIDE; }; /* Faster than dynamic_cast */ diff --git a/make/calcdep.pl b/make/calcdep.pl index 882e75f22..99355efa4 100755 --- a/make/calcdep.pl +++ b/make/calcdep.pl @@ -166,7 +166,7 @@ END obj/ld-extra.cmd: $core_src \@\$(SOURCEPATH)/make/unit-cc.pl gen-ld \$\@ \$^ \$> -bin/inspircd: obj/ld-extra.cmd $core_mk +bin/inspircd: $core_mk obj/ld-extra.cmd \@\$(SOURCEPATH)/make/unit-cc.pl static-ld \$\@ \$^ \$> inspircd: bin/inspircd diff --git a/make/common.pm b/make/common.pm index b1608db56..6ca280bec 100644 --- a/make/common.pm +++ b/make/common.pm @@ -1,7 +1,7 @@ # # InspIRCd -- Internet Relay Chat Daemon # -# Copyright (C) 2013-2014 Peter Powell <petpow@saberuk.com> +# Copyright (C) 2013-2017 Peter Powell <petpow@saberuk.com> # # 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 @@ -31,10 +31,13 @@ use Exporter qw(import); use File::Path qw(mkpath); use File::Spec::Functions qw(rel2abs); +use make::console; + our @EXPORT = qw(create_directory get_cpu_count get_version - module_installed); + read_config_file + write_config_file); sub create_directory($$) { my ($location, $permissions) = @_; @@ -86,12 +89,6 @@ sub get_version { return %version; } -sub module_installed($) { - my $module = shift; - eval("use $module;"); - return !$@; -} - sub get_cpu_count { my $count = 1; if ($^O =~ /bsd/) { @@ -107,4 +104,28 @@ sub get_cpu_count { return $count; } +sub read_config_file($) { + my $path = shift; + my %config; + open(my $fh, $path) or return %config; + while (my $line = <$fh>) { + next if $line =~ /^\s*($|\#)/; + my ($key, $value) = ($line =~ /^(\S+)(?:\s(.*))?$/); + $config{$key} = $value; + } + close $fh; + return %config; +} + +sub write_config_file($%) { + my $path = shift; + my %config = @_; + open(my $fh, '>', $path) or print_error "unable to write to $path: $!"; + while (my ($key, $value) = each %config) { + $value //= ''; + say $fh "$key $value"; + } + close $fh; +} + 1; diff --git a/make/configure.pm b/make/configure.pm index 59657bfc4..dfdbf5f75 100644 --- a/make/configure.pm +++ b/make/configure.pm @@ -1,7 +1,7 @@ # # InspIRCd -- Internet Relay Chat Daemon # -# Copyright (C) 2012-2014 Peter Powell <petpow@saberuk.com> +# Copyright (C) 2012-2017 Peter Powell <petpow@saberuk.com> # Copyright (C) 2008 Robin Burchell <robin+git@viroteck.net> # Copyright (C) 2007-2008 Craig Edwards <craigedwards@brainbox.cc> # Copyright (C) 2008 Thomas Stagner <aquanight@inspircd.org> @@ -52,7 +52,6 @@ our @EXPORT = qw(CONFIGURE_CACHE_FILE run_test test_file test_header - read_configure_cache write_configure_cache get_compiler_info find_compiler @@ -180,7 +179,7 @@ EOH sub cmd_update { print_error "You have not run $0 before. Please do this before trying to update the generated files." unless -f CONFIGURE_CACHE_FILE; say 'Updating...'; - my %config = read_configure_cache(); + my %config = read_config_file(CONFIGURE_CACHE_FILE); my %compiler = get_compiler_info($config{CXX}); my %version = get_version $config{DISTRIBUTION}; parse_templates(\%config, \%compiler, \%version); @@ -209,24 +208,12 @@ sub test_file($$;$) { sub test_header($$;$) { my ($compiler, $header, $args) = @_; $args //= ''; - open(COMPILER, "| $compiler -E - $args ${\CONFIGURE_ERROR_PIPE}") or return 0; - print COMPILER "#include <$header>"; - close(COMPILER); + open(my $fh, "| $compiler -E - $args ${\CONFIGURE_ERROR_PIPE}") or return 0; + print $fh "#include <$header>"; + close $fh; return !$?; } -sub read_configure_cache { - my %config; - open(CACHE, CONFIGURE_CACHE_FILE) or return %config; - while (my $line = <CACHE>) { - next if $line =~ /^\s*($|\#)/; - my ($key, $value) = ($line =~ /^(\S+)(?:\s(.*))?$/); - $config{$key} = $value; - } - close(CACHE); - return %config; -} - sub write_configure_cache(%) { unless (-e CONFIGURE_DIRECTORY) { print_format "Creating <|GREEN ${\CONFIGURE_DIRECTORY}|> ...\n"; @@ -235,29 +222,20 @@ sub write_configure_cache(%) { print_format "Writing <|GREEN ${\CONFIGURE_CACHE_FILE}|> ...\n"; my %config = @_; - open(CACHE, '>', CONFIGURE_CACHE_FILE) or print_error "unable to write ${\CONFIGURE_CACHE_FILE}: $!"; - while (my ($key, $value) = each %config) { - $value //= ''; - say CACHE "$key $value"; - } - close(CACHE); + write_config_file CONFIGURE_CACHE_FILE, %config; } sub get_compiler_info($) { my $binary = shift; - my $version = `$binary -v 2>&1`; - if ($version =~ /Apple\sLLVM\sversion\s(\d+\.\d+)/i) { - # Apple version their LLVM releases slightly differently to the mainline LLVM. - # See https://trac.macports.org/wiki/XcodeVersionInfo for more information. - return (NAME => 'AppleClang', VERSION => $1); - } elsif ($version =~ /clang\sversion\s(\d+\.\d+)/i) { - return (NAME => 'Clang', VERSION => $1); - } elsif ($version =~ /gcc\sversion\s(\d+\.\d+)/i) { - return (NAME => 'GCC', VERSION => $1); - } elsif ($version =~ /(?:icc|icpc)\sversion\s(\d+\.\d+).\d+\s\(gcc\sversion\s(\d+\.\d+).\d+/i) { - return (NAME => 'ICC', VERSION => $1); + my %info = (NAME => 'Unknown', VERSION => '0.0'); + return %info if system "$binary -o __compiler_info make/test/compiler_info.cpp ${\CONFIGURE_ERROR_PIPE}"; + open(my $fh, '-|', './__compiler_info 2>/dev/null'); + while (my $line = <$fh>) { + $info{$1} = $2 if $line =~ /^([A-Z]+)\s(.+)$/; } - return (NAME => $binary, VERSION => '0.0'); + close $fh; + unlink './__compiler_info'; + return %info; } sub find_compiler { @@ -279,11 +257,11 @@ sub parse_templates($$$) { # Iterate through files in make/template. foreach (<make/template/*>) { print_format "Parsing <|GREEN $_|> ...\n"; - open(TEMPLATE, $_) or print_error "unable to read $_: $!"; - my (@lines, $mode, @platforms, %targets); + open(my $fh, $_) or print_error "unable to read $_: $!"; + my (@lines, $mode, @platforms, @targets); # First pass: parse template variables and directives. - while (my $line = <TEMPLATE>) { + while (my $line = <$fh>) { chomp $line; # Does this line match a variable? @@ -310,11 +288,7 @@ sub parse_templates($$$) { } elsif ($1 eq 'platform') { push @platforms, $2; } elsif ($1 eq 'target') { - if ($2 =~ /(\w+)\s(.+)/) { - $targets{$1} = $2; - } else { - $targets{DEFAULT} = $2; - } + push @targets, $2 } else { print_warning "unknown template command '$1' in $_!"; push @lines, $line; @@ -323,92 +297,18 @@ sub parse_templates($$$) { } push @lines, $line; } - close(TEMPLATE); + close $fh; # Only proceed if this file should be templated on this platform. if ($#platforms < 0 || grep { $_ eq $^O } @platforms) { # Add a default target if the template has not defined one. - unless (scalar keys %targets) { - $targets{DEFAULT} = catfile(CONFIGURE_DIRECTORY, basename $_); + unless (@targets) { + push @targets, catfile(CONFIGURE_DIRECTORY, basename $_); } - # Second pass: parse makefile junk and write files. - while (my ($name, $target) = each %targets) { - - # TODO: when buildtool is done this mess can be removed completely. - my @final_lines; - foreach my $line (@lines) { - - # Are we parsing a makefile and does this line match a statement? - if ($name =~ /(?:BSD|GNU)_MAKE/ && $line =~ /^\s*\@(\w+)(?:\s+(.+))?$/) { - my @tokens = split /\s/, $2 if defined $2; - if ($1 eq 'DO_EXPORT' && defined $2) { - if ($name eq 'BSD_MAKE') { - foreach my $variable (@tokens) { - push @final_lines, "MAKEENV += $variable='\${$variable}'"; - } - } elsif ($name eq 'GNU_MAKE') { - push @final_lines, "export $2"; - } - } elsif ($1 eq 'ELSE') { - if ($name eq 'BSD_MAKE') { - push @final_lines, ".else"; - } elsif ($name eq 'GNU_MAKE') { - push @final_lines, "else"; - } - } elsif ($1 eq 'ENDIF') { - if ($name eq 'BSD_MAKE') { - push @final_lines, ".endif"; - } elsif ($name eq 'GNU_MAKE') { - push @final_lines, "endif"; - } - } elsif ($1 eq 'ELSIFEQ' && defined $2) { - if ($name eq 'BSD_MAKE') { - push @final_lines, ".elif $tokens[0] == $tokens[1]"; - } elsif ($name eq 'GNU_MAKE') { - push @final_lines, "else ifeq ($tokens[0], $tokens[1])"; - } - } elsif ($1 eq 'IFDEF' && defined $2) { - if ($name eq 'BSD_MAKE') { - push @final_lines, ".if defined($2)"; - } elsif ($name eq 'GNU_MAKE') { - push @final_lines, "ifdef $2"; - } - } elsif ($1 eq 'IFEQ' && defined $2) { - if ($name eq 'BSD_MAKE') { - push @final_lines, ".if $tokens[0] == $tokens[1]"; - } elsif ($name eq 'GNU_MAKE') { - push @final_lines, "ifeq ($tokens[0],$tokens[1])"; - } - } elsif ($1 eq 'IFNEQ' && defined $2) { - if ($name eq 'BSD_MAKE') { - push @final_lines, ".if $tokens[0] != $tokens[1]"; - } elsif ($name eq 'GNU_MAKE') { - push @final_lines, "ifneq ($tokens[0],$tokens[1])"; - } - } elsif ($1 eq 'IFNDEF' && defined $2) { - if ($name eq 'BSD_MAKE') { - push @final_lines, ".if !defined($2)"; - } elsif ($name eq 'GNU_MAKE') { - push @final_lines, "ifndef $2"; - } - } elsif ($1 eq 'TARGET' && defined $2) { - if ($tokens[0] eq $name) { - push @final_lines, substr($2, length($tokens[0]) + 1); - } - } elsif ($1 !~ /[A-Z]/) { - # HACK: silently ignore if lower case as these are probably make commands. - push @final_lines, $line; - } else { - print_warning "unknown template command '$1' in $_!"; - push @final_lines, $line; - } - next; - } - - push @final_lines, $line; - } + # Write the templated files to disk. + for my $target (@targets) { # Create the directory if it doesn't already exist. my $directory = dirname $target; @@ -419,11 +319,11 @@ sub parse_templates($$$) { # Write the template file. print_format "Writing <|GREEN $target|> ...\n"; - open(TARGET, '>', $target) or print_error "unable to write $target: $!"; - foreach (@final_lines) { - say TARGET $_; + open(my $fh, '>', $target) or print_error "unable to write $target: $!"; + foreach (@lines) { + say $fh $_; } - close(TARGET); + close $fh; # Set file permissions. if (defined $mode) { diff --git a/make/console.pm b/make/console.pm index 84fbaae4a..0d3c1b38d 100644 --- a/make/console.pm +++ b/make/console.pm @@ -1,7 +1,7 @@ # # InspIRCd -- Internet Relay Chat Daemon # -# Copyright (C) 2014 Peter Powell <petpow@saberuk.com> +# Copyright (C) 2014-2017 Peter Powell <petpow@saberuk.com> # # 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 @@ -27,11 +27,14 @@ use feature ':5.10'; use strict; use warnings FATAL => qw(all); +use Class::Struct qw(struct); +use Exporter qw(import); use File::Path qw(mkpath); use File::Spec::Functions qw(rel2abs); -use Exporter qw(import); -our @EXPORT = qw(print_format +our @EXPORT = qw(command + execute_command + print_format print_error print_warning prompt_bool @@ -39,8 +42,9 @@ our @EXPORT = qw(print_format prompt_string); my %FORMAT_CODES = ( - DEFAULT => "\e[0m", - BOLD => "\e[1m", + DEFAULT => "\e[0m", + BOLD => "\e[1m", + UNDERLINE => "\e[4m", RED => "\e[1;31m", GREEN => "\e[1;32m", @@ -48,6 +52,13 @@ my %FORMAT_CODES = ( BLUE => "\e[1;34m" ); +my %commands; + +struct 'command' => { + 'callback' => '$', + 'description' => '$', +}; + sub __console_format($$) { my ($name, $data) = @_; return $data unless -t STDOUT; @@ -111,4 +122,38 @@ sub prompt_string($$$) { return $answer ? $answer : $default; } +sub command($$$) { + my ($name, $description, $callback) = @_; + $commands{$name} = command->new; + $commands{$name}->callback($callback); + $commands{$name}->description($description); +} + +sub command_alias($$) { + my ($source, $target) = @_; + command $source, undef, sub(@) { + execute_command $target, @_; + }; +} + +sub execute_command(@) { + my $command = defined $_[0] ? lc shift : 'help'; + if ($command eq 'help') { + print_format "<|GREEN Usage:|> $0 <<|UNDERLINE COMMAND|>> [<|UNDERLINE OPTIONS...|>]\n\n"; + print_format "<|GREEN Commands:|>\n"; + for my $key (sort keys %commands) { + next unless defined $commands{$key}->description; + my $name = sprintf "%-15s", $key; + my $description = $commands{$key}->description; + print_format " <|BOLD $name|> # $description\n"; + } + exit 0; + } elsif (!$commands{$command}) { + print_error "no command called <|BOLD $command|> exists!", + "See <|BOLD $0 help|> for a list of commands."; + } else { + return $commands{$command}->callback->(@_); + } +} + 1; diff --git a/make/directive.pm b/make/directive.pm index 4501fc5ec..2e9e7ed61 100644 --- a/make/directive.pm +++ b/make/directive.pm @@ -41,16 +41,16 @@ our @EXPORT = qw(get_directive sub get_directive($$;$) { my ($file, $property, $default) = @_; - open(MODULE, $file) or return $default; + open(my $fh, $file) or return $default; my $value = ''; - while (<MODULE>) { + while (<$fh>) { if ($_ =~ /^\/\* \$(\S+): (.+) \*\/$/ || $_ =~ /^\/\/\/ \$(\S+): (.+)/) { next unless $1 eq $property; $value .= ' ' . execute_functions($file, $1, $2); } } - close(MODULE); + close $fh; # Strip all extraneous whitespace. $value =~ s/^\s+|\s+$//g; diff --git a/make/template/bsd.mk b/make/template/bsd.mk new file mode 100644 index 000000000..05d413d0a --- /dev/null +++ b/make/template/bsd.mk @@ -0,0 +1,33 @@ +%platform darwin +%platform freebsd +%platform netbsd +%platform openbsd +%target Makefile +# +# InspIRCd -- Internet Relay Chat Daemon +# +# Copyright (C) 2017 Peter Powell <petpow@saberuk.com> +# +# 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/>. +# + +# This file will be installed as `Makefile` on BSD derivatives. When a user runs +# BSD Make it will be picked up as the default makefile even on systems like +# OpenBSD which have removed BSDMakefile support. If they run GNU Make then it +# will ignore this file and run GNUmakefile instead. + +all clean configureclean debug deinstall distclean help install: + @echo "InspIRCd no longer supports BSD Make. You should install GNU Make instead." + @echo "If this is problematic for you then please contact us via our IRC channel" + @echo "at irc.inspircd.org #InspIRCd." + @exit 1 diff --git a/make/template/main.mk b/make/template/main.mk index 50feb8f8d..49c77da05 100644 --- a/make/template/main.mk +++ b/make/template/main.mk @@ -1,5 +1,4 @@ -%target BSD_MAKE BSDmakefile -%target GNU_MAKE GNUmakefile +%target GNUmakefile # # InspIRCd -- Internet Relay Chat Daemon # @@ -26,9 +25,7 @@ # make/template/main.mk. Any changes made to the generated # files will go away whenever it is regenerated! # -# Please do not edit unless you know what you're doing. This -# needs to work in both GNU and BSD make; it is mangled for -# them by configure. +# Please do not edit unless you know what you're doing. # @@ -54,101 +51,106 @@ INSTMODE_DIR = 0750 INSTMODE_BIN = 0750 INSTMODE_LIB = 0640 -@IFNEQ $(COMPILER) ICC +ifneq ($(COMPILER), ICC) CORECXXFLAGS += -Woverloaded-virtual -Wshadow -@IFNEQ $(SYSTEM) openbsd +ifneq ($(SYSTEM), openbsd) CORECXXFLAGS += -pedantic -Wformat=2 -Wmissing-format-attribute -@ENDIF -@ENDIF +endif +endif -@IFNEQ $(SYSTEM) darwin +ifneq ($(SYSTEM), darwin) LDLIBS += -pthread -@ENDIF +endif -@IFEQ $(SYSTEM) linux +ifeq ($(SYSTEM), linux) LDLIBS += -ldl -lrt -@ENDIF -@IFEQ $(SYSTEM) gnukfreebsd +endif +ifeq ($(SYSTEM), gnukfreebsd) LDLIBS += -ldl -lrt -@ENDIF -@IFEQ $(SYSTEM) gnu +endif +ifeq ($(SYSTEM), gnu) LDLIBS += -ldl -lrt -@ENDIF -@IFEQ $(SYSTEM) solaris +endif +ifeq ($(SYSTEM), solaris) LDLIBS += -lsocket -lnsl -lrt -lresolv INSTALL = ginstall -@ENDIF -@IFEQ $(SYSTEM) darwin +endif +ifeq ($(SYSTEM), darwin) LDLIBS += -ldl CORELDFLAGS = -dynamic -bind_at_load -L. $(LDFLAGS) PICLDFLAGS = -fPIC -shared -twolevel_namespace -undefined dynamic_lookup $(LDFLAGS) -@ENDIF +endif -@IFNDEF INSPIRCD_DEBUG +ifndef INSPIRCD_DEBUG INSPIRCD_DEBUG=0 -@ENDIF +endif DBGOK=0 -@IFEQ $(INSPIRCD_DEBUG) 0 +ifeq ($(INSPIRCD_DEBUG), 0) CORECXXFLAGS += -fno-rtti -O2 -@IFEQ $(COMPILER) GCC +ifeq ($(COMPILER), GCC) CORECXXFLAGS += -g1 -@ENDIF +endif HEADER = std-header DBGOK=1 -@ENDIF -@IFEQ $(INSPIRCD_DEBUG) 1 +endif +ifeq ($(INSPIRCD_DEBUG), 1) CORECXXFLAGS += -O0 -g3 -Werror -DINSPIRCD_ENABLE_RTTI HEADER = debug-header DBGOK=1 -@ENDIF -@IFEQ $(INSPIRCD_DEBUG) 2 +endif +ifeq ($(INSPIRCD_DEBUG), 2) CORECXXFLAGS += -fno-rtti -O2 -g3 HEADER = debug-header DBGOK=1 -@ENDIF +endif FOOTER = finishmessage -@TARGET GNU_MAKE MAKEFLAGS += --no-print-directory +MAKEFLAGS += --no-print-directory -@TARGET GNU_MAKE SOURCEPATH = $(shell /bin/pwd) -@TARGET BSD_MAKE SOURCEPATH != /bin/pwd +SOURCEPATH = $(shell /bin/pwd) -@IFNDEF INSPIRCD_VERBOSE - @TARGET GNU_MAKE MAKEFLAGS += --silent - @TARGET BSD_MAKE MAKE += -s -@ENDIF +ifndef INSPIRCD_VERBOSE + MAKEFLAGS += --silent +endif -@IFDEF INSPIRCD_STATIC +ifdef INSPIRCD_STATIC CORECXXFLAGS += -DINSPIRCD_STATIC -@ENDIF +endif # Add the users CPPFLAGS/CXXFLAGS to the base ones to allow them to # override things like -Wfatal-errors if they wish to. CORECXXFLAGS += $(CPPFLAGS) $(CXXFLAGS) -@DO_EXPORT CXX CORECXXFLAGS LDLIBS PICLDFLAGS INSPIRCD_VERBOSE SOCKETENGINE CORELDFLAGS -@DO_EXPORT SOURCEPATH BUILDPATH INSPIRCD_STATIC +export BUILDPATH +export CORECXXFLAGS +export CORELDFLAGS +export CXX +export INSPIRCD_STATIC +export INSPIRCD_VERBOSE +export LDLIBS +export PICLDFLAGS +export SOCKETENGINE +export SOURCEPATH # Default target TARGET = all -@IFDEF INSPIRCD_MODULE +ifdef INSPIRCD_MODULE HEADER = mod-header FOOTER = mod-footer - @TARGET BSD_MAKE TARGET = modules/${INSPIRCD_MODULE:S/.so$//}.so - @TARGET GNU_MAKE TARGET = modules/$(INSPIRCD_MODULE:.so=).so -@ENDIF + TARGET = modules/$(INSPIRCD_MODULE:.so=).so +endif -@IFDEF INSPIRCD_TARGET +ifdef INSPIRCD_TARGET HEADER = FOOTER = target TARGET = $(INSPIRCD_TARGET) -@ENDIF +endif -@IFEQ $(DBGOK) 0 +ifeq ($(DBGOK), 0) HEADER = unknown-debug-level -@ENDIF +endif all: $(FOOTER) @@ -174,10 +176,10 @@ debug-header: @echo "*************************************" mod-header: -@IFDEF INSPIRCD_STATIC +ifdef INSPIRCD_STATIC @echo 'Cannot build single modules in pure-static build' @exit 1 -@ENDIF +endif @echo 'Building single module:' mod-footer: target @@ -223,17 +225,17 @@ install: target @-$(INSTALL) -d -m $(INSTMODE_DIR) $(MANPATH) @-$(INSTALL) -d -m $(INSTMODE_DIR) $(MODPATH) [ "$(BUILDPATH)/bin/" -ef $(BINPATH) ] || $(INSTALL) -m $(INSTMODE_BIN) "$(BUILDPATH)/bin/inspircd" $(BINPATH) -@IFNDEF INSPIRCD_STATIC +ifndef INSPIRCD_STATIC [ "$(BUILDPATH)/modules/" -ef $(MODPATH) ] || $(INSTALL) -m $(INSTMODE_LIB) "$(BUILDPATH)/modules/"*.so $(MODPATH) -@ENDIF +endif -$(INSTALL) -m $(INSTMODE_BIN) @CONFIGURE_DIRECTORY@/inspircd $(BASE) 2>/dev/null -$(INSTALL) -m $(INSTMODE_LIB) .gdbargs $(BASE)/.gdbargs 2>/dev/null -@IFEQ $(SYSTEM) darwin +ifeq ($(SYSTEM), darwin) -$(INSTALL) -m $(INSTMODE_BIN) @CONFIGURE_DIRECTORY@/org.inspircd.plist $(BASE) 2>/dev/null -@ENDIF -@IFEQ $(SYSTEM) linux +endif +ifeq ($(SYSTEM), linux) -$(INSTALL) -m $(INSTMODE_LIB) @CONFIGURE_DIRECTORY@/inspircd.service $(BASE) 2>/dev/null -@ENDIF +endif -$(INSTALL) -m $(INSTMODE_LIB) @CONFIGURE_DIRECTORY@/inspircd.1 $(MANPATH) 2>/dev/null -$(INSTALL) -m $(INSTMODE_LIB) @CONFIGURE_DIRECTORY@/inspircd-genssl.1 $(MANPATH) 2>/dev/null -$(INSTALL) -m $(INSTMODE_BIN) tools/genssl $(BINPATH)/inspircd-genssl 2>/dev/null @@ -255,9 +257,8 @@ install: target @echo 'Remember to create your config file:' $(CONPATH)/inspircd.conf @echo 'Examples are available at:' $(CONPATH)/examples/ -GNUmakefile BSDmakefile: make/template/main.mk src/version.sh configure @CONFIGURE_CACHE_FILE@ +GNUmakefile: make/template/main.mk src/version.sh configure @CONFIGURE_CACHE_FILE@ ./configure --update -@TARGET BSD_MAKE .MAKEFILEDEPS: BSDmakefile clean: @echo Cleaning... @@ -280,7 +281,7 @@ deinstall: configureclean: rm -f .gdbargs - rm -f BSDmakefile + -rm -f Makefile rm -f GNUmakefile rm -f include/config.h rm -rf @CONFIGURE_DIRECTORY@ diff --git a/make/test/clock_gettime.cpp b/make/test/clock_gettime.cpp index 91d8cd412..d111d591f 100644 --- a/make/test/clock_gettime.cpp +++ b/make/test/clock_gettime.cpp @@ -1,6 +1,7 @@ /* * InspIRCd -- Internet Relay Chat Daemon * + * Copyright (C) 2013 Peter Powell <petpow@saberuk.com> * * 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 diff --git a/make/test/compiler.cpp b/make/test/compiler.cpp index e2cbd9f64..f01423325 100644 --- a/make/test/compiler.cpp +++ b/make/test/compiler.cpp @@ -1,6 +1,8 @@ /* * InspIRCd -- Internet Relay Chat Daemon * + * Copyright (C) 2016 Attila Molnar <attilamolnar@hush.com> + * Copyright (C) 2014-2015 Peter Powell <petpow@saberuk.com> * * 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 diff --git a/make/test/compiler_info.cpp b/make/test/compiler_info.cpp new file mode 100644 index 000000000..10b156fc8 --- /dev/null +++ b/make/test/compiler_info.cpp @@ -0,0 +1,41 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2017 Peter Powell <petpow@saberuk.com> + * + * 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 <iostream> + +#if defined __INTEL_COMPILER // Also defines __clang__ and __GNUC__ +# define INSPIRCD_COMPILER_NAME "Intel" +# define INSPIRCD_COMPILER_VERSION (__INTEL_COMPILER / 100) << '.' << (__INTEL_COMPILER % 100) +#elif defined __clang__ // Also defines __GNUC__ +# if defined __apple_build_version__ +# define INSPIRCD_COMPILER_NAME "AppleClang" +# else +# define INSPIRCD_COMPILER_NAME "Clang" +# endif +# define INSPIRCD_COMPILER_VERSION __clang_major__ << '.' << __clang_minor__ +#elif defined __GNUC__ +# define INSPIRCD_COMPILER_NAME "GCC" +# define INSPIRCD_COMPILER_VERSION __GNUC__ << '.' << __GNUC_MINOR__ +#endif + +int main() { + std::cout << "NAME " << INSPIRCD_COMPILER_NAME << std::endl + << "VERSION " << INSPIRCD_COMPILER_VERSION << std::endl; + return 0; +} diff --git a/modulemanager b/modulemanager index e859f683b..7471dcc77 100755 --- a/modulemanager +++ b/modulemanager @@ -3,6 +3,7 @@ # # InspIRCd -- Internet Relay Chat Daemon # +# Copyright (C) 2012-2017 Peter Powell <petpow@saberuk.com> # Copyright (C) 2008-2009 Robin Burchell <robin+git@viroteck.net> # # This file is part of InspIRCd. InspIRCd is free software: you can @@ -19,23 +20,26 @@ # -use strict; -use warnings FATAL => qw(all); - -use make::common; - BEGIN { - unless (module_installed("LWP::Simple")) { + require 5.10.0; + unless (eval "use LWP::Simple; 1") { die "Your system is missing the LWP::Simple Perl module!"; } - unless (module_installed("Crypt::SSLeay") || module_installed("IO::Socket::SSL")) { + unless (eval "use Crypt::SSLeay; 1" || eval "use IO::Socket::SSL; 1") { die "Your system is missing the Crypt::SSLeay or IO::Socket::SSL Perl modules!"; } - } -use File::Basename; -use LWP::Simple; +use feature ':5.10'; +use strict; +use warnings FATAL => qw(all); + +use File::Basename qw(basename); +use FindBin qw($RealDir); + +use lib $RealDir; +use make::common; +use make::console; my %installed; # $installed{name} = $version @@ -102,7 +106,7 @@ sub parse_url { } # hash of installed module versions from our mini-database, key (m_foobar) to version (00abacca..). -my %mod_versions; +my %mod_versions = read_config_file '.modulemanager'; # useless helper stub sub getmodversion { @@ -110,19 +114,6 @@ sub getmodversion { return $mod_versions{$file}; } -# read in installed versions -if (-e '.modulemanager') -{ - open SRC, '.modulemanager' or die ".modulemanager exists but i can't read it: $!"; - while (<SRC>) - { - s/\n//; - (my $mod, my $ver) = split(/ /, $_); - $mod_versions{$mod} = $ver; - } - close SRC; -} - # read in external URL sources open SRC, 'sources.list' or die "Could not open sources.list: $!"; while (<SRC>) { @@ -262,10 +253,8 @@ sub resolve_deps { } } -my $action = $#ARGV >= 0 ? lc shift @ARGV : 'help'; - -if ($action eq 'install') { - for my $mod (@ARGV) { +command 'install', 'Install a third-party module', sub { + for my $mod (@_) { my $vers = $mod =~ s/=([-0-9.]+)// ? $1 : undef; $mod = lc $mod; unless ($modules{$mod}) { @@ -279,7 +268,9 @@ if ($action eq 'install') { } $todo{$mod} = $ver; } -} elsif ($action eq 'upgrade') { +}; + +command 'upgrade', 'Upgrade a third-party module', sub { my @installed = sort keys %installed; for my $mod (@installed) { next unless $mod =~ /^m_/; @@ -289,7 +280,9 @@ if ($action eq 'install') { %todo = %saved; } } -} elsif ($action eq 'list') { +}; + +command 'list', 'List available third-party modules', sub { my @all = sort keys %modules; for my $mod (@all) { my @vers = sort { ver_cmp() } keys %{$modules{$mod}}; @@ -303,25 +296,16 @@ if ($action eq 'install') { my $vers = join ' ', map { $_ eq $instver ? "\e[1m$_\e[m" : $_ } @vers; print "$mod ($vers) - $desc\n"; } -} else { - print <<ENDUSAGE -Use: $0 <action> <args> -Action is one of the following - install install new modules - upgrade upgrade installed modules - list lists available modules - -For installing a package, specify its name or name=version to force the -installation of a specific version. -ENDUSAGE -;exit 1; -} + exit 0; +}; + +execute_command @ARGV; resolve_deps(0); $| = 1; # immediate print of lines without \n -print "Processing changes for $action...\n"; +print "Processing changes...\n"; for my $mod (keys %installed) { next if $todo{$mod}; print "Uninstalling $mod $installed{$mod}\n"; @@ -359,11 +343,6 @@ for my $mod (sort keys %todo) { } # write database of installed versions -open SRC, '>.modulemanager' or die "can't write installed versions to .modulemanager, won't be able to track upgrades properly: $!"; -foreach my $key (keys %mod_versions) -{ - print SRC "$key $mod_versions{$key}\n"; -} -close SRC; +write_config_file '.modulemanager', %mod_versions; print "Finished!\n"; diff --git a/src/configparser.cpp b/src/configparser.cpp index 8bf9aaec2..7c03fe58a 100644 --- a/src/configparser.cpp +++ b/src/configparser.cpp @@ -91,7 +91,7 @@ struct Parser unget(ch); } - bool kv(std::vector<KeyVal>* items, std::set<std::string>& seen) + bool kv(ConfigItems* items) { std::string key; nextword(key); @@ -177,10 +177,10 @@ struct Parser value.push_back(ch); } - if (!seen.insert(key).second) + if (items->find(key) != items->end()) throw CoreException("Duplicate key '" + key + "' found"); - items->push_back(KeyVal(key, value)); + (*items)[key] = value; return true; } @@ -199,11 +199,10 @@ struct Parser if (name.empty()) throw CoreException("Empty tag name"); - std::vector<KeyVal>* items; - std::set<std::string> seen; + ConfigItems* items; tag = ConfigTag::create(name, current.filename, current.line, items); - while (kv(items, seen)) + while (kv(items)) { // Do nothing here (silences a GCC warning). } @@ -220,14 +219,14 @@ struct Parser } else if (name == "files") { - for(std::vector<KeyVal>::iterator i = items->begin(); i != items->end(); i++) + for(ConfigItems::iterator i = items->begin(); i != items->end(); i++) { stack.DoReadFile(i->first, i->second, flags, false); } } else if (name == "execfiles") { - for(std::vector<KeyVal>::iterator i = items->begin(); i != items->end(); i++) + for(ConfigItems::iterator i = items->begin(); i != items->end(); i++) { stack.DoReadFile(i->first, i->second, flags, true); } @@ -385,7 +384,7 @@ bool ParseStack::ParseFile(const std::string& path, int flags, const std::string bool ConfigTag::readString(const std::string& key, std::string& value, bool allow_lf) { - for(std::vector<KeyVal>::iterator j = items.begin(); j != items.end(); ++j) + for(ConfigItems::iterator j = items.begin(); j != items.end(); ++j) { if(j->first != key) continue; @@ -488,7 +487,7 @@ 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, ConfigItems*& Items) { ConfigTag* rv = new ConfigTag(Tag, file, line); Items = &rv->items; diff --git a/src/configreader.cpp b/src/configreader.cpp index 9d327532b..8263b8737 100644 --- a/src/configreader.cpp +++ b/src/configreader.cpp @@ -46,7 +46,7 @@ ServerLimits::ServerLimits(ConfigTag* tag) static ConfigTag* CreateEmptyTag() { - std::vector<KeyVal>* items; + ConfigItems* items; return ConfigTag::create("empty", "<auto>", 0, items); } @@ -220,9 +220,9 @@ void ServerConfig::CrossCheckConnectBlocks(ServerConfig* current) if (blk_count == 0) { // No connect blocks found; make a trivial default block - std::vector<KeyVal>* items; + ConfigItems* items; ConfigTag* tag = ConfigTag::create("connect", "<auto>", 0, items); - items->push_back(std::make_pair("allow", "*")); + (*items)["allow"] = "*"; config_data.insert(std::make_pair("connect", tag)); blk_count = 1; } diff --git a/src/coremods/core_channel/core_channel.cpp b/src/coremods/core_channel/core_channel.cpp index b77aac7e2..3af809645 100644 --- a/src/coremods/core_channel/core_channel.cpp +++ b/src/coremods/core_channel/core_channel.cpp @@ -20,6 +20,7 @@ #include "inspircd.h" #include "core_channel.h" #include "invite.h" +#include "listmode.h" class CoreModChannel : public Module, public CheckExemption::EventListener { @@ -81,6 +82,30 @@ class CoreModChannel : public Module, public CheckExemption::EventListener exemptions.swap(exempts); } + void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE + { + // Build a map of limits to their mode character. + insp::flat_map<int, std::string> limits; + const ModeParser::ListModeList& listmodes = ServerInstance->Modes->GetListModes(); + for (ModeParser::ListModeList::const_iterator iter = listmodes.begin(); iter != listmodes.end(); ++iter) + { + const unsigned int limit = (*iter)->GetLowerLimit(); + limits[limit].push_back((*iter)->GetModeChar()); + } + + // Generate the MAXLIST token from the limits map. + std::string& buffer = tokens["MAXLIST"]; + for (insp::flat_map<int, std::string>::const_iterator iter = limits.begin(); iter != limits.end(); ++iter) + { + if (!buffer.empty()) + buffer.push_back(','); + + buffer.append(iter->second); + buffer.push_back(':'); + buffer.append(ConvToStr(iter->first)); + } + } + void OnPostJoin(Membership* memb) CXX11_OVERRIDE { Channel* const chan = memb->chan; diff --git a/src/coremods/core_dns.cpp b/src/coremods/core_dns.cpp index 753b41f43..1040bb036 100644 --- a/src/coremods/core_dns.cpp +++ b/src/coremods/core_dns.cpp @@ -154,7 +154,7 @@ class Packet : public Query record.ttl = (input[pos] << 24) | (input[pos + 1] << 16) | (input[pos + 2] << 8) | input[pos + 3]; pos += 4; - //record.rdlength = input[pos] << 8 | input[pos + 1]; + uint16_t rdlength = input[pos] << 8 | input[pos + 1]; pos += 2; switch (record.type) @@ -200,6 +200,19 @@ class Packet : public Query break; } + case QUERY_TXT: + { + if (pos + rdlength > input_size) + throw Exception("Unable to unpack txt resource record"); + + record.rdata = std::string(reinterpret_cast<const char *>(input + pos), rdlength); + pos += rdlength; + + if (record.rdata.find_first_of("\r\n\0", 0, 3) != std::string::npos) + throw Exception("Invalid character in txt record"); + + break; + } default: break; } @@ -429,7 +442,7 @@ class MyManager : public Manager, public Timer, public EventHandler } } - void Process(DNS::Request* req) + void Process(DNS::Request* req) CXX11_OVERRIDE { if ((unloading) || (req->creator->dying)) throw Exception("Module is being unloaded"); @@ -496,13 +509,13 @@ class MyManager : public Manager, public Timer, public EventHandler ServerInstance->Timers.AddTimer(req); } - void RemoveRequest(DNS::Request* req) + void RemoveRequest(DNS::Request* req) CXX11_OVERRIDE { if (requests[req->id] == req) requests[req->id] = NULL; } - std::string GetErrorStr(Error e) + std::string GetErrorStr(Error e) CXX11_OVERRIDE { switch (e) { @@ -651,7 +664,7 @@ class MyManager : public Manager, public Timer, public EventHandler delete request; } - bool Tick(time_t now) + bool Tick(time_t now) CXX11_OVERRIDE { ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "cache: purging DNS cache"); @@ -813,7 +826,7 @@ class ModuleDNS : public Module this->manager.Rehash(DNSServer, SourceIP, SourcePort); } - void OnUnloadModule(Module* mod) + void OnUnloadModule(Module* mod) CXX11_OVERRIDE { for (unsigned int i = 0; i <= MAX_REQUEST_ID; ++i) { @@ -832,7 +845,7 @@ class ModuleDNS : public Module } } - Version GetVersion() + Version GetVersion() CXX11_OVERRIDE { return Version("DNS support", VF_CORE|VF_VENDOR); } diff --git a/src/coremods/core_hostname_lookup.cpp b/src/coremods/core_hostname_lookup.cpp index b9adc9c2e..d150b8551 100644 --- a/src/coremods/core_hostname_lookup.cpp +++ b/src/coremods/core_hostname_lookup.cpp @@ -195,7 +195,7 @@ class ModuleHostnameLookup : public Module ph = &ptrHosts; } - void OnUserInit(LocalUser *user) + void OnUserInit(LocalUser *user) CXX11_OVERRIDE { if (!DNS || !user->MyClass->resolvehostnames) { @@ -222,12 +222,12 @@ class ModuleHostnameLookup : public Module } } - ModResult OnCheckReady(LocalUser* user) + ModResult OnCheckReady(LocalUser* user) CXX11_OVERRIDE { return this->dnsLookup.get(user) ? MOD_RES_DENY : MOD_RES_PASSTHRU; } - Version GetVersion() + Version GetVersion() CXX11_OVERRIDE { return Version("Provides support for DNS lookups on connecting clients", VF_CORE|VF_VENDOR); } diff --git a/src/coremods/core_loadmodule.cpp b/src/coremods/core_loadmodule.cpp index 09c044198..fde149587 100644 --- a/src/coremods/core_loadmodule.cpp +++ b/src/coremods/core_loadmodule.cpp @@ -116,7 +116,7 @@ class CoreModLoadModule : public Module { } - Version GetVersion() + Version GetVersion() CXX11_OVERRIDE { return Version("Provides the LOADMODULE and UNLOADMODULE commands", VF_VENDOR|VF_CORE); } diff --git a/src/coremods/core_lusers.cpp b/src/coremods/core_lusers.cpp index a0d0d0205..7f1903dd0 100644 --- a/src/coremods/core_lusers.cpp +++ b/src/coremods/core_lusers.cpp @@ -151,20 +151,20 @@ class ModuleLusers : public Module { } - void OnPostConnect(User* user) + void OnPostConnect(User* user) CXX11_OVERRIDE { counters.UpdateMaxUsers(); if (user->IsModeSet(invisiblemode)) counters.invisible++; } - void OnUserQuit(User* user, const std::string& message, const std::string& oper_message) + void OnUserQuit(User* user, const std::string& message, const std::string& oper_message) CXX11_OVERRIDE { if (user->IsModeSet(invisiblemode)) counters.invisible--; } - Version GetVersion() + Version GetVersion() CXX11_OVERRIDE { return Version("LUSERS", VF_VENDOR | VF_CORE); } diff --git a/src/coremods/core_oper/cmd_kill.cpp b/src/coremods/core_oper/cmd_kill.cpp index e75566e2f..8e8c4fadc 100644 --- a/src/coremods/core_oper/cmd_kill.cpp +++ b/src/coremods/core_oper/cmd_kill.cpp @@ -43,96 +43,85 @@ CmdResult CommandKill::Handle (const std::vector<std::string>& parameters, User return CMD_FAILURE; } - User *u = ServerInstance->FindNick(parameters[0]); - if (u) + User* target = ServerInstance->FindNick(parameters[0]); + if (!target) + { + user->WriteNumeric(Numerics::NoSuchNick(parameters[0])); + return CMD_FAILURE; + } + + /* + * Here, we need to decide how to munge kill messages. Whether to hide killer, what to show opers, etc. + * We only do this when the command is being issued LOCALLY, for remote KILL, we just copy the message we got. + * + * This conditional is so that we only append the "Killed (" prefix ONCE. If killer is remote, then the kill + * just gets processed and passed on, otherwise, if they are local, it gets prefixed. Makes sense :-) -- w00t + */ + + if (IS_LOCAL(user)) { /* - * Here, we need to decide how to munge kill messages. Whether to hide killer, what to show opers, etc. - * We only do this when the command is being issued LOCALLY, for remote KILL, we just copy the message we got. - * - * This conditional is so that we only append the "Killed (" prefix ONCE. If killer is remote, then the kill - * just gets processed and passed on, otherwise, if they are local, it gets prefixed. Makes sense :-) -- w00t + * Moved this event inside the IS_LOCAL check also, we don't want half the network killing a user + * and the other half not. This would be a bad thing. ;p -- w00t */ + ModResult MOD_RESULT; + FIRST_MOD_RESULT(OnKill, MOD_RESULT, (user, target, parameters[1])); + + if (MOD_RESULT == MOD_RES_DENY) + return CMD_FAILURE; - if (IS_LOCAL(user)) + killreason = "Killed ("; + if (!ServerInstance->Config->HideKillsServer.empty()) { - /* - * Moved this event inside the IS_LOCAL check also, we don't want half the network killing a user - * and the other half not. This would be a bad thing. ;p -- w00t - */ - ModResult MOD_RESULT; - FIRST_MOD_RESULT(OnKill, MOD_RESULT, (user, u, parameters[1])); - - if (MOD_RESULT == MOD_RES_DENY) - return CMD_FAILURE; - - killreason = "Killed ("; - if (!ServerInstance->Config->HideKillsServer.empty()) - { - // hidekills is on, use it - killreason += ServerInstance->Config->HideKillsServer; - } - else - { - // hidekills is off, do nothing - killreason += user->nick; - } - - killreason += " (" + parameters[1] + "))"; + // hidekills is on, use it + killreason += ServerInstance->Config->HideKillsServer; } else { - /* Leave it alone, remote server has already formatted it */ - killreason.assign(parameters[1], 0, ServerInstance->Config->Limits.MaxQuit); + // hidekills is off, do nothing + killreason += user->nick; } - /* - * Now we need to decide whether or not to send a local or remote snotice. Currently this checking is a little flawed. - * No time to fix it right now, so left a note. -- w00t - */ - if (!IS_LOCAL(u)) - { - // remote kill - if ((!ServerInstance->Config->HideULineKills) || (!user->server->IsULine())) - ServerInstance->SNO->WriteToSnoMask('K', "Remote kill by %s: %s (%s)", user->nick.c_str(), u->GetFullRealHost().c_str(), parameters[1].c_str()); - this->lastuuid = u->uuid; - } + killreason += " (" + parameters[1] + "))"; + } + else + { + /* Leave it alone, remote server has already formatted it */ + killreason.assign(parameters[1], 0, ServerInstance->Config->Limits.MaxQuit); + } + + if ((!ServerInstance->Config->HideULineKills) || (!user->server->IsULine())) + { + if (IS_LOCAL(user) && IS_LOCAL(target)) + ServerInstance->SNO->WriteGlobalSno('k', "Local kill by %s: %s (%s)", user->nick.c_str(), target->GetFullRealHost().c_str(), parameters[1].c_str()); else - { - // local kill - /* - * XXX - this isn't entirely correct, servers A - B - C, oper on A, client on C. Oper kills client, A and B will get remote kill - * snotices, C will get a local kill snotice. this isn't accurate, and needs fixing at some stage. -- w00t - */ - if ((!ServerInstance->Config->HideULineKills) || (!user->server->IsULine())) - { - if (IS_LOCAL(user)) - ServerInstance->SNO->WriteGlobalSno('k',"Local Kill by %s: %s (%s)", user->nick.c_str(), u->GetFullRealHost().c_str(), parameters[1].c_str()); - else - ServerInstance->SNO->WriteToSnoMask('k',"Local Kill by %s: %s (%s)", user->nick.c_str(), u->GetFullRealHost().c_str(), parameters[1].c_str()); - } - - ServerInstance->Logs->Log("KILL", LOG_DEFAULT, "LOCAL KILL: %s :%s!%s!%s (%s)", u->nick.c_str(), ServerInstance->Config->ServerName.c_str(), user->dhost.c_str(), user->nick.c_str(), parameters[1].c_str()); - - u->Write(":%s KILL %s :%s!%s!%s (%s)", ServerInstance->Config->HideKillsServer.empty() ? user->GetFullHost().c_str() : ServerInstance->Config->HideKillsServer.c_str(), - u->nick.c_str(), - ServerInstance->Config->ServerName.c_str(), - ServerInstance->Config->HideKillsServer.empty() ? user->dhost.c_str() : ServerInstance->Config->HideKillsServer.c_str(), - ServerInstance->Config->HideKillsServer.empty() ? user->nick.c_str() : ServerInstance->Config->HideKillsServer.c_str(), - parameters[1].c_str()); - - this->lastuuid.clear(); - } + ServerInstance->SNO->WriteToSnoMask('K', "Remote kill by %s: %s (%s)", user->nick.c_str(), target->GetFullRealHost().c_str(), parameters[1].c_str()); + } - // send the quit out - ServerInstance->Users->QuitUser(u, killreason); + if (IS_LOCAL(user) || IS_LOCAL(target)) + ServerInstance->Logs->Log("KILL", LOG_DEFAULT, "%s KILL: %s :%s!%s!%s (%s)", + IS_LOCAL(user) && IS_LOCAL(target) ? "LOCAL" : "REMOTE", + target->nick.c_str(), + ServerInstance->Config->ServerName.c_str(), user->dhost.c_str(), user->nick.c_str(), + parameters[1].c_str()); + + if (IS_LOCAL(target)) + { + target->Write(":%s KILL %s :%s", + ServerInstance->Config->HideKillsServer.empty() ? user->GetFullHost().c_str() : ServerInstance->Config->HideKillsServer.c_str(), + target->nick.c_str(), + parameters[1].c_str()); + + this->lastuuid.clear(); } else { - user->WriteNumeric(Numerics::NoSuchNick(parameters[0])); - return CMD_FAILURE; + this->lastuuid = target->uuid; } + // send the quit out + ServerInstance->Users->QuitUser(target, killreason); + return CMD_SUCCESS; } diff --git a/src/coremods/core_privmsg.cpp b/src/coremods/core_privmsg.cpp index cccba0850..449097a75 100644 --- a/src/coremods/core_privmsg.cpp +++ b/src/coremods/core_privmsg.cpp @@ -280,7 +280,7 @@ class ModuleCoreMessage : public Module { } - Version GetVersion() + Version GetVersion() CXX11_OVERRIDE { return Version("PRIVMSG, NOTICE", VF_CORE|VF_VENDOR); } diff --git a/src/coremods/core_stub.cpp b/src/coremods/core_stub.cpp index 91fc16241..71b0ddaea 100644 --- a/src/coremods/core_stub.cpp +++ b/src/coremods/core_stub.cpp @@ -147,7 +147,7 @@ class CoreModStub : public Module { } - Version GetVersion() + Version GetVersion() CXX11_OVERRIDE { return Version("Provides the stub commands CONNECT, LINKS, SERVER and SQUIT", VF_VENDOR|VF_CORE); } diff --git a/src/coremods/core_who.cpp b/src/coremods/core_who.cpp index 739c675a9..677a1eb6d 100644 --- a/src/coremods/core_who.cpp +++ b/src/coremods/core_who.cpp @@ -38,14 +38,18 @@ class CommandWho : public Command bool opt_time; ChanModeReference secretmode; ChanModeReference privatemode; + UserModeReference hidechansmode; UserModeReference invisiblemode; - Membership* get_first_visible_channel(User* u) + Membership* get_first_visible_channel(User* source, User* u) { for (User::ChanList::iterator i = u->chans.begin(); i != u->chans.end(); ++i) { Membership* memb = *i; - if (!memb->chan->IsModeSet(secretmode)) + + /* XXX move the +I check into m_hidechans */ + bool has_modes = memb->chan->IsModeSet(secretmode) || memb->chan->IsModeSet(privatemode) || u->IsModeSet(hidechansmode); + if (source == u || !has_modes || memb->chan->HasUser(source)) return memb; } return NULL; @@ -58,6 +62,7 @@ class CommandWho : public Command : Command(parent, "WHO", 1) , secretmode(parent, "secret") , privatemode(parent, "private") + , hidechansmode(parent, "hidechans") , invisiblemode(parent, "invisible") { syntax = "<server>|<nickname>|<channel>|<realname>|<host>|0 [ohurmMiaplf]"; @@ -189,7 +194,7 @@ bool CommandWho::CanView(Channel* chan, User* user) void CommandWho::SendWhoLine(User* user, const std::vector<std::string>& parms, Membership* memb, User* u, std::vector<Numeric::Numeric>& whoresults) { if (!memb) - memb = get_first_visible_channel(u); + memb = get_first_visible_channel(user, u); Numeric::Numeric wholine(RPL_WHOREPLY); wholine.push(memb ? memb->chan->name : "*").push(u->ident); diff --git a/src/coremods/core_whowas.cpp b/src/coremods/core_whowas.cpp index f52fb0174..0bb47b273 100644 --- a/src/coremods/core_whowas.cpp +++ b/src/coremods/core_whowas.cpp @@ -259,13 +259,13 @@ class ModuleWhoWas : public Module { } - void OnGarbageCollect() + void OnGarbageCollect() CXX11_OVERRIDE { // Remove all entries older than MaxKeep cmd.manager.Maintain(); } - void OnUserQuit(User* user, const std::string& message, const std::string& oper_message) + void OnUserQuit(User* user, const std::string& message, const std::string& oper_message) CXX11_OVERRIDE { cmd.manager.Add(user); } @@ -288,7 +288,7 @@ class ModuleWhoWas : public Module cmd.manager.UpdateConfig(NewGroupSize, NewMaxGroups, NewMaxKeep); } - Version GetVersion() + Version GetVersion() CXX11_OVERRIDE { return Version("WHOWAS", VF_VENDOR); } diff --git a/src/listmode.cpp b/src/listmode.cpp index cd034688c..23f98bf3f 100644 --- a/src/listmode.cpp +++ b/src/listmode.cpp @@ -77,7 +77,7 @@ void ListModeBase::DoRehash() // Add the default entry. This is inserted last so if the user specifies a // wildcard record in the config it will take precedence over this entry. - chanlimits.push_back(ListLimit("*", 64)); + chanlimits.push_back(ListLimit("*", DEFAULT_LIST_SIZE)); // Most of the time our settings are unchanged, so we can avoid iterating the chanlist if (oldlimits == chanlimits) @@ -102,7 +102,7 @@ unsigned int ListModeBase::FindLimit(const std::string& channame) return it->limit; } } - return 64; + return DEFAULT_LIST_SIZE; } unsigned int ListModeBase::GetLimitInternal(const std::string& channame, ChanData* cd) @@ -121,6 +121,17 @@ unsigned int ListModeBase::GetLimit(Channel* channel) return GetLimitInternal(channel->name, cd); } +unsigned int ListModeBase::GetLowerLimit() +{ + unsigned int limit = UINT_MAX; + for (limitlist::iterator iter = chanlimits.begin(); iter != chanlimits.end(); ++iter) + { + if (iter->limit < limit) + limit = iter->limit; + } + return limit == UINT_MAX ? DEFAULT_LIST_SIZE : limit; +} + ModeAction ListModeBase::OnModeChange(User* source, User*, Channel* channel, std::string ¶meter, bool adding) { // Try and grab the list diff --git a/src/modmanager_static.cpp b/src/modmanager_static.cpp index 5c04a7680..9a385dd3c 100644 --- a/src/modmanager_static.cpp +++ b/src/modmanager_static.cpp @@ -72,7 +72,7 @@ class AllModule : public Module stdalgo::delete_all(cmds); } - Version GetVersion() + Version GetVersion() CXX11_OVERRIDE { return Version("All commands", VF_VENDOR|VF_CORE); } diff --git a/src/modules/extra/m_pgsql.cpp b/src/modules/extra/m_pgsql.cpp index 5f6f6e30f..6835cb558 100644 --- a/src/modules/extra/m_pgsql.cpp +++ b/src/modules/extra/m_pgsql.cpp @@ -159,7 +159,7 @@ class SQLConn : public SQLProvider, public EventHandler } } - CullResult cull() + CullResult cull() CXX11_OVERRIDE { this->SQLProvider::cull(); ServerInstance->Modules->DelService(*this); @@ -389,7 +389,7 @@ restart: } } - void submit(SQLQuery *req, const std::string& q) + void submit(SQLQuery *req, const std::string& q) CXX11_OVERRIDE { if (qinprog.q.empty()) { @@ -402,7 +402,7 @@ restart: } } - void submit(SQLQuery *req, const std::string& q, const ParamL& p) + void submit(SQLQuery *req, const std::string& q, const ParamL& p) CXX11_OVERRIDE { std::string res; unsigned int param = 0; @@ -427,7 +427,7 @@ restart: submit(req, res); } - void submit(SQLQuery *req, const std::string& q, const ParamM& p) + void submit(SQLQuery *req, const std::string& q, const ParamM& p) CXX11_OVERRIDE { std::string res; for(std::string::size_type i = 0; i < q.length(); i++) diff --git a/src/modules/m_abbreviation.cpp b/src/modules/m_abbreviation.cpp index 85709080f..2a38bd3a6 100644 --- a/src/modules/m_abbreviation.cpp +++ b/src/modules/m_abbreviation.cpp @@ -22,7 +22,7 @@ class ModuleAbbreviation : public Module { public: - void Prioritize() + void Prioritize() CXX11_OVERRIDE { ServerInstance->Modules->SetPriority(this, I_OnPreCommand, PRIORITY_FIRST); } diff --git a/src/modules/m_alias.cpp b/src/modules/m_alias.cpp index c6e53f0cf..e99d9dab5 100644 --- a/src/modules/m_alias.cpp +++ b/src/modules/m_alias.cpp @@ -352,7 +352,7 @@ class ModuleAlias : public Module ServerInstance->Parser.CallHandler(command, pars, user); } - void Prioritize() + void Prioritize() CXX11_OVERRIDE { // Prioritise after spanningtree so that channel aliases show the alias before the effects. Module* linkmod = ServerInstance->Modules->Find("m_spanningtree.so"); diff --git a/src/modules/m_bcrypt.cpp b/src/modules/m_bcrypt.cpp index 8a025a0d6..1698b0727 100644 --- a/src/modules/m_bcrypt.cpp +++ b/src/modules/m_bcrypt.cpp @@ -978,7 +978,7 @@ class ModuleBCrypt : public Module bcrypt.rounds = conf->getInt("rounds", 10, 1); } - Version GetVersion() + Version GetVersion() CXX11_OVERRIDE { return Version("Implements bcrypt hashing", VF_VENDOR); } diff --git a/src/modules/m_cgiirc.cpp b/src/modules/m_cgiirc.cpp index 09d6e5fdf..5eba5ce35 100644 --- a/src/modules/m_cgiirc.cpp +++ b/src/modules/m_cgiirc.cpp @@ -77,6 +77,7 @@ class CommandWebirc : public Command realhost("cgiirc_realhost", ExtensionItem::EXT_USER, Creator) , realip("cgiirc_realip", ExtensionItem::EXT_USER, Creator) { + allow_empty_last_param = false; works_before_reg = true; this->syntax = "password client hostname ip"; } @@ -85,6 +86,14 @@ class CommandWebirc : public Command if(user->registered == REG_ALL) return CMD_FAILURE; + irc::sockets::sockaddrs ipaddr; + if (!irc::sockets::aptosa(parameters[3], 0, ipaddr)) + { + IS_LOCAL(user)->CommandFloodPenalty += 5000; + ServerInstance->SNO->WriteGlobalSno('a', "Connecting user %s tried to use WEBIRC but gave an invalid IP address.", user->GetFullRealHost().c_str()); + return CMD_FAILURE; + } + for(CGIHostlist::iterator iter = Hosts.begin(); iter != Hosts.end(); iter++) { if(InspIRCd::Match(user->host, iter->hostmask, ascii_case_insensitive_map) || InspIRCd::MatchCIDR(user->GetIPString(), iter->hostmask, ascii_case_insensitive_map)) @@ -112,6 +121,7 @@ class CommandWebirc : public Command } } + IS_LOCAL(user)->CommandFloodPenalty += 5000; ServerInstance->SNO->WriteGlobalSno('w', "Connecting user %s tried to use WEBIRC, but didn't match any configured webirc blocks.", user->GetFullRealHost().c_str()); return CMD_FAILURE; } diff --git a/src/modules/m_clearchan.cpp b/src/modules/m_clearchan.cpp index 4142f81d1..1b4b8724a 100644 --- a/src/modules/m_clearchan.cpp +++ b/src/modules/m_clearchan.cpp @@ -150,7 +150,7 @@ class ModuleClearChan : public Module { } - void init() + void init() CXX11_OVERRIDE { // Only attached while we are working; don't react to events otherwise ServerInstance->Modules->DetachAll(this); diff --git a/src/modules/m_cloaking.cpp b/src/modules/m_cloaking.cpp index 890c799f2..cb3fdac1a 100644 --- a/src/modules/m_cloaking.cpp +++ b/src/modules/m_cloaking.cpp @@ -89,6 +89,10 @@ class CloakUser : public ModeHandler if (adding) { + // assume this is more correct + if (user->registered != REG_ALL && user->host != user->dhost) + return MODEACTION_DENY; + std::string* cloak = ext.get(user); if (!cloak) @@ -139,7 +143,6 @@ class ModuleCloaking : public Module std::string prefix; std::string suffix; std::string key; - const char* xtab[4]; dynamic_reference<HashProvider> Hash; ModuleCloaking() : cu(this), mode(MODE_OPAQUE), ck(this), Hash(this, "hash/md5") @@ -286,7 +289,7 @@ class ModuleCloaking : public Module return MOD_RES_PASSTHRU; } - void Prioritize() + void Prioritize() CXX11_OVERRIDE { /* Needs to be after m_banexception etc. */ ServerInstance->Modules->SetPriority(this, I_OnCheckBan, PRIORITY_LAST); @@ -343,11 +346,14 @@ class ModuleCloaking : public Module { std::string chost; + irc::sockets::sockaddrs hostip; + bool host_is_ip = irc::sockets::aptosa(host, ip.port(), hostip) && hostip == ip; + switch (mode) { case MODE_HALF_CLOAK: { - if (ipstr != host) + if (!host_is_ip) chost = prefix + SegmentCloak(host, 1, 6) + LastTwoDomainParts(host); if (chost.empty() || chost.length() > 50) chost = SegmentIP(ip, false); diff --git a/src/modules/m_conn_join.cpp b/src/modules/m_conn_join.cpp index b22dbdf4d..bd8d89dc9 100644 --- a/src/modules/m_conn_join.cpp +++ b/src/modules/m_conn_join.cpp @@ -78,7 +78,7 @@ class ModuleConnJoin : public Module defdelay = tag->getInt("delay", 0, 0, 60); } - void Prioritize() + void Prioritize() CXX11_OVERRIDE { ServerInstance->Modules->SetPriority(this, I_OnPostConnect, PRIORITY_LAST); } diff --git a/src/modules/m_conn_umodes.cpp b/src/modules/m_conn_umodes.cpp index 7a8d66ae7..0b708641e 100644 --- a/src/modules/m_conn_umodes.cpp +++ b/src/modules/m_conn_umodes.cpp @@ -25,7 +25,7 @@ class ModuleModesOnConnect : public Module { public: - void Prioritize() + void Prioritize() CXX11_OVERRIDE { // for things like +x on connect, important, otherwise we have to resort to config order (bleh) -- w00t ServerInstance->Modules->SetPriority(this, I_OnUserConnect, PRIORITY_FIRST); diff --git a/src/modules/m_connectban.cpp b/src/modules/m_connectban.cpp index fcb4b09ed..e0f9717c4 100644 --- a/src/modules/m_connectban.cpp +++ b/src/modules/m_connectban.cpp @@ -95,7 +95,7 @@ class ModuleConnectBan : public Module } } - void OnGarbageCollect() + void OnGarbageCollect() CXX11_OVERRIDE { ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Clearing map."); connects.clear(); diff --git a/src/modules/m_dnsbl.cpp b/src/modules/m_dnsbl.cpp index 73ecd02a6..752a0d7a5 100644 --- a/src/modules/m_dnsbl.cpp +++ b/src/modules/m_dnsbl.cpp @@ -70,6 +70,14 @@ class DNSBLResolver : public DNS::Request if (!ans_record) return; + // All replies should be in 127.0.0.0/8 + if (ans_record->rdata.compare(0, 4, "127.") != 0) + { + ServerInstance->SNO->WriteGlobalSno('a', "DNSBL: %s returned address outside of acceptable subnet 127.0.0.0/8: %s", ConfEntry->domain.c_str(), ans_record->rdata.c_str()); + ConfEntry->stats_misses++; + return; + } + int i = countExt.get(them); if (i) countExt.set(them, i - 1); @@ -175,7 +183,7 @@ class DNSBLResolver : public DNS::Request if (ServerInstance->XLines->AddLine(zl,NULL)) { std::string timestr = InspIRCd::TimeString(zl->expiry); - ServerInstance->SNO->WriteGlobalSno('x',"Z:line added due to DNSBL match on *@%s to expire on %s: %s", + ServerInstance->SNO->WriteGlobalSno('x',"Z:line added due to DNSBL match on %s to expire on %s: %s", them->GetIPString().c_str(), timestr.c_str(), reason.c_str()); ServerInstance->XLines->ApplyLines(); } diff --git a/src/modules/m_filter.cpp b/src/modules/m_filter.cpp index bd19a60ba..0badd1377 100644 --- a/src/modules/m_filter.cpp +++ b/src/modules/m_filter.cpp @@ -176,7 +176,7 @@ class ModuleFilter : public Module ExemptTargetSet exemptednicks; ModuleFilter(); - CullResult cull(); + CullResult cull() CXX11_OVERRIDE; ModResult OnUserPreMessage(User* user, void* dest, int target_type, std::string& text, char status, CUList& exempt_list, MessageType msgtype) CXX11_OVERRIDE; FilterResult* FilterMatch(User* user, const std::string &text, int flags); bool DeleteFilter(const std::string &freeform); diff --git a/src/modules/m_flashpolicyd.cpp b/src/modules/m_flashpolicyd.cpp index 8f847e111..38b7be73f 100644 --- a/src/modules/m_flashpolicyd.cpp +++ b/src/modules/m_flashpolicyd.cpp @@ -146,7 +146,7 @@ class ModuleFlashPD : public Module </cross-domain-policy>"; } - CullResult cull() + CullResult cull() CXX11_OVERRIDE { for (insp::intrusive_list<FlashPDSocket>::const_iterator i = sockets.begin(); i != sockets.end(); ++i) { diff --git a/src/modules/m_hostcycle.cpp b/src/modules/m_hostcycle.cpp index b33c101ef..621f06a27 100644 --- a/src/modules/m_hostcycle.cpp +++ b/src/modules/m_hostcycle.cpp @@ -40,6 +40,8 @@ class ModuleHostCycle : public Module FOREACH_MOD(OnBuildNeighborList, (user, include_chans, exceptions)); + // Users shouldn't see themselves quitting when host cycling + exceptions.erase(user); for (std::map<User*,bool>::iterator i = exceptions.begin(); i != exceptions.end(); ++i) { LocalUser* u = IS_LOCAL(i->first); diff --git a/src/modules/m_httpd.cpp b/src/modules/m_httpd.cpp index 6055d1f77..35ae9abe5 100644 --- a/src/modules/m_httpd.cpp +++ b/src/modules/m_httpd.cpp @@ -224,7 +224,7 @@ class HttpServerSocket : public BufferedSocket, public Timer, public insp::intru WriteData("\r\n"); } - void OnDataReady() + void OnDataReady() CXX11_OVERRIDE { if (InternalState == HTTP_SERVE_RECV_POSTDATA) { @@ -415,7 +415,7 @@ class ModuleHttpServer : public Module return MOD_RES_ALLOW; } - void OnUnloadModule(Module* mod) + void OnUnloadModule(Module* mod) CXX11_OVERRIDE { for (insp::intrusive_list<HttpServerSocket>::const_iterator i = sockets.begin(); i != sockets.end(); ) { diff --git a/src/modules/m_httpd_config.cpp b/src/modules/m_httpd_config.cpp index 6fd7f4050..11c82c031 100644 --- a/src/modules/m_httpd_config.cpp +++ b/src/modules/m_httpd_config.cpp @@ -81,8 +81,8 @@ class ModuleHttpConfig : public Module, public HTTPRequestEventListener for (ConfigDataHash::iterator x = ServerInstance->Config->config_data.begin(); x != ServerInstance->Config->config_data.end(); ++x) { data << "<" << x->first << " "; - ConfigTag* tag = x->second; - for (std::vector<KeyVal>::const_iterator j = tag->getItems().begin(); j != tag->getItems().end(); j++) + const ConfigItems& items = x->second->getItems(); + for (ConfigItems::const_iterator j = items.begin(); j != items.end(); j++) { data << Sanitize(j->first) << "="" << Sanitize(j->second) << "" "; } diff --git a/src/modules/m_httpd_stats.cpp b/src/modules/m_httpd_stats.cpp index 11fad4b18..62ae0c204 100644 --- a/src/modules/m_httpd_stats.cpp +++ b/src/modules/m_httpd_stats.cpp @@ -211,7 +211,7 @@ class ModuleHttpStats : public Module, public HTTPRequestEventListener data << "<server>"; data << "<servername>" << b->servername << "</servername>"; data << "<parentname>" << b->parentname << "</parentname>"; - data << "<gecos>" << b->gecos << "</gecos>"; + data << "<gecos>" << Sanitize(b->gecos) << "</gecos>"; data << "<usercount>" << b->usercount << "</usercount>"; // This is currently not implemented, so, commented out. // data << "<opercount>" << b->opercount << "</opercount>"; diff --git a/src/modules/m_ircv3.cpp b/src/modules/m_ircv3.cpp index 9e94e556d..543fb49a4 100644 --- a/src/modules/m_ircv3.cpp +++ b/src/modules/m_ircv3.cpp @@ -169,7 +169,7 @@ class ModuleIRCv3 : public Module, public AccountEventListener last_excepts.clear(); } - void Prioritize() + void Prioritize() CXX11_OVERRIDE { ServerInstance->Modules->SetPriority(this, I_OnUserJoin, PRIORITY_LAST); } diff --git a/src/modules/m_ldapauth.cpp b/src/modules/m_ldapauth.cpp index 7da63284a..fedf02b4d 100644 --- a/src/modules/m_ldapauth.cpp +++ b/src/modules/m_ldapauth.cpp @@ -406,9 +406,22 @@ public: return MOD_RES_DENY; } + std::string what; + std::string::size_type pos = user->password.find(':'); + if (pos != std::string::npos) + { + what = attribute + "=" + user->password.substr(0, pos); + + // Trim the user: prefix, leaving just 'pass' for later password check + user->password = user->password.substr(pos + 1); + } + else + { + what = attribute + "=" + (useusername ? user->ident : user->nick); + } + try { - std::string what = attribute + "=" + (useusername ? user->ident : user->nick); LDAP->BindAsManager(new AdminBindInterface(this, LDAP.GetProvider(), user->uuid, base, what)); } catch (LDAPException &ex) diff --git a/src/modules/m_md5.cpp b/src/modules/m_md5.cpp index 6cec05a18..26ff4cffc 100644 --- a/src/modules/m_md5.cpp +++ b/src/modules/m_md5.cpp @@ -61,23 +61,13 @@ class MD5Provider : public HashProvider } while (--words); } - void MD5Init(MD5Context *ctx, unsigned int* ikey = NULL) + void MD5Init(MD5Context *ctx) { /* These are the defaults for md5 */ - if (!ikey) - { - ctx->buf[0] = 0x67452301; - ctx->buf[1] = 0xefcdab89; - ctx->buf[2] = 0x98badcfe; - ctx->buf[3] = 0x10325476; - } - else - { - ctx->buf[0] = ikey[0]; - ctx->buf[1] = ikey[1]; - ctx->buf[2] = ikey[2]; - ctx->buf[3] = ikey[3]; - } + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; ctx->bytes[0] = 0; ctx->bytes[1] = 0; @@ -236,10 +226,10 @@ class MD5Provider : public HashProvider } - void MyMD5(void *dest, void *orig, int len, unsigned int* ikey) + void MyMD5(void *dest, void *orig, int len) { MD5Context context; - MD5Init(&context, ikey); + MD5Init(&context); MD5Update(&context, (const unsigned char*)orig, len); MD5Final((unsigned char*)dest, &context); } @@ -248,7 +238,7 @@ class MD5Provider : public HashProvider std::string GenerateRaw(const std::string& data) { char res[16]; - MyMD5(res, (void*)data.data(), data.length(), NULL); + MyMD5(res, (void*)data.data(), data.length()); return std::string(res, 16); } diff --git a/src/modules/m_messageflood.cpp b/src/modules/m_messageflood.cpp index 46df977a5..9d119b6c3 100644 --- a/src/modules/m_messageflood.cpp +++ b/src/modules/m_messageflood.cpp @@ -155,7 +155,7 @@ class ModuleMsgFlood : public Module return MOD_RES_PASSTHRU; } - void Prioritize() + void Prioritize() CXX11_OVERRIDE { // we want to be after all modules that might deny the message (e.g. m_muteban, m_noctcp, m_blockcolor, etc.) ServerInstance->Modules->SetPriority(this, I_OnUserPreMessage, PRIORITY_LAST); diff --git a/src/modules/m_mlock.cpp b/src/modules/m_mlock.cpp index d3ab5b9fd..2a0410bed 100644 --- a/src/modules/m_mlock.cpp +++ b/src/modules/m_mlock.cpp @@ -34,7 +34,7 @@ class ModuleMLock : public Module return Version("Implements the ability to have server-side MLOCK enforcement.", VF_VENDOR); } - ModResult OnRawMode(User* source, Channel* channel, ModeHandler* mh, const std::string& parameter, bool adding) + ModResult OnRawMode(User* source, Channel* channel, ModeHandler* mh, const std::string& parameter, bool adding) CXX11_OVERRIDE { if (!channel) return MOD_RES_PASSTHRU; diff --git a/src/modules/m_namedmodes.cpp b/src/modules/m_namedmodes.cpp index 7a86c9e3c..7f2687d66 100644 --- a/src/modules/m_namedmodes.cpp +++ b/src/modules/m_namedmodes.cpp @@ -124,7 +124,7 @@ class ModuleNamedModes : public Module return Version("Provides the ability to manipulate modes via long names.",VF_VENDOR); } - void Prioritize() + void Prioritize() CXX11_OVERRIDE { ServerInstance->Modules->SetPriority(this, I_OnPreMode, PRIORITY_FIRST); } diff --git a/src/modules/m_nicklock.cpp b/src/modules/m_nicklock.cpp index 35845c8d8..6e22a69bb 100644 --- a/src/modules/m_nicklock.cpp +++ b/src/modules/m_nicklock.cpp @@ -157,7 +157,7 @@ class ModuleNickLock : public Module return MOD_RES_PASSTHRU; } - void Prioritize() + void Prioritize() CXX11_OVERRIDE { Module *nflood = ServerInstance->Modules->Find("m_nickflood.so"); ServerInstance->Modules->SetPriority(this, I_OnUserPreNick, PRIORITY_BEFORE, nflood); diff --git a/src/modules/m_ojoin.cpp b/src/modules/m_ojoin.cpp index 9465a51e5..76e66bdc2 100644 --- a/src/modules/m_ojoin.cpp +++ b/src/modules/m_ojoin.cpp @@ -150,7 +150,7 @@ class ModuleOjoin : public Module return MOD_RES_DENY; } - void Prioritize() + void Prioritize() CXX11_OVERRIDE { ServerInstance->Modules->SetPriority(this, I_OnUserPreJoin, PRIORITY_FIRST); } diff --git a/src/modules/m_operprefix.cpp b/src/modules/m_operprefix.cpp index d66f99450..b355047ee 100644 --- a/src/modules/m_operprefix.cpp +++ b/src/modules/m_operprefix.cpp @@ -72,7 +72,7 @@ class ModuleOperPrefixMode : public Module return MOD_RES_PASSTHRU; } - void OnPostJoin(Membership* memb) + void OnPostJoin(Membership* memb) CXX11_OVERRIDE { if ((!IS_LOCAL(memb->user)) || (!memb->user->IsOper()) || (memb->user->IsModeSet(hideopermode))) return; @@ -105,7 +105,7 @@ class ModuleOperPrefixMode : public Module return Version("Gives opers cmode +y which provides a staff prefix.", VF_VENDOR); } - void Prioritize() + void Prioritize() CXX11_OVERRIDE { // m_opermodes may set +H on the oper to hide him, we don't want to set the oper prefix in that case Module* opermodes = ServerInstance->Modules->Find("m_opermodes.so"); diff --git a/src/modules/m_override.cpp b/src/modules/m_override.cpp index 9cfc3aed0..fd09dd6ec 100644 --- a/src/modules/m_override.cpp +++ b/src/modules/m_override.cpp @@ -121,7 +121,8 @@ class ModuleOverride : public Module if (source->IsOper() && CanOverride(source,"KICK")) { // If the kicker's status is less than the target's, or the kicker's status is less than or equal to voice - if ((memb->chan->GetPrefixValue(source) < memb->getRank()) || (memb->chan->GetPrefixValue(source) <= VOICE_VALUE)) + if ((memb->chan->GetPrefixValue(source) < memb->getRank()) || (memb->chan->GetPrefixValue(source) <= VOICE_VALUE) || + (memb->chan->GetPrefixValue(source) == HALFOP_VALUE && memb->getRank() == HALFOP_VALUE)) { ServerInstance->SNO->WriteGlobalSno('v',source->nick+" used oper override to kick "+memb->user->nick+" on "+memb->chan->name+" ("+reason+")"); return MOD_RES_ALLOW; diff --git a/src/modules/m_permchannels.cpp b/src/modules/m_permchannels.cpp index 9e77bd60e..0f2a2ef6f 100644 --- a/src/modules/m_permchannels.cpp +++ b/src/modules/m_permchannels.cpp @@ -244,6 +244,10 @@ public: mode->OnModeChange(ServerInstance->FakeClient, ServerInstance->FakeClient, c, par, true); } } + + // We always apply the permchannels mode to permanent channels. + par.clear(); + p.OnModeChange(ServerInstance->FakeClient, ServerInstance->FakeClient, c, par, true); } } } @@ -269,7 +273,7 @@ public: dirty = false; } - void Prioritize() + void Prioritize() CXX11_OVERRIDE { // XXX: Load the DB here because the order in which modules are init()ed at boot is // alphabetical, this means we must wait until all modules have done their init() diff --git a/src/modules/m_rline.cpp b/src/modules/m_rline.cpp index 97fbf169a..e77a00b6d 100644 --- a/src/modules/m_rline.cpp +++ b/src/modules/m_rline.cpp @@ -333,7 +333,7 @@ class ModuleRLine : public Module } } - void Prioritize() + void Prioritize() CXX11_OVERRIDE { Module* mod = ServerInstance->Modules->Find("m_cgiirc.so"); ServerInstance->Modules->SetPriority(this, I_OnUserRegister, PRIORITY_AFTER, mod); diff --git a/src/modules/m_samode.cpp b/src/modules/m_samode.cpp index 6288f5862..394cea722 100644 --- a/src/modules/m_samode.cpp +++ b/src/modules/m_samode.cpp @@ -96,7 +96,7 @@ class ModuleSaMode : public Module return MOD_RES_PASSTHRU; } - void Prioritize() + void Prioritize() CXX11_OVERRIDE { Module *override = ServerInstance->Modules->Find("m_override.so"); ServerInstance->Modules->SetPriority(this, I_OnPreMode, PRIORITY_BEFORE, override); diff --git a/src/modules/m_sasl.cpp b/src/modules/m_sasl.cpp index 2b247a198..6ad9d77b7 100644 --- a/src/modules/m_sasl.cpp +++ b/src/modules/m_sasl.cpp @@ -153,10 +153,63 @@ class SaslAuthenticator SaslResult result; bool state_announced; + /* taken from m_services_account */ + static bool ReadCGIIRCExt(const char* extname, User* user, 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; + } + + + void SendHostIP() + { + std::string host, ip; + + if (!ReadCGIIRCExt("cgiirc_webirc_hostname", user, host)) + { + host = user->host; + } + if (!ReadCGIIRCExt("cgiirc_webirc_ip", user, ip)) + { + ip = user->GetIPString(); + } + else + { + /* IP addresses starting with a : on irc are a Bad Thing (tm) */ + if (ip.c_str()[0] == ':') + ip.insert(ip.begin(),1,'0'); + } + + parameterlist params; + params.push_back(sasl_target); + params.push_back("SASL"); + params.push_back(user->uuid); + params.push_back("*"); + params.push_back("H"); + params.push_back(host); + params.push_back(ip); + + SendSASL(params); + } + public: SaslAuthenticator(User* user_, const std::string& method) : user(user_), state(SASL_INIT), state_announced(false) { + SendHostIP(); + parameterlist params; params.push_back(user->uuid); params.push_back("*"); @@ -164,7 +217,7 @@ class SaslAuthenticator params.push_back(method); LocalUser* localuser = IS_LOCAL(user); - if (method == "EXTERNAL" && localuser) + if (localuser) { std::string fp = SSLClientCert::GetFingerprint(&localuser->eh); @@ -287,6 +340,7 @@ class CommandAuthenticate : public Command : Command(Creator, "AUTHENTICATE", 1), authExt(ext), cap(Cap) { works_before_reg = true; + allow_empty_last_param = false; } CmdResult Handle (const std::vector<std::string>& parameters, User *user) @@ -295,6 +349,9 @@ class CommandAuthenticate : public Command if (!cap.get(user)) return CMD_FAILURE; + if (parameters[0].find(' ') != std::string::npos || parameters[0][0] == ':') + return CMD_FAILURE; + SaslAuthenticator *sasl = authExt.get(user); if (!sasl) authExt.set(user, new SaslAuthenticator(user, parameters[0])); @@ -378,7 +435,7 @@ class ModuleSASL : public Module servertracker.Reset(); } - ModResult OnUserRegister(LocalUser *user) CXX11_OVERRIDE + void OnUserConnect(LocalUser *user) CXX11_OVERRIDE { SaslAuthenticator *sasl_ = authExt.get(user); if (sasl_) @@ -386,8 +443,6 @@ class ModuleSASL : public Module sasl_->Abort(); authExt.unset(user); } - - return MOD_RES_PASSTHRU; } void OnDecodeMetaData(Extensible* target, const std::string& extname, const std::string& extdata) CXX11_OVERRIDE diff --git a/src/modules/m_sha1.cpp b/src/modules/m_sha1.cpp index 5926e4926..798539d91 100644 --- a/src/modules/m_sha1.cpp +++ b/src/modules/m_sha1.cpp @@ -190,7 +190,7 @@ class ModuleSHA1 : public Module big_endian = (htonl(1337) == 1337); } - Version GetVersion() + Version GetVersion() CXX11_OVERRIDE { return Version("Implements SHA-1 hashing", VF_VENDOR); } diff --git a/src/modules/m_shun.cpp b/src/modules/m_shun.cpp index 022726524..28faf898b 100644 --- a/src/modules/m_shun.cpp +++ b/src/modules/m_shun.cpp @@ -191,7 +191,7 @@ class ModuleShun : public Module ServerInstance->XLines->UnregisterFactory(&f); } - void Prioritize() + void Prioritize() CXX11_OVERRIDE { Module* alias = ServerInstance->Modules->Find("m_alias.so"); ServerInstance->Modules->SetPriority(this, I_OnPreCommand, PRIORITY_BEFORE, alias); diff --git a/src/modules/m_spanningtree/main.h b/src/modules/m_spanningtree/main.h index 46c21b4e9..00cbd3dcd 100644 --- a/src/modules/m_spanningtree/main.h +++ b/src/modules/m_spanningtree/main.h @@ -168,8 +168,8 @@ class ModuleSpanningTree : public Module void OnUnloadModule(Module* mod) CXX11_OVERRIDE; ModResult OnAcceptConnection(int newsock, ListenSocket* from, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server) CXX11_OVERRIDE; void OnMode(User* source, User* u, Channel* c, const Modes::ChangeList& modes, ModeParser::ModeProcessFlag processflags, const std::string& output_mode) CXX11_OVERRIDE; - CullResult cull(); + CullResult cull() CXX11_OVERRIDE; ~ModuleSpanningTree(); Version GetVersion() CXX11_OVERRIDE; - void Prioritize(); + void Prioritize() CXX11_OVERRIDE; }; diff --git a/src/modules/m_spanningtree/protocolinterface.h b/src/modules/m_spanningtree/protocolinterface.h index e7fed5475..b0609005c 100644 --- a/src/modules/m_spanningtree/protocolinterface.h +++ b/src/modules/m_spanningtree/protocolinterface.h @@ -37,7 +37,7 @@ class SpanningTreeProtocolInterface : public ProtocolInterface void SendMetaData(Channel* chan, const std::string& key, const std::string& data) CXX11_OVERRIDE; void SendMetaData(const std::string& key, const std::string& data) CXX11_OVERRIDE; void SendSNONotice(char snomask, const std::string& text) CXX11_OVERRIDE; - void SendMessage(Channel* target, char status, const std::string& text, MessageType msgtype); - void SendMessage(User* target, const std::string& text, MessageType msgtype); - void GetServerList(ServerList& sl); + void SendMessage(Channel* target, char status, const std::string& text, MessageType msgtype) CXX11_OVERRIDE; + void SendMessage(User* target, const std::string& text, MessageType msgtype) CXX11_OVERRIDE; + void GetServerList(ServerList& sl) CXX11_OVERRIDE; }; diff --git a/src/modules/m_spanningtree/servercommand.h b/src/modules/m_spanningtree/servercommand.h index 07dfc4898..ee7766764 100644 --- a/src/modules/m_spanningtree/servercommand.h +++ b/src/modules/m_spanningtree/servercommand.h @@ -43,7 +43,7 @@ class ServerCommand : public CommandBase void RegisterService() CXX11_OVERRIDE; virtual CmdResult Handle(User* user, std::vector<std::string>& parameters) = 0; - virtual RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters); + virtual RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) CXX11_OVERRIDE; /** * Extract the TS from a string. diff --git a/src/modules/m_spanningtree/treeserver.h b/src/modules/m_spanningtree/treeserver.h index b7e9ee9d9..f75adf54c 100644 --- a/src/modules/m_spanningtree/treeserver.h +++ b/src/modules/m_spanningtree/treeserver.h @@ -219,7 +219,7 @@ class TreeServer : public Server */ void OnPong() { pingtimer.OnPong(); } - CullResult cull(); + CullResult cull() CXX11_OVERRIDE; /** Destructor, deletes ServerUser unless IsRoot() */ diff --git a/src/modules/m_spanningtree/treesocket.h b/src/modules/m_spanningtree/treesocket.h index 4887623c1..3571f2816 100644 --- a/src/modules/m_spanningtree/treesocket.h +++ b/src/modules/m_spanningtree/treesocket.h @@ -200,7 +200,7 @@ class TreeSocket : public BufferedSocket */ void CleanNegotiationInfo(); - CullResult cull(); + CullResult cull() CXX11_OVERRIDE; /** Destructor */ ~TreeSocket(); @@ -216,7 +216,7 @@ class TreeSocket : public BufferedSocket * to server docs on the inspircd.org site, the other side * will then send back its own server string. */ - void OnConnected(); + void OnConnected() CXX11_OVERRIDE; /** Handle socket error event */ @@ -270,7 +270,7 @@ class TreeSocket : public BufferedSocket /** This function is called when we receive data from a remote * server. */ - void OnDataReady(); + void OnDataReady() CXX11_OVERRIDE; /** Send one or more complete lines down the socket */ @@ -299,10 +299,10 @@ class TreeSocket : public BufferedSocket /** Handle socket timeout from connect() */ - void OnTimeout(); + void OnTimeout() CXX11_OVERRIDE; /** Handle server quit on close */ - void Close(); + void Close() CXX11_OVERRIDE; /** Fixes messages coming from old servers so the new command handlers understand them */ diff --git a/src/modules/m_spanningtree/utils.h b/src/modules/m_spanningtree/utils.h index a2f7212f6..f262f9a48 100644 --- a/src/modules/m_spanningtree/utils.h +++ b/src/modules/m_spanningtree/utils.h @@ -108,7 +108,7 @@ class SpanningTreeUtilities : public classbase /** Prepare for class destruction */ - CullResult cull(); + CullResult cull() CXX11_OVERRIDE; /** Destroy class and free listeners etc */ diff --git a/src/modules/m_timedbans.cpp b/src/modules/m_timedbans.cpp index 874e6440f..44c6c4c4f 100644 --- a/src/modules/m_timedbans.cpp +++ b/src/modules/m_timedbans.cpp @@ -218,7 +218,7 @@ class ModuleTimedBans : public Module } } - void OnChannelDelete(Channel* chan) + void OnChannelDelete(Channel* chan) CXX11_OVERRIDE { // Remove all timed bans affecting the channel from internal bookkeeping TimedBanList.erase(std::remove_if(TimedBanList.begin(), TimedBanList.end(), ChannelMatcher(chan)), TimedBanList.end()); diff --git a/src/server.cpp b/src/server.cpp index 2feb08f96..6782187fe 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -171,7 +171,6 @@ void ISupportManager::Build() tokens["CHANTYPES"] = "#"; tokens["ELIST"] = "MU"; tokens["KICKLEN"] = ConvToStr(ServerInstance->Config->Limits.MaxKick); - tokens["MAXBANS"] = "64"; // TODO: make this a config setting. tokens["MAXTARGETS"] = ConvToStr(ServerInstance->Config->MaxTargets); tokens["MODES"] = ConvToStr(ServerInstance->Config->Limits.MaxModes); tokens["NETWORK"] = ServerInstance->Config->Network; diff --git a/src/socketengine.cpp b/src/socketengine.cpp index 4183488b7..3735e7530 100644 --- a/src/socketengine.cpp +++ b/src/socketengine.cpp @@ -203,40 +203,35 @@ void SocketEngine::SetReuse(int fd) int SocketEngine::RecvFrom(EventHandler* fd, void *buf, size_t len, int flags, sockaddr *from, socklen_t *fromlen) { int nbRecvd = recvfrom(fd->GetFd(), (char*)buf, len, flags, from, fromlen); - if (nbRecvd > 0) - stats.Update(nbRecvd, 0); + stats.UpdateReadCounters(nbRecvd); return nbRecvd; } int SocketEngine::Send(EventHandler* fd, const void *buf, size_t len, int flags) { int nbSent = send(fd->GetFd(), (const char*)buf, len, flags); - if (nbSent > 0) - stats.Update(0, nbSent); + stats.UpdateWriteCounters(nbSent); return nbSent; } int SocketEngine::Recv(EventHandler* fd, void *buf, size_t len, int flags) { int nbRecvd = recv(fd->GetFd(), (char*)buf, len, flags); - if (nbRecvd > 0) - stats.Update(nbRecvd, 0); + stats.UpdateReadCounters(nbRecvd); return nbRecvd; } int SocketEngine::SendTo(EventHandler* fd, const void *buf, size_t len, int flags, const sockaddr *to, socklen_t tolen) { int nbSent = sendto(fd->GetFd(), (const char*)buf, len, flags, to, tolen); - if (nbSent > 0) - stats.Update(0, nbSent); + stats.UpdateWriteCounters(nbSent); return nbSent; } int SocketEngine::WriteV(EventHandler* fd, const IOVector* iovec, int count) { int sent = writev(fd->GetFd(), iovec, count); - if (sent > 0) - stats.Update(0, sent); + stats.UpdateWriteCounters(sent); return sent; } @@ -289,11 +284,26 @@ int SocketEngine::Shutdown(int fd, int how) return shutdown(fd, how); } -void SocketEngine::Statistics::Update(size_t len_in, size_t len_out) +void SocketEngine::Statistics::UpdateReadCounters(int len_in) { CheckFlush(); - indata += len_in; - outdata += len_out; + + ReadEvents++; + if (len_in > 0) + indata += len_in; + else if (len_in < 0) + ErrorEvents++; +} + +void SocketEngine::Statistics::UpdateWriteCounters(int len_out) +{ + CheckFlush(); + + WriteEvents++; + if (len_out > 0) + outdata += len_out; + else if (len_out < 0) + ErrorEvents++; } void SocketEngine::Statistics::CheckFlush() const diff --git a/src/socketengines/socketengine_epoll.cpp b/src/socketengines/socketengine_epoll.cpp index 7602dd201..c442e340d 100644 --- a/src/socketengines/socketengine_epoll.cpp +++ b/src/socketengines/socketengine_epoll.cpp @@ -22,7 +22,7 @@ #include "exitcodes.h" #include <sys/epoll.h> -#include <ulimit.h> +#include <sys/resource.h> #include <iostream> /** A specialisation of the SocketEngine class, designed to use linux 2.6 epoll(). @@ -38,8 +38,12 @@ namespace void SocketEngine::Init() { - // MAX_DESCRIPTORS is mainly used for display purposes, no problem if ulimit() fails and returns a negative number - MAX_DESCRIPTORS = ulimit(4, 0); + // MAX_DESCRIPTORS is mainly used for display purposes, no problem if getrlimit() fails + struct rlimit limit; + if (!getrlimit(RLIMIT_NOFILE, &limit)) + { + MAX_DESCRIPTORS = limit.rlim_cur; + } // 128 is not a maximum, just a hint at the eventual number of sockets that may be polled, // and it is completely ignored by 2.6.8 and later kernels, except it must be larger than zero. @@ -213,7 +217,6 @@ int SocketEngine::DispatchEvents() eh->SetEventMask(mask); if (ev.events & EPOLLIN) { - stats.ReadEvents++; eh->OnEventHandlerRead(); if (eh != GetRef(fd)) // whoa! we got deleted, better not give out the write event @@ -221,7 +224,6 @@ int SocketEngine::DispatchEvents() } if (ev.events & EPOLLOUT) { - stats.WriteEvents++; eh->OnEventHandlerWrite(); } } diff --git a/src/socketengines/socketengine_kqueue.cpp b/src/socketengines/socketengine_kqueue.cpp index 922cb7f2d..9db902314 100644 --- a/src/socketengines/socketengine_kqueue.cpp +++ b/src/socketengines/socketengine_kqueue.cpp @@ -199,7 +199,6 @@ int SocketEngine::DispatchEvents() } if (filter == EVFILT_WRITE) { - stats.WriteEvents++; /* When mask is FD_WANT_FAST_WRITE or FD_WANT_SINGLE_WRITE, * we set a one-shot write, so we need to clear that bit * to detect when it set again. @@ -210,7 +209,6 @@ int SocketEngine::DispatchEvents() } else if (filter == EVFILT_READ) { - stats.ReadEvents++; eh->SetEventMask(eh->GetEventMask() & ~FD_READ_WILL_BLOCK); eh->OnEventHandlerRead(); } diff --git a/src/socketengines/socketengine_ports.cpp b/src/socketengines/socketengine_ports.cpp index d94d02664..68fa70e3b 100644 --- a/src/socketengines/socketengine_ports.cpp +++ b/src/socketengines/socketengine_ports.cpp @@ -159,14 +159,12 @@ int SocketEngine::DispatchEvents() port_associate(EngineHandle, PORT_SOURCE_FD, fd, mask_to_events(mask), eh); if (portev_events & POLLRDNORM) { - stats.ReadEvents++; eh->OnEventHandlerRead(); if (eh != GetRef(fd)) continue; } if (portev_events & POLLWRNORM) { - stats.WriteEvents++; eh->OnEventHandlerWrite(); } } diff --git a/src/socketengines/socketengine_select.cpp b/src/socketengines/socketengine_select.cpp index 6dfbae88e..42f634db1 100644 --- a/src/socketengines/socketengine_select.cpp +++ b/src/socketengines/socketengine_select.cpp @@ -147,7 +147,6 @@ int SocketEngine::DispatchEvents() if (has_read) { - stats.ReadEvents++; ev->SetEventMask(ev->GetEventMask() & ~FD_READ_WILL_BLOCK); ev->OnEventHandlerRead(); if (ev != GetRef(i)) @@ -156,7 +155,6 @@ int SocketEngine::DispatchEvents() if (has_write) { - stats.WriteEvents++; int newmask = (ev->GetEventMask() & ~(FD_WRITE_WILL_BLOCK | FD_WANT_SINGLE_WRITE)); SocketEngine::OnSetEvent(ev, ev->GetEventMask(), newmask); ev->SetEventMask(newmask); diff --git a/src/users.cpp b/src/users.cpp index bdcc9edd0..d54931644 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -588,6 +588,7 @@ void LocalUser::FullConnect() void User::InvalidateCache() { /* Invalidate cache */ + cachedip.clear(); cached_fullhost.clear(); cached_hostip.clear(); cached_makehost.clear(); @@ -709,8 +710,7 @@ irc::sockets::cidr_mask User::GetCIDRMask() bool User::SetClientIP(const char* sip, bool recheck_eline) { - cachedip.clear(); - cached_hostip.clear(); + this->InvalidateCache(); return irc::sockets::aptosa(sip, 0, client_sa); } diff --git a/tools/genssl b/tools/genssl index 189311c1a..e4d5bf1f4 100755 --- a/tools/genssl +++ b/tools/genssl @@ -119,6 +119,7 @@ __GNUTLS_END__ close($tmp); $status ||= system "$certtool --generate-privkey $sec_param --outfile key.pem"; $status ||= system "$certtool --generate-self-signed --load-privkey key.pem --outfile cert.pem --template $tmp"; + $status ||= system "$certtool --generate-request --load-privkey key.pem --outfile csr.pem --template $tmp"; $status ||= system "$certtool --generate-dh-params $sec_param --outfile dhparams.pem"; $dercert = `$certtool --certificate-info --infile cert.pem --outder` unless $status; } elsif ($tool eq 'openssl') { @@ -131,9 +132,12 @@ $organization $unit $common_name $email +. +$organization __OPENSSL_END__ close($tmp); $status ||= system "cat $tmp | openssl req -x509 -nodes -newkey rsa:2048 -keyout key.pem -out cert.pem -days $days 2>/dev/null"; + $status ||= system "cat $tmp | openssl req -new -nodes -key key.pem -out csr.pem 2>/dev/null"; $status ||= system 'openssl dhparam -out dhparams.pem 2048'; $dercert = `openssl x509 -in cert.pem -outform DER` unless $status; } @@ -147,6 +151,6 @@ if (defined $dercert && eval 'use Digest::SHA; 1') { my $hash = Digest::SHA->new(256); $hash->add($dercert); say ''; - say 'Add this TLSA record to your domain for DANE support:'; + say 'If you are using the self-signed certificate then add this TLSA record to your domain for DANE support:'; say "_6697._tcp." . $common_name . " TLSA 3 0 1 " . $hash->hexdigest; } diff --git a/win/CMakeLists.txt b/win/CMakeLists.txt index 768270696..b5812b0c2 100644 --- a/win/CMakeLists.txt +++ b/win/CMakeLists.txt @@ -89,6 +89,7 @@ file(MAKE_DIRECTORY ${LOG_DIR}) install(DIRECTORY ${LOG_DIR} DESTINATION .) if(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake") + set(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION ".") # place runtime libraries next to InspIRCd binary include(InstallRequiredSystemLibraries) set(CPACK_PACKAGE_NAME "InspIRCd IRC Daemon") |